Question: How do we use the code graph for autocomplete context?

To use the code graph for autocomplete context, we follow a multi-step process. We will use the LSP-based retriever (LspLightRetriever) as an example to illustrate how it works.

1. Selection of context retrieval method

The DefaultContextStrategyFactory selects the appropriate context retrieval strategy based on the given document and context strategy. In our example, it selects LspLightRetriever when the context strategy is set to lsp-light. There are a few methods here, but we'll focus on LSP to see how it works.

File: context-strategy.ts

export class DefaultContextStrategyFactory implements ContextStrategyFactory {
    constructor(private contextStrategy: ContextStrategy, createBfgRetriever?: () => BfgRetriever) {
        switch (contextStrategy) {
            // Other cases...
            case 'lsp-light':
                this.localRetriever = new JaccardSimilarityRetriever();
                this.graphRetriever = new LspLightRetriever();
                this.disposables.push(this.localRetriever, this.graphRetriever);
                break;
        }
    }
}

2. Extracting symbols

Defining the range and executing the query

The function getLastNGraphContextIdentifiersFromDocument in identifiers.ts defines the range and extracts symbols from a specified range in the document.

File: identifiers.ts

export function getLastNGraphContextIdentifiersFromDocument(params: GetLastNGraphContextIdentifiersFromDocumentParams): SymbolRequest[] {
    const { document, position, n } = params;

    // Define the range for symbol extraction (last 100 lines to the current position)
    const queryPoints = {
        startPoint: asPoint({ line: Math.max(position.line - 100, 0), character: 0 }),
        endPoint: asPoint({ line: position.line, character: position.character + 1 }),
    };

    // Execute the query to get identifiers
    return execQueryWrapper({ document, queryPoints, queryWrapper: 'getGraphContextIdentifiers' })
        .map(identifier => ({
            uri: document.uri,
            languageId: document.languageId,
            nodeType: identifier.node.type,
            symbolName: identifier.node.text,
            position: new vscode.Position(identifier.node.startPosition.row, identifier.node.startPosition.column),
        }))
        .sort((a, b) => (a.position.isBefore(b.position) ? 1 : -1))
        .slice(0, n);
}

3. Using the code graph to find identifiers

The execQueryWrapper function in identifiers.ts queries the code graph using Tree-Sitter to find symbols.

File: identifiers.ts

import { execQueryWrapper } from '../../../../tree-sitter/query-sdk';

// Executes the query within the specified range to get identifiers
const identifiers = execQueryWrapper({
    document: params.document,
    queryPoints: {
        startPoint: asPoint({ line: Math.max(params.position.line - 100, 0), character: 0 }),
        endPoint: asPoint({ line: params.position.line, character: params.position.character + 1 })
    },
    queryWrapper: 'getGraphContextIdentifiers'
});

4. Building the context with LSP

The LspLightRetriever uses these extracted symbols to build the context.

File: lsp-light-retriever.ts