auto-lsp 0.6.2

A rust crate for creating AST and LSP servers powered by tree-sitter.
Documentation
# Building an AST

The generated AST includes:

- Structs representing AST nodes.
- Implementations of the AstNode trait.
- A TryFrom implementation to build nodes from Tree-sitter.

Building an AST requires a `salsa::Database`, which is used to accumulate errors during parsing.

## Using TryFrom

Each AST node type provides a `TryFrom` implementation that accepts a `TryFromParams` tuple. This is used to convert a Tree-sitter node into an AST node.

```rust, ignore
/// Parameters passed to `TryFrom` implementations for AST nodes.
pub type TryFromParams<'from> = (
    &'from Node<'from>,         // Tree-sitter node
    &'from dyn salsa::Database, // Salsa database
    &'from mut Builder,         // AST builder
    usize,                      // Node ID (auto-incremented by the builder)
    Option<usize>,              // Optional parent node ID
);
```

### Example: Building a root node

```rust, ignore
// Create the AST builder
let mut builder = auto_lsp::core::ast::Builder::default();

// Build the root node from the Tree-sitter parse tree
let root = ast::generated::SourceFile::try_from((
    &tree.root_node(),
    db,            // Your salsa database
    &mut builder,
    0,             // Root node ID
    None,          // Root has no parent
))?;

// Retrieve all non-root nodes from the builder
let mut nodes = builder.take_nodes();

// Add the root node manually
nodes.push(std::sync::Arc::new(root));

// Optional: Sort the nodes by ID
nodes.sort_unstable();
```

## Retrieving Errors

Errors that occur during AST construction are accumulated using the `ParseErrorAccumulator` struct. This allows partial AST construction even when some nodes fail to parse.

It’s recommended to use `TryFrom` inside a `salsa::tracked` function so you can retrieve errors using `salsa::accumulated`.

The default crate provides a `get_ast` query that builds the AST and collects errors. It is compatible with `BaseDatabase`.

### ParseError Structure

The `ParseError` enum represents errors that can be encountered during parsing.

```rust, ignore
#[derive(Error, Clone, Debug, PartialEq, Eq)]
pub enum ParseError {
    #[error("{error:?}")]
    LexerError {
        range: lsp_types::Range,
        #[source]
        error: LexerError,
    },
    #[error("{error:?}")]
    AstError {
        range: lsp_types::Range,
        #[source]
        error: AstError,
    },
}
```

- LexerError — Issues from Tree-sitter's lexer
- AstError — Issues from a TryFrom implementation

You can retrieve lexer errors via get_tree_sitter_errors() from the `default` crate.

`LexerError` can either be a missing symbol error or a syntax error.

```rust, ignore
#[derive(Error, Clone, Debug, PartialEq, Eq)]
pub enum LexerError {
    #[error("{error:?}")]
    Missing {
        range: lsp_types::Range,
        error: String,
    },
    #[error("{error:?}")]
    Syntax {
        range: lsp_types::Range,
        error: String,
    },
}
```

## ParsedAst struct

The result of `get_ast` is a `ParsedAst` struct, which holds the list of AST nodes and implements `Deref` for direct iteration.

```rust, ignore
pub struct ParsedAst {
    pub nodes: Arc<Vec<Arc<dyn AstNode>>>,
}
```

You can work with AST nodes in two ways:
- Downcast a node to a concrete type and access its fields.
- Iterate over all nodes and filter or match on their type.

### Methods

 - `get_root`: Returns the root node.
 - `descendant_at`: Returns the first node that contains the given offset.

### Example: Filtering nodes by type

```rust, ignore
let functions = get_ast(db file)
    .iter()
    .filter_map(|node| node.is::<FunctionDefinition>())
    .collect();
```

For convenience when calling methods on multiple node types, use the `dispatch` or `dispatch_once` macros.
See [Dispatch Pattern](../patterns/dispatch.md).