fix(compiler): report errors for queries without selectors (#9018)

Fixes #4489
This commit is contained in:
Pawel Kozlowski 2016-06-05 04:46:03 +02:00 committed by Miško Hevery
parent f0e24b1a1e
commit 057abefe50
2 changed files with 36 additions and 8 deletions

View File

@ -161,8 +161,8 @@ export class CompileMetadataResolver {
var queries = []; var queries = [];
var viewQueries = []; var viewQueries = [];
if (isPresent(dirMeta.queries)) { if (isPresent(dirMeta.queries)) {
queries = this.getQueriesMetadata(dirMeta.queries, false); queries = this.getQueriesMetadata(dirMeta.queries, false, directiveType);
viewQueries = this.getQueriesMetadata(dirMeta.queries, true); viewQueries = this.getQueriesMetadata(dirMeta.queries, true, directiveType);
} }
meta = cpl.CompileDirectiveMetadata.create({ meta = cpl.CompileDirectiveMetadata.create({
selector: dirMeta.selector, selector: dirMeta.selector,
@ -314,8 +314,8 @@ export class CompileMetadataResolver {
isSelf: isSelf, isSelf: isSelf,
isSkipSelf: isSkipSelf, isSkipSelf: isSkipSelf,
isOptional: isOptional, isOptional: isOptional,
query: isPresent(query) ? this.getQueryMetadata(query, null) : null, query: isPresent(query) ? this.getQueryMetadata(query, null, typeOrFunc) : null,
viewQuery: isPresent(viewQuery) ? this.getQueryMetadata(viewQuery, null) : null, viewQuery: isPresent(viewQuery) ? this.getQueryMetadata(viewQuery, null, typeOrFunc) : null,
token: this.getTokenMetadata(token) token: this.getTokenMetadata(token)
}); });
@ -381,21 +381,24 @@ export class CompileMetadataResolver {
} }
getQueriesMetadata(queries: {[key: string]: QueryMetadata}, getQueriesMetadata(queries: {[key: string]: QueryMetadata},
isViewQuery: boolean): cpl.CompileQueryMetadata[] { isViewQuery: boolean, directiveType: Type): cpl.CompileQueryMetadata[] {
var compileQueries = []; var compileQueries = [];
StringMapWrapper.forEach(queries, (query, propertyName) => { StringMapWrapper.forEach(queries, (query, propertyName) => {
if (query.isViewQuery === isViewQuery) { if (query.isViewQuery === isViewQuery) {
compileQueries.push(this.getQueryMetadata(query, propertyName)); compileQueries.push(this.getQueryMetadata(query, propertyName, directiveType));
} }
}); });
return compileQueries; return compileQueries;
} }
getQueryMetadata(q: QueryMetadata, propertyName: string): cpl.CompileQueryMetadata { getQueryMetadata(q: QueryMetadata, propertyName: string, typeOrFunc: Type | Function): cpl.CompileQueryMetadata {
var selectors; var selectors;
if (q.isVarBindingQuery) { if (q.isVarBindingQuery) {
selectors = q.varBindings.map(varName => this.getTokenMetadata(varName)); selectors = q.varBindings.map(varName => this.getTokenMetadata(varName));
} else { } else {
if (!isPresent(q.selector)) {
throw new BaseException(`Can't construct a query for the property "${propertyName}" of "${stringify(typeOrFunc)}" since the query selector wasn't defined.`);
}
selectors = [this.getTokenMetadata(q.selector)]; selectors = [this.getTokenMetadata(q.selector)];
} }
return new cpl.CompileQueryMetadata({ return new cpl.CompileQueryMetadata({

View File

@ -11,7 +11,7 @@ import {
import {TestComponentBuilder} from '@angular/compiler/testing'; import {TestComponentBuilder} from '@angular/compiler/testing';
import {AsyncTestCompleter} from '@angular/core/testing/testing_internal'; import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
import {isPresent} from '../../src/facade/lang'; import {isPresent, stringify} from '../../src/facade/lang';
import {ObservableWrapper} from '../../src/facade/async'; import {ObservableWrapper} from '../../src/facade/async';
import { import {
@ -262,6 +262,17 @@ export function main() {
async.done(); async.done();
}); });
})); }));
it('should throw with descriptive error when query selectors are not present',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => {
tcb.overrideTemplate(MyCompBroken0, '<has-null-query-condition></has-null-query-condition>')
.createAsync(MyCompBroken0)
.catch((e) => {
expect(e.message).toEqual(
`Can't construct a query for the property "errorTrigger" of "${stringify(HasNullQueryCondition)}" since the query selector wasn't defined.`);
async.done();
});
}));
}); });
describe('query for TemplateRef', () => { describe('query for TemplateRef', () => {
@ -1086,6 +1097,11 @@ class NeedsViewContainerWithRead {
createView() { this.vc.createEmbeddedView(this.template); } createView() { this.vc.createEmbeddedView(this.template); }
} }
@Component({selector: 'has-null-query-condition', template: '<div></div>'})
class HasNullQueryCondition {
@ContentChildren(null) errorTrigger;
}
@Component({ @Component({
selector: 'my-comp', selector: 'my-comp',
directives: [ directives: [
@ -1128,3 +1144,12 @@ class MyComp0 {
this.list = ['1d', '2d', '3d']; this.list = ['1d', '2d', '3d'];
} }
} }
@Component({
selector: 'my-comp',
directives: [HasNullQueryCondition],
template: ''
})
@Injectable()
class MyCompBroken0 {
}