prometeu-studio/discussion/lessons/DSC-0040-pbs-lsp-find-references/LSN-0069-pbs-find-references-is-the-physical-inverse-of-definition.md
bQUARKz 9458312d73
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.51% (18192/29102) * Branch Coverage: 53.15% (7093/13345) * Lines of Code: 29102 * Cyclomatic Complexity: 11715 #### Quality Gates Summary Output truncated.
Test / Build skipped: 15, passed: 663
implements PLN-0132
Add PBS find-references as the request-local inverse of definition
identity on FrontendLanguageService. Usage sites are identifier
tokens whose definition locations intersect the cursor set.
Empty results stay honest when definition is empty, including
virtual stdlib paths. Honor includeDeclaration in the LSP bridge.

Housekeep DSC-0040 with LSN-0069.
2026-09-21 08:54:11 +01:00

6.2 KiB
Raw Permalink Blame History

id ticket title created tags
LSN-0069 pbs-lsp-find-references PBS find-references is the physical inverse of definition 2026-09-21
studio
lsp
vscode
compiler-pbs
editor
references

PBS find-references is the physical inverse of definition

Original Problem

PBS already had compiler-backed completion, hover, signature help, and go-to-definition (LSN-0051, LSN-0068). Users still could not ask where a resolved symbol is used. Text search confuses overloads, shadowing, members, comments, and coincidental names. Rename (AGD-0046) and hierarchy (AGD-0056) need an honest usage list before they exist.

The risk was inventing a SymbolId / RefIndex, waiting for snapshot cache (AGD-0051), or listing uses of stdlib APIs whose declarations are still virtual paths.

Consolidated Decision

PBS Find References is the LSP projection of physical usage sites of the same identity definition already returns.

Durable locks from DEC-0053 (AGD-0043 Q1Q6 = A):

  1. Resolve the cursor through the definition path (locals, parameters, members, imports/supplementals, current-module top-level). Identity is that physical declaration-location set. Do not text-search. Do not add SymbolId or a persistent RefIndex.
  2. A site is a usage when its definition locations intersect the cursor identity. Overloads follow that intersection.
  3. If definition at the same offset is empty, references is empty.
  4. Walk regular fileTable files from the current analyze() surface. Do not scan /virtual/stdlib or other non-regular handles.
  5. Keep the capability on the existing aggregated FrontendLanguageService. Reuse FrontendDefinitionLocation. Map PBS spans in prometeu-frontend-pbs. Common LSP must not import p.studio.compiler.pbs.*. No References SPI.
  6. Honor LSP includeDeclaration in the server: union usage sites with definition locations when the host asks and the declaration is a regular file. No read/write classification.
  7. Advertise referencesProvider. Partial coverage is valid. Analysis stays request-local. This discussion does not build rename, hierarchy, workspace symbols, virtual documents, or snapshot cache.

Spec 23 §8.3 now also states: a references location must identify a compiler-known physical source file; empty definition implies empty references; includeDeclaration must not invent a virtual location.

Final Implementation

Layer What landed
PBS editorial PbsEditorialSupportService.references walks IDENTIFIER tokens and keeps sites whose definition locations intersect the cursor identity (FileId + start + end).
Generic contract FrontendLanguageService.references defaults to List.of(). FrontendEditorialContext.projectSurface carries the PBS semantic read surface so the walk can see astByFile.
PBS mapping PBSFrontendLanguageService requires a non-empty physical definition set, skips non-regular files, and maps surviving spans through the same Files.isRegularFile helper as definition.
LSP referencesProvider, textDocument/references. The bridge applies includeDeclaration by unioning references with definition. Compile-only frontends stay empty.
VS Code Unchanged thin client.

Stdlib and SDK modules remain virtual (/virtual/stdlib/...). Shift+F12 on Gfx.clear is empty, matching F12. Hover is unchanged.

Local binding names are not usage sites: definition at let total is empty because the name is not yet in scope. The use return total matches. includeDeclaration adds the declaration span from definition, not a second name search.

Examples

Same-file function uses, including the declaring identifier (top-level names resolve to themselves):

fn helper() -> int { return 42; }

fn frame() -> void {
  helper();
  helper();
  // helper          // not a reference
  let text = "helper"; // not a reference
}

Imported project (or otherwise physical) symbols collect uses in the importing file. Identity is the foreign declaration span.

import { Log as Logger } from @sdk:log;
Logger.info("a");
Logger.info("b");

If @sdk:log is only a virtual handle, definition is empty, so references is empty.

Builtins stay hover-only:

let n: int = 1;  // hover works; references is empty

includeDeclaration=true adds the canonical declaration location on top of identifier usage sites. false returns usages only.

Pitfalls

Do not implement find-references as workspace text search in lsp-v1 or in the VS Code extension. It will lie about overloads, members, and imports, then poison rename.

Do not add a SymbolId index “for rename later”. Definition already gave the key: physical declaration locations. Rename can consume this list once it has its own decision.

Do not wait for snapshot cache. The LSP already reanalyzes on each editorial request. Snapshots (AGD-0051) can make the walk cheaper without changing the contract.

Do not treat empty stdlib references as a missing feature. Virtual paths are not regular files. Empty is the honest result until those sources live on disk.

Do not expect let total to appear as a usage of total. Inverse-of-definition only keeps identifier sites that themselves resolve. The declaration span arrives through includeDeclaration.

Do not put includeDeclaration into PBS types. It is a host flag applied in the LSP bridge.

Do not scan /virtual/stdlib to “find more uses”. That reopens virtual documents.

Do not split a References SPI “for future languages”. PBS is a real consumer of FrontendLanguageService (LSN-0067).

Do not treat this lesson as closing rename, snapshots, workspace symbols, document links, or hierarchy.

References

  • Agenda: AGD-0043 (Q1Q6 = A)
  • Decision: DEC-0053
  • Plan: PLN-0132
  • Spec 23 §8.3 — optional navigation; physical-file-or-empty; empty definition implies empty references
  • LSN-0068 — definition identity this feature inverts
  • LSN-0051 — wave 1 deferred navigation
  • LSN-0058 — generic FrontendLanguageService for LSP
  • LSN-0047 — protocol stays in lsp-v1; compiler owns semantics
  • LSN-0067 — no SPI without a real in-repo consumer
  • Still open: AGD-0046 rename, AGD-0045 workspace symbols, AGD-0051 snapshots, AGD-0055 document links, AGD-0056 hierarchy