Call hierarchy walks CallExpr nodes for functions and methods. It does not use the references index. A cursor that is not on a callable is empty, and type hierarchy stays unadvertised. Housekeep DSC-0066 with LSN-0074.
5.9 KiB
| id | ticket | title | created | tags | |||||
|---|---|---|---|---|---|---|---|---|---|
| LSN-0074 | pbs-lsp-remaining-editor-surface | PBS remaining editor surface is frontend-owned and transported by the LSP | 2026-09-22 |
|
PBS remaining editor surface is frontend-owned and transported by the LSP
Original Problem
Nine open LSP agendas still described formatting, imports, semantic tokens, snapshots, completion, folding, diagnostics, document links, and call hierarchy as if none of that surface existed. By the time those agendas were still open, the server already advertised hover, completion, signature help, definition, references, outline, workspace symbols, rename, quick fix, and full semantic tokens. Each request still rebuilt analysis. References and rename had already shipped without a snapshot cache. There was no diagnostic whose meaning was "this name is not imported."
Treating the nine agendas as nine decisions would have reimplemented finished work and locked stale premises.
Consolidated Decision
DEC-0058 retired that split. One plan, PLN-0137, landed seven steps. The frontend produces the editorial result. The LSP transports it and does not invent a second policy. A missing capability is not advertised and returns an empty list, not a protocol error.
The wave explicitly does not add a project snapshot cache, type hierarchy, completionItem/resolve, snippets, a ranking score, range or on-type formatting, organize imports, a missing-import quick fix, relatedInformation, or a new semantic-token key.
- Published editor diagnostic
sourceis the bound frontendlanguageId. For PBS that ispbs.codestays the stable compiler code. The code is not copied intosource. - A document link covers only the span of a
ModuleRefwhose module assembly already resolved to a regular file. Virtual stdlib and unresolved modules produce no link. - Folding comes from recovered spans of the listed declarations, their bodies, parameter lists, and
Doctext blocks. A brace, parenthesis, or text block the tree does not cover still folds, including an unmatched opener through the end of the text. Selection grows outward from identifier, to argument or parameter list, to block orDoctext block, to declaration. - Formatting is full-document only. It reprints the token stream, indents by four spaces where brace or parenthesis nesting changes, leaves
Doctext-block interiors untouched, and does not reorder declarations or move comments off their line. - Semantic tokens keep
PBSSemanticTokenProvideras the baseline. Hover resolution may replace an identifier token only when an existingPbsSemanticKindmatches the symbol. Failure, a broken file, or a symbol with no existing key keeps the baseline token. - Completion inside a
ModuleReflists project and stdlib modules the current resolver can already name. Every other offset keeps the existing member or general completion. Items stay eager andresolveProviderstays false. - Call hierarchy walks
CallExprnodes for functions and methods. It does not use the references index. A cursor that is not on a callable is empty. Type hierarchy is not advertised.
Final Implementation
CompilerLanguageServiceBridge reads LspProjectContext.languageId into BaselineDocumentIssue.source. Document links read the physical module map that module assembly already built; stdlib files under /virtual/stdlib are not regular files, so they are not links. Folding, selection, and formatting reparse the open buffer with the existing lexer and parser. They do not require a successful project analysis. The semantic-token overlay runs only when editorial context is available and otherwise returns the provider tokens, including when project discovery fails. Module completion labels are the project modules from that same physical map plus the modules ResourceStdlibEnvironmentResolver can already resolve. Call hierarchy collects function, method, and constructor declarations from the recovered AST and matches CallExpr callees by name and call shape.
Spec 23 §8.3 states each of these rules. The nine earlier agendas, AGD-0048 through AGD-0056, were abandoned and are not normative.
Examples
A project import @app:a that resolves to src/a/source.pbs is one document link on that module-reference span. @sdk:log is not, because the stdlib file is virtual.
fn helper() -> int { return 1; }
fn main() -> int { return helper; }
The use of helper without a call is an identifier in the lexical pass. Hover resolves it as a function, so the overlay key is pbs-function. A local such as value has no existing key, so it stays pbs-identifier.
fn helper() -> int { return 1; }
fn main() -> int { return helper(); }
Prepare on main returns that function. Outgoing calls include helper. Incoming calls of helper include main. A cursor on a struct name returns no item.
Common Pitfalls
- Do not copy the diagnostic code into
source. The editor then shows the code twice and loses the language id. - Do not build document links to
/virtual/stdlib. Definition already refuses that destination. - Do not treat document symbols as folding ranges. Outline and folding are different payloads.
- Do not pretty-print from the AST. Comments and
Doctext-block interiors are not fully modeled as trivia on the tree. - Do not add
pbs-local,pbs-parameter, orpbs-fieldin the overlay. Those symbols stay on the baseline token until a later decision adds the key. - Do not implement call hierarchy by inverting the references index. A reference is a use of a name, not a call.
- Do not start a snapshot cache because a later feature feels slow. This wave deliberately kept request-local analysis.
References
DEC-0058andPLN-0137, removed by housekeeping after this lessondocs/specs/compiler/23. Compiler Pipeline Entry Points Specification.md§8.3- Earlier surface:
LSN-0068,LSN-0069,LSN-0070,LSN-0071,LSN-0072,LSN-0073 - Abandoned agendas:
AGD-0048throughAGD-0056