Contents
In brief
Repo text search finds similar strings but does not answer what type a variable has or where an import is declared. A Habr note shows how an LLM completion system queries the Language Server Protocol for definitions, types, and references — then turns those answers into model context.
What happened
The author continues a series on autocomplete. After BM25 around the cursor, a gap remains: an import points to a concrete declaration, a service has an interface, a method has argument fields. Matching the words ReturnRequest is not the same as a program edge.
LSP standardises editor ↔ language server traffic over JSON-RPC: initialize, document sync, then methods such as textDocument/definition, typeDefinition, references, and hover. The protocol does not “understand TypeScript”; a concrete language server supplies quality, while LSP supplies the message shape. Some IDEs use PSI or editor APIs instead, but the idea is the same: a graph of definitions and types instead of a bag of strings.
On a returnService example the chain is: definition → typed declaration → typeDefinition → interface with submit → definition of SubmitReturnCommand → method references → a real call site that shows where requestedBy comes from. Both the API contract and how the project usually uses it land in the prompt.
Why it matters
An LLM without semantics guesses from neighbouring text. LSP gives retrieval along program edges: which symbols are legal at the cursor is completion; what the developer intends to write is ranking plus FIM prompt assembly. For future agents the same layer becomes code navigation: semantic tools walk known edges, repository search covers wording and meaning.
Completion quality is not only the model: when generation starts, which context you kept, how you ranked it, token cost, and whether you finish before the next keystroke.
In practice
- Before generation, request definition and typeDefinition for symbols near the cursor.
- Add one or two live production
references, not only the interface signature. - Rank candidates by type match, file freshness, test vs prod, and token cost.
- Do not confuse
textDocument/completion(legal symbols) with generating a full expression — different jobs. - Budget a timeout: a slow language server is worse than empty context if it kills interactivity.
Takeaway
A semantic layer on top of BM25 turns completion from “guess from lines” into “lean on the project contract.” LSP is not a model replacement; it is how you give the model the same edges the IDE already uses.

