Skip to content

Commit cc722ea

Browse files
P4alxhub
authored andcommitted
fix(compiler): return full spans for Comment nodes (#50855)
Change sourceSpan for Comment nodes to cover the whole comment instead of just the opening token. The primary motivation for this is the interaction between ESLint and `@angular-eslint`. ESLint can detect unused `eslint-disable` directives in comments and automatically remove them when running with `--fix`. This is based on ranges computed from AST spans, and as a result does not work inside Angular templates - right now all comments claim to be 4 characters long so only the opening `<!--` is removed. PR Close #50855
1 parent 21299d9 commit cc722ea

File tree

4 files changed

+21
-13
lines changed

4 files changed

+21
-13
lines changed

packages/compiler/src/ml_parser/parser.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,13 @@ class _TreeBuilder {
107107

108108
private _consumeComment(token: CommentStartToken) {
109109
const text = this._advanceIf(TokenType.RAW_TEXT);
110-
this._advanceIf(TokenType.COMMENT_END);
110+
const endToken = this._advanceIf(TokenType.COMMENT_END);
111111
const value = text != null ? text.parts[0].trim() : null;
112-
this._addToParent(new html.Comment(value, token.sourceSpan));
112+
const sourceSpan = endToken == null ?
113+
token.sourceSpan :
114+
new ParseSourceSpan(
115+
token.sourceSpan.start, endToken.sourceSpan.end, token.sourceSpan.fullStart);
116+
this._addToParent(new html.Comment(value, sourceSpan));
113117
}
114118

115119
private _consumeExpansion(token: ExpansionFormStartToken) {

packages/compiler/test/i18n/extractor_merger_spec.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -351,40 +351,40 @@ import {serializeNodes as serializeHtmlNodes} from '../ml_parser/util/util';
351351
describe('blocks', () => {
352352
it('should report nested blocks', () => {
353353
expect(extractErrors(`<!-- i18n --><!-- i18n --><!-- /i18n --><!-- /i18n -->`)).toEqual([
354-
['Could not start a block inside a translatable section', '<!--'],
355-
['Trying to close an unopened block', '<!--'],
354+
['Could not start a block inside a translatable section', '<!-- i18n -->'],
355+
['Trying to close an unopened block', '<!-- /i18n -->'],
356356
]);
357357
});
358358

359359
it('should report unclosed blocks', () => {
360360
expect(extractErrors(`<!-- i18n -->`)).toEqual([
361-
['Unclosed block', '<!--'],
361+
['Unclosed block', '<!-- i18n -->'],
362362
]);
363363
});
364364

365365
it('should report translatable blocks in translatable elements', () => {
366366
expect(extractErrors(`<p i18n><!-- i18n --><!-- /i18n --></p>`)).toEqual([
367-
['Could not start a block inside a translatable section', '<!--'],
368-
['Trying to close an unopened block', '<!--'],
367+
['Could not start a block inside a translatable section', '<!-- i18n -->'],
368+
['Trying to close an unopened block', '<!-- /i18n -->'],
369369
]);
370370
});
371371

372372
it('should report translatable blocks in implicit elements', () => {
373373
expect(extractErrors(`<p><!-- i18n --><!-- /i18n --></p>`, ['p'])).toEqual([
374-
['Could not start a block inside a translatable section', '<!--'],
375-
['Trying to close an unopened block', '<!--'],
374+
['Could not start a block inside a translatable section', '<!-- i18n -->'],
375+
['Trying to close an unopened block', '<!-- /i18n -->'],
376376
]);
377377
});
378378

379379
it('should report when start and end of a block are not at the same level', () => {
380380
expect(extractErrors(`<!-- i18n --><p><!-- /i18n --></p>`)).toEqual([
381-
['I18N blocks should not cross element boundaries', '<!--'],
381+
['I18N blocks should not cross element boundaries', '<!-- /i18n -->'],
382382
['Unclosed block', '<p><!-- /i18n --></p>'],
383383
]);
384384

385385
expect(extractErrors(`<p><!-- i18n --></p><!-- /i18n -->`)).toEqual([
386-
['I18N blocks should not cross element boundaries', '<!--'],
387-
['Unclosed block', '<!--'],
386+
['I18N blocks should not cross element boundaries', '<!-- /i18n -->'],
387+
['Unclosed block', '<!-- /i18n -->'],
388388
]);
389389
});
390390
});

packages/compiler/test/ml_parser/html_parser_spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn, humanizeNodes}
251251
],
252252
[html.Element, 'span', 1, '<span>x {{ expr }<!---->} y</span>', '<span>', '</span>'],
253253
[html.Text, 'x {{ expr }', 2, ['x '], ['{{', ' expr }'], [''], 'x {{ expr }'],
254-
[html.Comment, '', 2, '<!--'],
254+
[html.Comment, '', 2, '<!---->'],
255255
[html.Text, '} y', 2, ['} y'], '} y'],
256256
[html.Element, 'div', 1, '<div></div>', '<div>', '</div>'],
257257
]);

packages/compiler/test/render3/view/parse_template_options_spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,13 @@ describe('collectCommentNodes', () => {
3939
.toEqual('eslint-disable-next-line');
4040
expect(templateCommentsOptionEnabled.commentNodes![0].sourceSpan)
4141
.toBeInstanceOf(ParseSourceSpan);
42+
expect(templateCommentsOptionEnabled.commentNodes![0].sourceSpan.toString())
43+
.toEqual('<!-- eslint-disable-next-line -->');
4244
expect(templateCommentsOptionEnabled.commentNodes![1]).toBeInstanceOf(Comment);
4345
expect(templateCommentsOptionEnabled.commentNodes![1].value).toEqual('some nested comment');
4446
expect(templateCommentsOptionEnabled.commentNodes![1].sourceSpan)
4547
.toBeInstanceOf(ParseSourceSpan);
48+
expect(templateCommentsOptionEnabled.commentNodes![1].sourceSpan.toString())
49+
.toEqual('<!-- some nested comment -->');
4650
});
4751
});

0 commit comments

Comments
 (0)