From 94e790d4ee44236da56832035bf3a4f230e5b839 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 e87c2c3b61..958f7e1230 100644 --- a/packages/compiler/src/expression_parser/parser.ts +++ b/packages/compiler/src/expression_parser/parser.ts @@ -974,7 +974,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 4b96ffa70e..0bc5323920 100644 --- a/packages/compiler/test/expression_parser/parser_spec.ts +++ b/packages/compiler/test/expression_parser/parser_spec.ts @@ -779,6 +779,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"'; @@ -1026,17 +1034,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|