fix(parser): report incomplete @let declarations like Angular - #529
Merged
Brooooooklyn merged 2 commits intoOct 4, 2026
Merged
Conversation
- The HTML parser skipped `IncompleteLet` tokens, so `@let foo = bar` without a closing `;` produced no error and no node. It now reports Angular's "Incomplete @let declaration" error and, when the declaration has a name, keeps a node with an empty value, as Angular's `_consumeIncompleteLet` does. - The lexer's `IncompleteLet` token now spans to the end of the consumed value, matching Angular's token location. - Port the seven `@let` cases from Angular's lexer, HTML parser and template transform specs that the conformance fixtures extract with no assertions.
Two more paths produced no INCOMPLETE_LET token, so the new parser arm could never report them: - `@let` followed by EOF or any non-whitespace, non-identifier char (`@let;`, `@let-`) fell back to plain text. Angular's _consumeLetDeclaration emits INCOMPLETE_LET for any non-whitespace following character, not only identifier chars. - `@let foo bar` and `@let foo` (a space after the name with no `=`) consumed "@let foo " and emitted nothing. Upstream marks the start token INCOMPLETE_LET, so the span ends at the name.
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.
Ports the seven
@letcases from Angular's compiler specs that the conformance fixtures extract with empty assertions, and fixes the parser gap two of them exposed.Fix: the HTML parser skipped
IncompleteLettokens (they fell through to the default arm), so@let foo = barwith no closing;produced no error and no node. It now does what Angular's_consumeIncompleteLetdoes: it reportsIncomplete @let declaration "foo". @let declarations must be written as `@let <name> = <value>;`and, when the declaration has a name, keeps aLetDeclarationnode with an empty value. The lexer'sIncompleteLettoken now ends at the end of the consumed value instead of at the name, matching Angular's span.Two lexer paths also produced no
IncompleteLettoken at all, so the new parser arm could never report them:@letfollowed by EOF or a non-whitespace, non-identifier char (@let,@let;,@let-) fell back to plain text. Angular's_consumeLetDeclarationemitsINCOMPLETE_LETfor any non-whitespace character after@let.@let foo barand@let foo(whitespace after the name with no=) consumed the text and emitted nothing. Upstream marks the same start tokenINCOMPLETE_LET, so the token span ends at the name.Tests, one per upstream case and named after its
it()title:ml_parser/lexer_spec.ts: escaped quotes in a string, function calls in the value, a complex expressionml_parser/html_parser_spec.ts: the error for an incomplete let declaration, the locations of an incomplete let declarationrender3/r3_template_transform_spec.ts: syntax errors in the value, a let declaration with no valuePlus four regression tests for the newly covered lexer paths (
@let foo bar = 123;,@let foo,@let,@let;), which have no upstream spec case.The lexer and transform cases already pass on main; only the HTML parser cases needed the parser fix. For the syntax-error case, Angular's message carries a
Parser Error:prefix that this crate does not add to any expression error, so the test matches the message without it.Evidence:
cargo test -p oxc_angular_compiler: 2940 passed, 0 failed.cargo fmt --checkis clean. Angular conformance: 1264/1264.advance()fails both HTML parser tests. Moving theIncompleteLetspan end back to the name fails the locations test. Disabling the backslash-escape skip in the lexer's quote scan, or no longer treating"as a quote, fails the escaped-quotes and complex-expression tests. Reverting either lexer fix fails the new regression tests.