From 6dc74fd5de79f0d2c15362d8bc8691cf81385e4b Mon Sep 17 00:00:00 2001 From: Krzysztof Grzybek Date: Tue, 7 May 2019 17:50:44 +0200 Subject: [PATCH] fix(compiler): report better error on interpolation in an expression (#30300) Compiler results in weird error message when encounters interpolation inside existing expression context, e.g. *ngIf="name {{ name }}" PR Close #30300 --- .../compiler/src/expression_parser/parser.ts | 3 ++- .../test/expression_parser/parser_spec.ts | 26 +++++++++++++++---- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/packages/compiler/src/expression_parser/parser.ts b/packages/compiler/src/expression_parser/parser.ts index 8af92b4905089..f969e1b3ea12b 100644 --- a/packages/compiler/src/expression_parser/parser.ts +++ b/packages/compiler/src/expression_parser/parser.ts @@ -968,7 +968,8 @@ export class _ParseAST { } else { // Otherwise the key must be a directive keyword, like "of". Transform // the key to actual key. Eg. of -> ngForOf, trackBy -> ngForTrackBy - key.source = templateKey.source + key.source[0].toUpperCase() + key.source.substring(1); + key.source = + templateKey.source + key.source.charAt(0).toUpperCase() + key.source.substring(1); bindings.push(...this.parseDirectiveKeywordBindings(key)); } } diff --git a/packages/compiler/test/expression_parser/parser_spec.ts b/packages/compiler/test/expression_parser/parser_spec.ts index fef9733c5f813..8a5a9687ba643 100644 --- a/packages/compiler/test/expression_parser/parser_spec.ts +++ b/packages/compiler/test/expression_parser/parser_spec.ts @@ -704,6 +704,14 @@ describe('parser', () => { ]); }); + it('should report unexpected token when encountering interpolation', () => { + const attr = '*ngIf="name && {{name}}"'; + + expectParseTemplateBindingsError( + attr, + 'Parser Error: Unexpected token {, expected identifier, keyword, or string at column 10 in [name && {{name}}] in foo.html'); + }); + it('should map variable declaration via "as"', () => { const attr = '*ngFor="let item; of items | slice:0:1 as collection, trackBy: func; index as i"'; @@ -951,17 +959,25 @@ function parseBinding(text: string, location: any = null, offset: number = 0): A } function parseTemplateBindings(attribute: string, templateUrl = 'foo.html'): TemplateBinding[] { + const result = _parseTemplateBindings(attribute, templateUrl); + expect(result.errors).toEqual([]); + expect(result.warnings).toEqual([]); + return result.templateBindings; +} + +function expectParseTemplateBindingsError(attribute: string, error: string) { + const result = _parseTemplateBindings(attribute, 'foo.html'); + expect(result.errors[0].message).toEqual(error); +} + +function _parseTemplateBindings(attribute: string, templateUrl: string) { const match = attribute.match(/^\*(.+)="(.*)"$/); expect(match).toBeTruthy(`failed to extract key and value from ${attribute}`); const [_, key, value] = match; const absKeyOffset = 1; // skip the * prefix const absValueOffset = attribute.indexOf('=') + '="'.length; const parser = createParser(); - const result = - parser.parseTemplateBindings(key, value, templateUrl, absKeyOffset, absValueOffset); - expect(result.errors).toEqual([]); - expect(result.warnings).toEqual([]); - return result.templateBindings; + return parser.parseTemplateBindings(key, value, templateUrl, absKeyOffset, absValueOffset); } function parseInterpolation(text: string, location: any = null, offset: number = 0): ASTWithSource|