Some checks are pending
Intrepid/Prometeu/Studio/pipeline/pr-master Build started...
JaCoCo Coverage #### Project Overview
No changes detected, that affect the code coverage.
* Line Coverage: 62.22% (17996/28921)
* Branch Coverage: 52.87% (6986/13213)
* Lines of Code: 28921
* Cyclomatic Complexity: 11624
#### Quality Gates Summary
Output truncated.
Test / Build skipped: 15, passed: 659
Intrepid/Prometeu/Studio/pipeline/head This commit looks good
Add PBS go-to-definition as hover editorial lookup plus physical declaration locations on FrontendLanguageService. Empty results stay honest when the target is not a regular file, including virtual stdlib paths. Housekeep DSC-0039 with LSN-0068.
99 lines
5.4 KiB
Markdown
99 lines
5.4 KiB
Markdown
---
|
||
id: LSN-0068
|
||
ticket: pbs-lsp-go-to-definition
|
||
title: PBS go-to-definition uses editorial lookup and physical files
|
||
created: 2026-09-21
|
||
tags: [studio, lsp, vscode, compiler-pbs, editor, definition]
|
||
---
|
||
|
||
# PBS go-to-definition uses editorial lookup and physical files
|
||
|
||
## Original Problem
|
||
|
||
PBS editor assistance already had compiler-backed completion, hover, and signature help (`LSN-0051`). Users still could not jump from a use to a declaration. Wave 1 explicitly deferred `go to definition`.
|
||
|
||
The remaining LSP navigation family (references, rename, workspace symbols, document links, hierarchy) needed a destination policy before those features could be honest. The risk was shipping a text search, a new `SymbolId` index, or virtual documents for stdlib before a real physical target existed.
|
||
|
||
## Consolidated Decision
|
||
|
||
PBS Go to Definition is the LSP projection of **physical declaration locations** on top of the **same editorial lookup hover already uses**.
|
||
|
||
Durable locks from `DEC-0052`:
|
||
|
||
1. Resolve the identifier under the cursor through the hover path (locals, parameters, members, imports/supplementals, current-module top-level). Do not use text search or a new usage index.
|
||
2. Keep the capability on the existing aggregated `FrontendLanguageService`. Add a default-empty `definition` method and a generic location DTO. Do not add a Definition SPI.
|
||
3. Map PBS editorial spans inside `prometeu-frontend-pbs`. Common LSP must not import `p.studio.compiler.pbs.*`.
|
||
4. Jump only when `Span.fileId` maps to a **regular filesystem file**. Otherwise return an empty list. Do not create virtual documents, `untitled:` buffers, or synthetic URIs.
|
||
5. The destination is the canonical declaration, not the import-alias line. Overloads return every matching location.
|
||
6. Advertise `definitionProvider`. Partial coverage is valid. Keywords, source-less builtins, unresolved names, and virtual stdlib paths stay empty; hover is unchanged.
|
||
7. Analysis stays request-local, like hover. This discussion does not build references, rename, or snapshot cache.
|
||
|
||
Spec 23 §8.3 already listed definition as an optional editor capability. It now also states: a definition location must identify a compiler-known physical source file, or the response must be empty.
|
||
|
||
## Final Implementation
|
||
|
||
| Layer | What landed |
|
||
|---|---|
|
||
| PBS editorial | `PbsEditorialSupportService.definition` reuses hover dispatch and attaches declaration `Span`s (`PbsEditorialLocation`). |
|
||
| Generic contract | `FrontendDefinitionLocation` (absolute path + offsets) and `FrontendLanguageService.definition` defaulting to `List.of()`. |
|
||
| PBS mapping | `PBSFrontendLanguageService` maps `FileId` through `fileTable` and keeps the location only if `Files.isRegularFile(path)`. |
|
||
| LSP | `LanguageServiceBridge.definition`, `definitionProvider`, `textDocument/definition`. Compile-only frontends return empty. |
|
||
| VS Code | Unchanged thin client. |
|
||
|
||
Stdlib and SDK modules are still registered under virtual paths such as `/virtual/stdlib/...`. Those handles are not regular files, so F12 on `Gfx.clear` is empty even though hover works. That is the physical-file rule, not a missing lookup.
|
||
|
||
The location payload (path + span of an already resolved symbol) is reusable later by references (`AGD-0043`) and rename (`AGD-0046`). Those indexes were not built here. Snapshots (`AGD-0051`) remain a later performance discussion, not a prerequisite for this request-local feature.
|
||
|
||
## Examples
|
||
|
||
Same-file jump:
|
||
|
||
```pbs
|
||
fn helper() -> int { return 42; }
|
||
|
||
fn frame() -> void {
|
||
helper(); // definition -> helper's declaration in this file
|
||
}
|
||
```
|
||
|
||
Aliased import jumps to the original declaration span, not the `import` line:
|
||
|
||
```pbs
|
||
import { Log as Logger } from @sdk:log;
|
||
Logger.info("hello");
|
||
```
|
||
|
||
If `@sdk:log` is only a virtual stdlib handle, definition is empty. If a project file owns the declaration and that file exists on disk, definition uses that path.
|
||
|
||
Builtins stay hover-only:
|
||
|
||
```pbs
|
||
let n: int = 1; // hover describes the builtin; definition is empty
|
||
```
|
||
|
||
## Pitfalls
|
||
|
||
Do not implement definition as a second name search in `lsp-v1` or in the VS Code extension. It will break on imports, overloads, and members, then be thrown away when references arrive.
|
||
|
||
Do not open `/virtual/stdlib/...` or invent an `untitled:` document so stdlib F12 “does something”. Empty is the honest result until those sources are real files.
|
||
|
||
Do not pick the first overload location in the server. Return the full `Location[]`.
|
||
|
||
Do not wait for snapshot cache before definition. Hover is already request-local; definition follows that shape.
|
||
|
||
Do not split a new top-level definition service “for future languages”. PBS is a real consumer of the existing language-service surface (`LSN-0067`).
|
||
|
||
Do not treat this lesson as closing references, rename, outline, workspace symbols, or document links. Those agendas stay open. This lesson only locks the destination policy they can reuse.
|
||
|
||
## References
|
||
|
||
- Agenda: `AGD-0042` (Q1–Q6 = A)
|
||
- Decision: `DEC-0052`
|
||
- Plan: `PLN-0131`
|
||
- Spec 23 §8.3 — optional definition capability; physical-file-or-empty
|
||
- `LSN-0051` — wave 1 deferred go-to-definition
|
||
- `LSN-0058` — generic `FrontendLanguageService` for LSP
|
||
- `LSN-0047` — protocol stays in `lsp-v1`; compiler owns semantics
|
||
- `LSN-0067` — no SPI or virtual-document host without a real consumer
|
||
- Still open: `AGD-0043` references, `AGD-0045` workspace symbols, `AGD-0046` rename, `AGD-0051` snapshots, `AGD-0055` document links, `AGD-0056` hierarchy
|