Skip to content

Commit

Permalink
fix(compiler-cli): preserve user line endings in diagnostic template …
Browse files Browse the repository at this point in the history
…parse (#40597)

Normally the template parsing operation normalizes all template line endings
to '\n' only. This normalization operation causes source mapping errors when
the original template uses '\r\n' line endings.

The compiler already parses templates again to create a "diagnostic"
template AST with accurate source maps, to avoid other parsing issues that
affect source map accuracy. This commit configures this diagnostic parse to
also preserve line endings.

PR Close #40597
  • Loading branch information
alxhub authored and mhevery committed Jan 29, 2021
1 parent 4b3106e commit bd0d191
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 2 deletions.
7 changes: 5 additions & 2 deletions packages/compiler-cli/src/ngtsc/annotations/src/component.ts
Expand Up @@ -869,12 +869,14 @@ export class ComponentDecoratorHandler implements

// Unfortunately, the primary parse of the template above may not contain accurate source map
// information. If used directly, it would result in incorrect code locations in template
// errors, etc. There are two main problems:
// errors, etc. There are three main problems:
//
// 1. `preserveWhitespaces: false` annihilates the correctness of template source mapping, as
// the whitespace transformation changes the contents of HTML text nodes before they're
// parsed into Angular expressions.
// 2. By default, the template parser strips leading trivia characters (like spaces, tabs, and
// 2. `preserveLineEndings: false` causes growing misalignments in templates that use '\r\n'
// line endings, by normalizing them to '\n'.
// 3. By default, the template parser strips leading trivia characters (like spaces, tabs, and
// newlines). This also destroys source mapping information.
//
// In order to guarantee the correctness of diagnostics, templates are parsed a second time
Expand All @@ -885,6 +887,7 @@ export class ComponentDecoratorHandler implements

const {nodes: diagNodes} = parseTemplate(templateStr, template.sourceMapUrl, {
preserveWhitespaces: true,
preserveLineEndings: true,
interpolationConfig: template.interpolationConfig,
range: templateRange ?? undefined,
escapedString,
Expand Down
17 changes: 17 additions & 0 deletions packages/compiler-cli/test/ngtsc/template_typecheck_spec.ts
Expand Up @@ -110,6 +110,23 @@ export declare class AnimationEvent {
env.driveMain();
});

it('should have accurate diagnostics in a template using crlf line endings', () => {
env.write('test.ts', `
import {Component} from '@angular/core';
@Component({
selector: 'test',
templateUrl: './test.html',
})
class TestCmp {}
`);
env.write('test.html', '<span>\r\n{{does_not_exist}}\r\n</span>');

const diags = env.driveDiagnostics();
expect(diags.length).toBe(1);
expect(getSourceCodeForDiagnostic(diags[0])).toBe('does_not_exist');
});

it('should check regular attributes that are directive inputs', () => {
env.tsconfig(
{fullTemplateTypeCheck: true, strictInputTypes: true, strictAttributeTypes: true});
Expand Down
4 changes: 4 additions & 0 deletions packages/compiler/src/render3/view/template.ts
Expand Up @@ -2003,6 +2003,10 @@ export interface ParseTemplateOptions {
* Include whitespace nodes in the parsed output.
*/
preserveWhitespaces?: boolean;
/**
* Preserve original line endings instead of normalizing '\r\n' endings to '\n'.
*/
preserveLineEndings?: boolean;
/**
* How to parse interpolation markers.
*/
Expand Down

0 comments on commit bd0d191

Please sign in to comment.