Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Range Requests

Some LSP requests, such as semantic tokens, support ranges, meaning you should request information for a specific range of the document instead of the whole document.

To support this, you can use the get_ast method from the default crate to get the AST of a file.

Since the nodes are sorted by position, it is possible to iterate over the AST and perform operations only on a portion of the AST that contains the range.

Example: Semantic tokens for a range

pub fn semantic_tokens_range(
    db: &impl BaseDatabase,
    params: SemanticTokensRangeParams,
) -> anyhow::Result<Option<SemanticTokensResult>> {
    // Get the file in DB
    let uri = params.text_document.uri;

    let file = db
        .get_file(&uri)
        .ok_or_else(|| anyhow::format_err!("File not found in workspace"))?;

    let mut builder = SemanticTokensBuilder::new("".into());

    // Iterate over the AST
    for node in get_ast(db, file).iter() {
        // Skip nodes that are before the range
        if node.get_lsp_range().end <= params.range.start {
            continue;
        }
        // Stop at nodes that are after the range
        if node.get_lsp_range().start >= params.range.end {
            break;
        }
        // Dispatch on the node
        dispatch!(node.lower(),
            [
                FunctionDefinition => build_semantic_tokens(db, file, &mut builder)
            ]
        );
    }

    Ok(Some(SemanticTokensResult::Tokens(builder.build())))
}