fix(compiler): report errors for queries without selectors (#9018)
Fixes #4489
This commit is contained in:
parent
f0e24b1a1e
commit
057abefe50
|
@ -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({
|
||||||
|
|
|
@ -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 {
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue