Recover from mismatched loop terminators with quick fixes#1696
Open
Recover from mismatched loop terminators with quick fixes#1696
Conversation
When a `while` block has no matching `end while` and the next dangling
terminator is a `next`, treat it as a malformed `end while`. Symmetric
treatment for `for`/`for each` blocks closed with a stray `end while`.
The previous behavior was a cascade of two unhelpful diagnostics
(`Unexpected token` + `Could not find matching end <kw>`) per case.
Now each case produces one targeted diagnostic:
- 1147 `Expected 'end while' but found 'next'`
- 1148 `Expected 'end for' or 'next' but found 'end while'`
Quick fixes are attached to each diagnostic (with fix-all variants
when the same mistake appears multiple times in the file):
- `while ... next` → `Convert 'next' to 'end while'`
- `for ... end while` → `Convert 'end while' to 'end for'` (preferred)
or `Convert 'end while' to 'next'`
- `for each ... end while` → same two fixes as `for`
TwitchBronBron
requested changes
May 4, 2026
…recovery # Conflicts: # src/bscPlugin/codeActions/CodeActionsProcessor.spec.ts
Replace whileLoopTerminatedWithNext (1147) and forLoopTerminatedWithEndWhile
(1148) with a single mismatchedEndingToken diagnostic that carries
{ expected, found } on its data payload. Code actions read the structured
data to build "Convert '<found>' to '<expected[i]>'" fixes, so adding new
recovery sites doesn't require new diagnostic codes or new handlers.
Also adds isDiagnosticOfType type guard for refining BsDiagnostic to a
specific DiagnosticMessageType<K>.
TwitchBronBron
approved these changes
May 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When a user writes a common loop-terminator mistake, the parser used to emit two cascading diagnostics that didn't connect the user's intent to the actual problem. This PR adds error recovery in three loop-parsing paths and a single parameterized diagnostic with a structured
datapayload that drives the quick fixes.Before
emitted:
Unexpected token 'next'Could not find matching 'end while'After
Same input emits one diagnostic:
Expected 'end while' but found 'next'(code 1147)with a quick fix
Convert 'next' to 'end while'.Cases handled
while ... nextExpected 'end while' but found 'next'Convert 'next' to 'end while'for ... end whileExpected 'end for' or 'next' but found 'end while'Convert 'end while' to 'end for'(preferred),Convert 'end while' to 'next'for each ... end whileforWhen the same mistake appears multiple times in a file, fix-all variants are also offered.
Implementation
mismatchedEndingToken(expected: string[], found: string)diagnostic (code 1147). Theexpectedarray is preferred-first, and both fields are kept ondiagnostic.dataso consumers can build fixes mechanically rather than dispatching on per-pair codes.whileStatementacceptsNextas a recovery terminator; consumes it on the bogus path and stores it onWhileStatement.tokens.endWhileso quick fixes can target the token's range. CallsmismatchedEndingToken(['end while'], 'next').forStatementandforEachStatementacceptEndWhileas a recovery terminator; same shape. They callmismatchedEndingToken(['end for', 'next'], 'end while').forEachStatementalso refactored from "throw on missing terminator" to recover-and-continue.CodeActionsProcessor.suggestMismatchedEndingTokenQuickFixesreadsexpected[]/foundfrom the diagnostic and emits one fix per legal terminator (first entry isisPreferred). No per-pair handler.isDiagnosticOfType(diagnostic, key)type guard refinesBsDiagnosticto the concreteDiagnosticMessageType<K>when its code matches, used by the code-action dispatcher.Test plan
npm test— 2838 passing, 0 failingnpm run lint— cleandata: { expected, found }payload forwhile,for, andfor each