fix(document-symbols): unbounded MAP/MODULE scan corrupting the outline - #382
fix(document-symbols): unbounded MAP/MODULE scan corrupting the outline#382geircodes wants to merge 2 commits into
Conversation
|
Reviewed — the core fix is correct: bounding the MAP/MODULE END-detection scan by Holding for two reasons, both process rather than logic:
|
msarson
left a comment
There was a problem hiding this comment.
Core fix is correct — holding on two process points: an unrelated "in <Parent>" detail change bundled in, and no regression test. Details in the review comment above.
|
👋 Housekeeping: This PR is still held on the review feedback above — no change to that. When you get a chance to revise, please rebase your branch onto |
…tions handleStructureToken() computed endsOnSameLine for structures that open and close on one line (e.g. `fq QUEUE(FILE:Queue) END`) and returned early — before reaching the code further down that reads the preceding same-line token and assigns token.label. Multi-line structures worked fine; any single-line QUEUE/GROUP/etc. never got its declared name attached, so the outline showed a bare "QUEUE" node instead of "QUEUE (fq)". Hoisted the label-assignment block (including the msarson#65 LOOP/ACCEPT special case) to run before the endsOnSameLine check, and removed the now-dead duplicate copy that used to sit after the early return.
…finishesAt
The lookahead accepted an EndStatement as the structure's true end only if no
Structure token had been seen since - but a MODULE nested inside a MAP is
itself a Structure token, so that condition could never become true again
once one appeared, and the scan ran unbounded through the rest of the file.
Any later identifier immediately followed by '(' (e.g. WINDOW attributes like
FONT(...), VALUE(...), FROM(...)) got misclassified as a MAP/MODULE procedure
and surfaced as a stray outline entry.
Bound the lookahead with the structure's own finishesAt, which the tokenizer
already computes with correct nesting depth (and which the rest of the
codebase, e.g. MapProcedureResolver, already relies on) - instead of
re-deriving the end with the broken heuristic.
The 'in <Parent>' detail suppression that previously rode along in this
branch is removed - it is independent of this fix and will be proposed
separately.
Tests: new DocumentSymbol.MapModuleLookahead382.test.ts pins the exact
trigger shape - a MAP with a nested MODULE followed by a WINDOW: attribute
keywords must not appear as outline symbols (fails against the unbounded
scan with stray FONT/FONT/FROM entries), and the MAP's and nested MODULE's
real prototypes must still index. Full suite 2385 passing.
d493f5a to
1959f62
Compare
Reply for PR #382 (fix/map-module-symbol-endless-lookahead)Both points addressed; rebased onto 1. Scope creep removed. The 2. Regression test added — new
Full suite: 2385 passing. |
Summary
Two document-symbol (outline) bugs found while auditing a real production
.clwfile'sDocument Structure (outline)panel for aWINDOWprocedure — one of them significant beyond just that outline, since it silently corrupted symbol classification for the rest of the file once triggered.ClarionDocumentSymbolProvider.ts— unbounded MAP/MODULE lookahead. When the parser hits aMAP/MODULEstructure, it scans forward to find shorthand procedure declarations, accepting anEndStatementas the structure's true end only if noStructuretoken had been seen since. AMODULE(...)nested inside aMAPis itself aStructuretoken, so once one appeared, that condition could never become true again — the scan ran unbounded through the rest of the file. Any later identifier immediately followed by((e.g.WINDOWattributes likeFONT(...),VALUE(...),FROM(...)) got misclassified as a MAP/MODULE procedure and surfaced as a stray top-level outline entry, for every symbol after that point in the file — not just inside the offendingWINDOW.Fix: bound the lookahead with the structure's own
finishesAt, which the tokenizer already computes with correct nesting depth and which the rest of the codebase (e.g.MapProcedureResolver) already relies on — instead of re-deriving the end with the broken heuristic.DocumentStructure.ts— single-line structure declarations never got a label.handleStructureToken()computesendsOnSameLinefor structures that open and close on one line (e.g.fq QUEUE(FILE:Queue) END) and returns early — before reaching the code further down that reads the preceding same-line token and assignstoken.label. Multi-line structures worked fine; any single-lineQUEUE/GROUP/etc. never got its declared name attached, so the outline showed a bare"QUEUE"node instead of"QUEUE (fq)".Fix: hoisted the label-assignment block (including the Language support: labeled LOOP and BREAK/CYCLE with label target #65 LOOP/ACCEPT special case) to run before the
endsOnSameLinecheck, and removed the now-dead duplicate copy that used to sit after the early return.The detail-text change was split out of this PR per review — it's proposed separately as its own
look-and-feel issue with a ready patch.
Disabled (commented out, not deleted, for a cheap revert if some consumer turns out to need it) the three call sites that set this text.
Checked git history before writing (1) and (2): both bugs were introduced together, from scratch, in the single commit that created
DocumentStructure.ts(#280) — not a regression of previously-correct behavior, and no existing helper elsewhere in the codebase does the same job that could have been reused instead.Test plan
DocumentSymbol.MapModuleLookahead382.test.tspinning the exact trigger shape — a MAP containing a nested MODULE, followed by a WINDOW: attribute keywords (FONT/AT/USE/FROM) must not appear as outline symbols. Fails against the unbounded scan (verified by reverting just the provider: the old code emits strayFONT,FONT,FROMentries), and a companion case confirms the MAP's own prototype and the nested MODULE's prototype still index.npx tsc -b— clean compileorigin/version-1.0.2.clwfile (tokenizer + provider run outside the test suite): no strayFONT/VALUE/FROMentries, no bareQUEUEnodes (1488 symbols checked)🤖 Generated with Claude Code