diff --git a/modules/@angular/compiler/src/parse_util.ts b/modules/@angular/compiler/src/parse_util.ts index aea4387a21..43ea774853 100644 --- a/modules/@angular/compiler/src/parse_util.ts +++ b/modules/@angular/compiler/src/parse_util.ts @@ -22,7 +22,8 @@ export class ParseSourceFile { } export class ParseSourceSpan { - constructor(public start: ParseLocation, public end: ParseLocation) {} + constructor( + public start: ParseLocation, public end: ParseLocation, public details: string = null) {} toString(): string { return this.start.file.content.substring(this.start.offset, this.end.offset); @@ -43,6 +44,7 @@ export abstract class ParseError { var source = this.span.start.file.content; var ctxStart = this.span.start.offset; var contextStr = ''; + var details = ''; if (isPresent(ctxStart)) { if (ctxStart > source.length - 1) { ctxStart = source.length - 1; @@ -77,6 +79,9 @@ export abstract class ParseError { source.substring(this.span.start.offset, ctxEnd + 1); contextStr = ` ("${context}")`; } - return `${this.msg}${contextStr}: ${this.span.start}`; + if (this.span.details) { + details = `, ${this.span.details}`; + } + return `${this.msg}${contextStr}: ${this.span.start}${details}`; } } diff --git a/modules/@angular/compiler/src/template_parser.ts b/modules/@angular/compiler/src/template_parser.ts index 59ddfef19c..fdae70f235 100644 --- a/modules/@angular/compiler/src/template_parser.ts +++ b/modules/@angular/compiler/src/template_parser.ts @@ -675,10 +675,12 @@ class TemplateParseVisitor implements HtmlAstVisitor { private _createDirectiveAsts( isTemplateElement: boolean, elementName: string, directives: CompileDirectiveMetadata[], props: BoundElementOrDirectiveProperty[], elementOrDirectiveRefs: ElementOrDirectiveRef[], - sourceSpan: ParseSourceSpan, targetReferences: ReferenceAst[]): DirectiveAst[] { + elementSourceSpan: ParseSourceSpan, targetReferences: ReferenceAst[]): DirectiveAst[] { const matchedReferences = new Set(); let component: CompileDirectiveMetadata = null; const directiveAsts = directives.map((directive: CompileDirectiveMetadata) => { + const sourceSpan = new ParseSourceSpan( + elementSourceSpan.start, elementSourceSpan.end, `Directive ${directive.type.name}`); if (directive.isComponent) { component = directive; } diff --git a/modules/@angular/compiler/test/template_parser_spec.ts b/modules/@angular/compiler/test/template_parser_spec.ts index 1c752aa543..480207af0e 100644 --- a/modules/@angular/compiler/test/template_parser_spec.ts +++ b/modules/@angular/compiler/test/template_parser_spec.ts @@ -308,7 +308,7 @@ export function main() { expect(console.warnings).toEqual([[ 'Template parse warnings:', - `Assigning animation triggers within host data as attributes such as "@prop": "exp" is deprecated. Use "[@prop]": "exp" instead! ("[ERROR ->]
"): TestComp@0:0` + `Assigning animation triggers within host data as attributes such as "@prop": "exp" is deprecated. Use "[@prop]": "exp" instead! ("[ERROR ->]
"): TestComp@0:0, Directive DirA` ].join('\n')]); }); @@ -1235,6 +1235,16 @@ Can't have multiple template bindings on one element. Use only one attribute nam Can't bind to 'invalidProp' since it isn't a known native property ("
][invalidProp]>
"): TestComp@0:5`); }); + it('should report invalid host property names', () => { + var dirA = CompileDirectiveMetadata.create({ + selector: 'div', + type: new CompileTypeMetadata({moduleUrl: someModuleUrl, name: 'DirA'}), + host: {'[invalidProp]': 'someProp'} + }); + expect(() => parse('
', [dirA])).toThrowError(`Template parse errors: +Can't bind to 'invalidProp' since it isn't a known native property ("[ERROR ->]
"): TestComp@0:0, Directive DirA`); + }); + it('should report errors in expressions', () => { expect(() => parse('
', [])).toThrowError(`Template parse errors: Parser Error: Unexpected token 'b' at column 3 in [a b] in TestComp@0:5 ("
][prop]="a b">
"): TestComp@0:5`);