diff --git a/modules/@angular/compiler/src/template_parser/template_ast.ts b/modules/@angular/compiler/src/template_parser/template_ast.ts index d8d916e173..3669a863aa 100644 --- a/modules/@angular/compiler/src/template_parser/template_ast.ts +++ b/modules/@angular/compiler/src/template_parser/template_ast.ts @@ -124,7 +124,8 @@ export class ElementAst implements TemplateAst { public outputs: BoundEventAst[], public references: ReferenceAst[], public directives: DirectiveAst[], public providers: ProviderAst[], public hasViewContainer: boolean, public children: TemplateAst[], - public ngContentIndex: number, public sourceSpan: ParseSourceSpan) {} + public ngContentIndex: number, public sourceSpan: ParseSourceSpan, + public endSourceSpan: ParseSourceSpan) {} visit(visitor: TemplateAstVisitor, context: any): any { return visitor.visitElement(this, context); diff --git a/modules/@angular/compiler/src/template_parser/template_parser.ts b/modules/@angular/compiler/src/template_parser/template_parser.ts index 0f884f25e5..b3c42efc74 100644 --- a/modules/@angular/compiler/src/template_parser/template_parser.ts +++ b/modules/@angular/compiler/src/template_parser/template_parser.ts @@ -442,8 +442,7 @@ class TemplateParseVisitor implements html.Visitor { nodeName, attrs, elementProps, events, references, providerContext.transformedDirectiveAsts, providerContext.transformProviders, providerContext.transformedHasViewContainer, children, - hasInlineTemplates ? null : ngContentIndex, element.sourceSpan); - + hasInlineTemplates ? null : ngContentIndex, element.sourceSpan, element.endSourceSpan); this._findComponentDirectives(directiveAsts) .forEach( componentDirectiveAst => this._validateElementAnimationInputOutputs( @@ -1083,7 +1082,7 @@ class NonBindableVisitor implements html.Visitor { const children = html.visitAll(this, ast.children, EMPTY_ELEMENT_CONTEXT); return new ElementAst( ast.name, html.visitAll(this, ast.attrs), [], [], [], [], [], false, children, - ngContentIndex, ast.sourceSpan); + ngContentIndex, ast.sourceSpan, ast.endSourceSpan); } visitComment(comment: html.Comment, context: any): any { return null; } diff --git a/modules/@angular/compiler/test/template_parser/template_parser_spec.ts b/modules/@angular/compiler/test/template_parser/template_parser_spec.ts index f378692788..33231ef201 100644 --- a/modules/@angular/compiler/test/template_parser/template_parser_spec.ts +++ b/modules/@angular/compiler/test/template_parser/template_parser_spec.ts @@ -1614,6 +1614,35 @@ Property binding a not used by any directive on an embedded template. Make sure ]); }); + it('should support endSourceSpan for elements', () => { + const tagSel = CompileDirectiveMetadata.create({ + selector: 'circle', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'elDir', reference: {} as Type}) + }); + const result = parse('', [tagSel]); + const circle = result[0] as ElementAst; + expect(circle.endSourceSpan).toBeDefined(); + expect(circle.endSourceSpan.start.offset).toBe(8); + expect(circle.endSourceSpan.end.offset).toBe(17); + }); + + it('should report undefined for endSourceSpan for elements without an end-tag', () => { + const ulSel = CompileDirectiveMetadata.create({ + selector: 'ul', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'ulDir', reference: {} as Type}) + }); + const liSel = CompileDirectiveMetadata.create({ + selector: 'li', + type: new CompileTypeMetadata( + {moduleUrl: someModuleUrl, name: 'liDir', reference: {} as Type}) + }); + const result = parse('
', [ulSel, liSel]); + const ul = result[0] as ElementAst; + const li = ul.children[0] as ElementAst; + expect(li.endSourceSpan).toBe(null); + }); }); describe('pipes', () => { @@ -1825,7 +1854,8 @@ class FooAstTransformer implements TemplateAstVisitor { visitElement(ast: ElementAst, context: any): any { if (ast.name != 'div') return ast; return new ElementAst( - 'foo', [], [], [], [], [], [], false, [], ast.ngContentIndex, ast.sourceSpan); + 'foo', [], [], [], [], [], [], false, [], ast.ngContentIndex, ast.sourceSpan, + ast.endSourceSpan); } visitReference(ast: ReferenceAst, context: any): any { throw 'not implemented'; } visitVariable(ast: VariableAst, context: any): any { throw 'not implemented'; } @@ -1844,7 +1874,8 @@ class BarAstTransformer extends FooAstTransformer { visitElement(ast: ElementAst, context: any): any { if (ast.name != 'foo') return ast; return new ElementAst( - 'bar', [], [], [], [], [], [], false, [], ast.ngContentIndex, ast.sourceSpan); + 'bar', [], [], [], [], [], [], false, [], ast.ngContentIndex, ast.sourceSpan, + ast.endSourceSpan); } }