From 6bd17216627978d68bb1c153af347b346a5aa503 Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Mon, 27 Apr 2026 09:39:44 +0200 Subject: [PATCH] fix(compiler): let declaration span not including end character Fixes that the span for `@let` declarations didn't include the end token. --- .../unused_let_declaration/unused_let_declaration_spec.ts | 4 ++-- packages/compiler/src/ml_parser/lexer.ts | 2 +- packages/compiler/src/ml_parser/parser.ts | 2 +- packages/compiler/test/ml_parser/html_parser_spec.ts | 2 +- packages/compiler/test/render3/r3_ast_spans_spec.ts | 2 +- packages/language-service/test/definitions_spec.ts | 2 +- packages/language-service/test/legacy/definitions_spec.ts | 2 +- packages/language-service/test/quick_info_spec.ts | 4 ++-- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/compiler-cli/src/ngtsc/typecheck/extended/test/checks/unused_let_declaration/unused_let_declaration_spec.ts b/packages/compiler-cli/src/ngtsc/typecheck/extended/test/checks/unused_let_declaration/unused_let_declaration_spec.ts index 9d27c2a4c83..8c613630c2f 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/extended/test/checks/unused_let_declaration/unused_let_declaration_spec.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/extended/test/checks/unused_let_declaration/unused_let_declaration_spec.ts @@ -61,7 +61,7 @@ runInEachFileSystem(() => { expect(diags.length).toBe(1); expect(diags[0].category).toBe(ts.DiagnosticCategory.Warning); expect(diags[0].code).toBe(ngErrorCode(ErrorCode.UNUSED_LET_DECLARATION)); - expect(getSourceCodeForDiagnostic(diags[0])).toBe('@let unused = 2'); + expect(getSourceCodeForDiagnostic(diags[0])).toBe('@let unused = 2;'); }); it('should report a solo @let declaration that is not used', () => { @@ -77,7 +77,7 @@ runInEachFileSystem(() => { expect(diags.length).toBe(1); expect(diags[0].category).toBe(ts.DiagnosticCategory.Warning); expect(diags[0].code).toBe(ngErrorCode(ErrorCode.UNUSED_LET_DECLARATION)); - expect(getSourceCodeForDiagnostic(diags[0])).toBe('@let foo = 1'); + expect(getSourceCodeForDiagnostic(diags[0])).toBe('@let foo = 1;'); }); it('should not report a @let declaration that is only used in other @let declarations', () => { diff --git a/packages/compiler/src/ml_parser/lexer.ts b/packages/compiler/src/ml_parser/lexer.ts index c463bc4a42a..2800f364208 100644 --- a/packages/compiler/src/ml_parser/lexer.ts +++ b/packages/compiler/src/ml_parser/lexer.ts @@ -423,8 +423,8 @@ class _Tokenizer { const endChar = this._cursor.peek(); if (endChar === chars.$SEMICOLON) { this._beginToken(TokenType.LET_END); - this._endToken([]); this._cursor.advance(); + this._endToken([]); } else { startToken.type = TokenType.INCOMPLETE_LET; startToken.sourceSpan = this._cursor.getSpan(start); diff --git a/packages/compiler/src/ml_parser/parser.ts b/packages/compiler/src/ml_parser/parser.ts index 88ea7c9f860..a0a69719165 100644 --- a/packages/compiler/src/ml_parser/parser.ts +++ b/packages/compiler/src/ml_parser/parser.ts @@ -843,7 +843,7 @@ class _TreeBuilder { endToken = this._advance(); } - const end = endToken.sourceSpan.fullStart; + const end = endToken.sourceSpan.end; const span = new ParseSourceSpan( startToken.sourceSpan.start, end, diff --git a/packages/compiler/test/ml_parser/html_parser_spec.ts b/packages/compiler/test/ml_parser/html_parser_spec.ts index 2ea1422e793..6d6badd872d 100644 --- a/packages/compiler/test/ml_parser/html_parser_spec.ts +++ b/packages/compiler/test/ml_parser/html_parser_spec.ts @@ -1283,7 +1283,7 @@ describe('HtmlParser', () => { it('should store the source location of a @let declaration', () => { expect(humanizeDomSourceSpans(parser.parse('@let foo = 123 + 456;', 'TestCmp'))).toEqual([ - [html.LetDeclaration, 'foo', '123 + 456', '@let foo = 123 + 456', 'foo', '123 + 456'], + [html.LetDeclaration, 'foo', '123 + 456', '@let foo = 123 + 456;', 'foo', '123 + 456'], ]); }); diff --git a/packages/compiler/test/render3/r3_ast_spans_spec.ts b/packages/compiler/test/render3/r3_ast_spans_spec.ts index 9f1a5336d26..3f4bee356ea 100644 --- a/packages/compiler/test/render3/r3_ast_spans_spec.ts +++ b/packages/compiler/test/render3/r3_ast_spans_spec.ts @@ -964,7 +964,7 @@ describe('R3 AST source spans', () => { describe('@let declaration', () => { it('is correct for a let declaration', () => { expectFromHtml('@let foo = 123;').toEqual([ - ['LetDeclaration', '@let foo = 123', 'foo', '123'], + ['LetDeclaration', '@let foo = 123;', 'foo', '123'], ]); }); }); diff --git a/packages/language-service/test/definitions_spec.ts b/packages/language-service/test/definitions_spec.ts index 694bc7c5f13..f3ee409b299 100644 --- a/packages/language-service/test/definitions_spec.ts +++ b/packages/language-service/test/definitions_spec.ts @@ -510,7 +510,7 @@ describe('definitions', () => { const {definitions} = getDefinitionsAndAssertBoundSpan(env, template); expect(definitions[0].name).toEqual('foo'); expect(definitions[0].kind).toBe(ts.ScriptElementKind.variableElement); - expect(definitions[0].textSpan).toBe('@let foo = {value: 123}'); + expect(definitions[0].textSpan).toBe('@let foo = {value: 123};'); assertFileNames(Array.from(definitions), ['app.html']); }); diff --git a/packages/language-service/test/legacy/definitions_spec.ts b/packages/language-service/test/legacy/definitions_spec.ts index c36536f7605..b529b3a3f0b 100644 --- a/packages/language-service/test/legacy/definitions_spec.ts +++ b/packages/language-service/test/legacy/definitions_spec.ts @@ -292,7 +292,7 @@ describe('definitions', () => { expect(definitions.length).toBe(1); const [def] = definitions; - expect(def.textSpan).toBe('@let value = 42'); + expect(def.textSpan).toBe('@let value = 42;'); }); }); diff --git a/packages/language-service/test/quick_info_spec.ts b/packages/language-service/test/quick_info_spec.ts index 7d6cddfdea8..286b7fb905c 100644 --- a/packages/language-service/test/quick_info_spec.ts +++ b/packages/language-service/test/quick_info_spec.ts @@ -877,7 +877,7 @@ describe('quick info', () => { it('should get quick info for a let declaration', () => { expectQuickInfo({ templateOverride: `@let na¦me = 'Frodo'; {{name}}`, - expectedSpanText: `@let name = 'Frodo'`, + expectedSpanText: `@let name = 'Frodo';`, expectedDisplayString: `(let) name: "Frodo"`, }); }); @@ -885,7 +885,7 @@ describe('quick info', () => { it('should get quick info for a let declaration initialized with a narrowed property', () => { expectQuickInfo({ templateOverride: `@if (signalValue) { @let na¦me = signalValue; {{name}} }`, - expectedSpanText: `@let name = signalValue`, + expectedSpanText: `@let name = signalValue;`, expectedDisplayString: `(let) name: string`, }); });