fix(compiler): throw an error if variable with the same name is already defined. (#7209)

* fix(compiler): throw an error if variable with the same name is already defined. Closes #6492

* fix(compiler): Clean up formatting for issue #6492

* fix(compiler): throw an error if reference with the same name is already defined.

Closes #6492
This commit is contained in:
Andrii Nechytailov 2016-05-26 23:04:17 +03:00 committed by Miško Hevery
parent 263122ea5f
commit 9036f78b74
3 changed files with 40 additions and 5 deletions

View File

@ -155,6 +155,9 @@ export class TemplateParser {
} else { } else {
result = []; result = [];
} }
this._assertNoReferenceDuplicationOnTemplate(result, errors);
if (errors.length > 0) { if (errors.length > 0) {
return new TemplateParseResult(result, errors); return new TemplateParseResult(result, errors);
} }
@ -164,6 +167,25 @@ export class TemplateParser {
} }
return new TemplateParseResult(result, errors); return new TemplateParseResult(result, errors);
} }
_assertNoReferenceDuplicationOnTemplate(result:any[], errors:TemplateParseError[]):void {
const existingReferences = [];
result
.filter(element => !!element.references)
.forEach(element => element.references.forEach(reference=> {
const name = reference.name;
if (existingReferences.indexOf(name) < 0) {
existingReferences.push(name);
}
else {
const error = new TemplateParseError(
`Reference "#${name}" is defined several times`,
reference.sourceSpan,
ParseErrorLevel.FATAL);
errors.push(error);
}
}));
}
} }
class TemplateParseVisitor implements HtmlAstVisitor { class TemplateParseVisitor implements HtmlAstVisitor {
@ -522,9 +544,11 @@ class TemplateParseVisitor implements HtmlAstVisitor {
private _parseVariable(identifier: string, value: string, sourceSpan: ParseSourceSpan, private _parseVariable(identifier: string, value: string, sourceSpan: ParseSourceSpan,
targetVars: VariableAst[]) { targetVars: VariableAst[]) {
if (identifier.indexOf('-') > -1) { if (identifier.indexOf('-') > -1) {
this._reportError(`"-" is not allowed in variable names`, sourceSpan); this._reportError(`"-" is not allowed in variable names`, sourceSpan);
} }
targetVars.push(new VariableAst(identifier, value, sourceSpan)); targetVars.push(new VariableAst(identifier, value, sourceSpan));
} }
@ -533,6 +557,7 @@ class TemplateParseVisitor implements HtmlAstVisitor {
if (identifier.indexOf('-') > -1) { if (identifier.indexOf('-') > -1) {
this._reportError(`"-" is not allowed in reference names`, sourceSpan); this._reportError(`"-" is not allowed in reference names`, sourceSpan);
} }
targetRefs.push(new ElementOrDirectiveRef(identifier, value, sourceSpan)); targetRefs.push(new ElementOrDirectiveRef(identifier, value, sourceSpan));
} }

View File

@ -822,6 +822,16 @@ There is no directive with "exportAs" set to "dirA" ("<div [ERROR ->]#a="dirA"><
"let-" is only supported on template elements. ("<div [ERROR ->]let-a></div>"): TestComp@0:5`); "let-" is only supported on template elements. ("<div [ERROR ->]let-a></div>"): TestComp@0:5`);
}); });
it('should report duplicate reference names', () => {
expect(() => parse('<div #a></div><div #a></div>', []))
.toThrowError(`Template parse errors:
Reference "#a" is defined several times ("<div #a></div><div [ERROR ->]#a></div>"): TestComp@0:19`);
});
it('should not throw error when there is same reference name in different templates', () => {
expect(() => parse('<div #a><template #a><span>OK</span></template></div>', [])).not.toThrowError();
});
it('should assign references with empty value to components', () => { it('should assign references with empty value to components', () => {
var dirA = CompileDirectiveMetadata.create({ var dirA = CompileDirectiveMetadata.create({
selector: '[a]', selector: '[a]',

View File

@ -1059,11 +1059,11 @@ class NeedsContentChildWithRead {
@Component({ @Component({
selector: 'needs-view-children-read', selector: 'needs-view-children-read',
template: '<div #q text="va"></div><div #q text="vb"></div>', template: '<div #q text="va"></div><div #w text="vb"></div>',
directives: [TextDirective] directives: [TextDirective]
}) })
class NeedsViewChildrenWithRead { class NeedsViewChildrenWithRead {
@ViewChildren('q', {read: TextDirective}) textDirChildren: QueryList<TextDirective>; @ViewChildren('q,w', {read: TextDirective}) textDirChildren: QueryList<TextDirective>;
@ViewChildren('nonExisting', {read: TextDirective}) nonExistingVar: QueryList<TextDirective>; @ViewChildren('nonExisting', {read: TextDirective}) nonExistingVar: QueryList<TextDirective>;
} }