|
| 1 | +# Brief: S5-D2 — span mapper + lazy memoized interpret + assembly wiring |
| 2 | + |
| 3 | +## Task |
| 4 | + |
| 5 | +Complete the data path (all in `packages/1-framework/3-tooling/language-server/`): |
| 6 | + |
| 7 | +1. **`diagnostic-mapping.ts`** — new mapper `ContractSourceDiagnostic → LspDiagnostic`: |
| 8 | + spans carry `{offset, line, column}` positions — verify the base (0- vs 1-based) |
| 9 | + against `rangeToPslSpan` (psl-parser's forward conversion; your mapper is its |
| 10 | + inverse) and pin with a hand-computed expected range in a test. **Span-less |
| 11 | + diagnostics anchor at document start** (synthetic 0,0→0,1 range) — never dropped. |
| 12 | +2. **`project-artifacts.ts`** — `DocumentArtifacts` gains a lazily computed, memoized |
| 13 | + interpret slot: on first request (diagnostics assembly only), invoke |
| 14 | + `interpretation.source.interpret({document, sourceFile, symbolTable, sourceId}, |
| 15 | + interpretation.context)` **as a method — never detach it** (slice-04 hazard, now |
| 16 | + live); unwrap `notOk → failure.diagnostics`, `ok → []`; map via (1); cache until |
| 17 | + the existing `documentChanged`/`documentClosed` drop. `sourceId` = the document |
| 18 | + URI (same URI form as D1's `resolvedInputs` — consistency pinned in a test). |
| 19 | + `runPipeline` untouched. **No try/catch around `interpret`** — a throw is a real |
| 20 | + bug that must surface (slice-04 no-throw pins are the guarantee; config-load |
| 21 | + failures are slice 06). |
| 22 | +3. **Assembly wiring** — one combined-diagnostics function (parse/symbol-table + |
| 23 | + mapped interpreter findings) consumed by BOTH the push path (`publish`) and the |
| 24 | + pull handler (`buildDocumentDiagnosticReport`) — do not implement it twice. |
| 25 | + Interpretation runs only when a diagnostics response/publication is built. |
| 26 | +4. **Reviewer carry-overs from D1 (all three):** |
| 27 | + - Fold the now-dead `resolveControlStackInputs` export (port its three pins into |
| 28 | + the surviving shape). |
| 29 | + - Add a one-line doc note on `PslInterpretCapable` (psl-parser): `interpret` must |
| 30 | + not read disk or `context.resolvedInputs`; those are load-path concerns. |
| 31 | + - (The as-a-method rule is restated in (2).) |
| 32 | + |
| 33 | +Tests first: |
| 34 | + |
| 35 | +- **SDoD1 (TC-9):** capability config + schema with an unresolvable relation → the |
| 36 | + diagnostics response contains the interpreter diagnostic at the hand-verifiable |
| 37 | + range; fixing the schema clears it on the next pull. |
| 38 | +- **SDoD2 (TC-10):** span-less diagnostic → anchored at document start (real span-less |
| 39 | + producer if one is reachable, else a capability-shaped test double — document the |
| 40 | + choice). |
| 41 | +- **SDoD3 (TC-11):** byte-for-byte degradation regression — full diagnostic responses |
| 42 | + (push and pull) for a capability-less config deep-equal the pre-slice shape. |
| 43 | +- **SDoD4 (TC-12):** spy on `interpret`: semantic-token, folding-range, and completion |
| 44 | + requests → zero calls; two consecutive pulls on unchanged content → exactly one |
| 45 | + call; an edit → exactly one more on the next pull. |
| 46 | + |
| 47 | +## Scope |
| 48 | + |
| 49 | +**In:** `language-server/src/{diagnostic-mapping,project-artifacts,document-diagnostics,server,config-resolution}.ts` + tests; the one-line doc note in |
| 50 | +`psl-parser/src/interpret.ts`. |
| 51 | +**Out:** `pipeline.ts` behavior; config-failure surfacing / last-good retention |
| 52 | +(slice 06); CLI; providers; `projects/**`; GitHub threads. |
| 53 | + |
| 54 | +## Completed when |
| 55 | + |
| 56 | +- [ ] SDoD1–4 tests green; combined assembly single-sourced for push + pull. |
| 57 | +- [ ] Dead wrapper folded; doc note landed; zero casts; zero try/catch around |
| 58 | + `interpret`. |
| 59 | +- [ ] Gates: `pnpm --filter @prisma-next/language-server test` + typecheck + lint, |
| 60 | + `pnpm typecheck`, `pnpm test:packages`, `pnpm lint:deps`. |
| 61 | + |
| 62 | +## Operational metadata |
| 63 | + |
| 64 | +- **Time-box:** 90 min. Halt: the span base cannot be pinned against a real |
| 65 | + interpreter diagnostic (mapping ambiguity — surface, never guess); the pull and |
| 66 | + push paths resist a shared assembly without restructuring beyond this slice's |
| 67 | + files; memoization cannot key cleanly on the existing document-drop lifecycle. |
0 commit comments