feat(transformers): collect information for CompileDiDependencyMetadata

This commit is contained in:
vsavkin 2016-02-26 12:43:38 -08:00
parent f60fa14767
commit 39b6e0efba
7 changed files with 146 additions and 12 deletions

View File

@ -120,14 +120,29 @@ export class CompileDiDependencyMetadata {
}
static fromJson(data: {[key: string]: any}): CompileDiDependencyMetadata {
return new CompileDiDependencyMetadata(
{token: objFromJson(data['token'], CompileIdentifierMetadata.fromJson)});
return new CompileDiDependencyMetadata({
token: objFromJson(data['token'], CompileIdentifierMetadata.fromJson),
query: objFromJson(data['query'], CompileQueryMetadata.fromJson),
viewQuery: objFromJson(data['viewQuery'], CompileQueryMetadata.fromJson),
isAttribute: data['isAttribute'],
isSelf: data['isSelf'],
isHost: data['isHost'],
isSkipSelf: data['isSkipSelf'],
isOptional: data['isOptional']
});
}
toJson(): {[key: string]: any} {
return {
// Note: Runtime type can't be serialized...
'token': objToJson(this.token)
'token': objToJson(this.token),
'query': objToJson(this.query),
'viewQuery': objToJson(this.viewQuery),
'isAttribute': this.isAttribute,
'isSelf': this.isSelf,
'isHost': this.isHost,
'isSkipSelf': this.isSkipSelf,
'isOptional': this.isOptional
};
}
}
@ -274,9 +289,28 @@ export class CompileQueryMetadata {
} = {}) {
this.selectors = selectors;
this.descendants = descendants;
this.first = first;
this.first = normalizeBool(first);
this.propertyName = propertyName;
}
static fromJson(data: {[key: string]: any}): CompileQueryMetadata {
return new CompileQueryMetadata({
selectors: arrayFromJson(data['selectors'], CompileIdentifierMetadata.fromJson),
descendants: data['descendants'],
first: data['first'],
propertyName: data['propertyName']
});
}
toJson(): {[key: string]: any} {
return {
// Note: Runtime type can't be serialized...
'selectors': arrayToJson(this.selectors),
'descendants': this.descendants,
'first': this.first,
'propertyName': this.propertyName
};
}
}
/**
@ -581,11 +615,11 @@ var _COMPILE_METADATA_FROM_JSON = {
};
function arrayFromJson(obj: any[], fn: (a: {[key: string]: any}) => any): any {
return isBlank(obj) ? null : obj.map(fn);
return isBlank(obj) ? null : obj.map(o => objFromJson(o, fn));
}
function arrayToJson(obj: any[]): string | {[key: string]: any} {
return isBlank(obj) ? null : obj.map(o => o.toJson());
return isBlank(obj) ? null : obj.map(objToJson);
}
function objFromJson(obj: any, fn: (a: {[key: string]: any}) => any): any {

View File

@ -16,7 +16,9 @@ import {
CompileDirectiveMetadata,
CompileTypeMetadata,
CompileTemplateMetadata,
CompileProviderMetadata
CompileProviderMetadata,
CompileDiDependencyMetadata,
CompileQueryMetadata
} from 'angular2/src/compiler/directive_metadata';
import {ViewEncapsulation} from 'angular2/src/core/metadata/view';
import {ChangeDetectionStrategy} from 'angular2/src/core/change_detection';
@ -29,8 +31,25 @@ export function main() {
var fullDirectiveMeta: CompileDirectiveMetadata;
beforeEach(() => {
fullTypeMeta = new CompileTypeMetadata(
{name: 'SomeType', moduleUrl: 'someUrl', isHost: true, diDeps: []});
fullTypeMeta = new CompileTypeMetadata({
name: 'SomeType',
moduleUrl: 'someUrl',
isHost: true,
diDeps: [
new CompileDiDependencyMetadata({
isAttribute: true,
isSelf: true,
isHost: true,
isSkipSelf: true,
isOptional: true,
token: 'someToken',
query: new CompileQueryMetadata(
{selectors: ['one'], descendants: true, first: true, propertyName: 'one'}),
viewQuery: new CompileQueryMetadata(
{selectors: ['one'], descendants: true, first: true, propertyName: 'one'})
})
]
});
fullTemplateMeta = new CompileTemplateMetadata({
encapsulation: ViewEncapsulation.Emulated,
template: '<a></a>',

View File

@ -185,9 +185,34 @@ class _CompileTypeMetadataVisitor extends Object
final typeToken = p is SimpleFormalParameter && p.type != null ? _readIdentifier(p.type.name) : null;
final injectTokens = p.metadata.where((m) => m.name.toString() == "Inject").map((m) => _readIdentifier(m.arguments.arguments[0]));
final token = injectTokens.isNotEmpty ? injectTokens.first : typeToken;
return new CompileDiDependencyMetadata(token: token);
final query = _hasAnnotation(p, "Query") ? _createQueryMetadata(_getAnnotation(p, "Query")) : null;
final viewQuery = _hasAnnotation(p, "ViewQuery") ? _createQueryMetadata(_getAnnotation(p, "ViewQuery")) : null;
return new CompileDiDependencyMetadata(
token: token,
isAttribute: _hasAnnotation(p, "Attribute"),
isSelf: _hasAnnotation(p, "Self"),
isHost: _hasAnnotation(p, "Host"),
isSkipSelf: _hasAnnotation(p, "SkipSelf"),
isOptional: _hasAnnotation(p, "Optional"),
query: query,
viewQuery: viewQuery);
}).toList();
}
_getAnnotation(p, String attrName) => p.metadata.where((m) => m.name.toString() == attrName).first;
_hasAnnotation(p, String attrName) => p.metadata.where((m) => m.name.toString() == attrName).isNotEmpty;
_createQueryMetadata(Annotation a) {
final selector = _readIdentifier(a.arguments.arguments.first);
var descendants = false;
a.arguments.arguments.skip(0).forEach((arg) {
if (arg is NamedExpression && arg.name.toString() == "descendants:")
descendants = naiveEval(arg.expression);
});
final selectors = selector is String ? selector.split(",") : [selector];
return new CompileQueryMetadata(selectors: selectors, descendants: descendants);
}
}

View File

@ -174,6 +174,12 @@ class _CompileDataCreator {
if (deps == null) return;
for (var dep in deps) {
dep.token = _resolveIdentifier(ngMetaMap, neededBy, dep.token);
if (dep.query != null) {
dep.query.selectors = dep.query.selectors.map((s) => _resolveIdentifier(ngMetaMap, neededBy, s)).toList();
}
if (dep.viewQuery != null) {
dep.viewQuery.selectors = dep.viewQuery.selectors.map((s) => _resolveIdentifier(ngMetaMap, neededBy, s)).toList();
}
}
}

View File

@ -597,9 +597,17 @@ void allTests() {
expect(cmp).toBeNotNull();
var deps = cmp.type.diDeps;
expect(deps).toBeNotNull();
expect(deps.length).toEqual(2);
expect(deps.length).toEqual(8);
expect(deps[0].token.name).toEqual("ServiceDep");
expect(deps[1].token.name).toEqual("ServiceDep");
expect(deps[2].isAttribute).toEqual(true);
expect(deps[3].isSelf).toEqual(true);
expect(deps[4].isSkipSelf).toEqual(true);
expect(deps[5].isOptional).toEqual(true);
expect(deps[6].query.selectors[0].name).toEqual("ServiceDep");
expect(deps[6].query.descendants).toEqual(true);
expect(deps[7].viewQuery.selectors[0]).toEqual("one");
expect(deps[7].viewQuery.selectors[1]).toEqual("two");
});
it('should populate `diDependency` using a string token.',

View File

@ -115,7 +115,16 @@ class ComponentWithProvidersUseClass {}
selector: 'component-with-di-deps',
template: '')
class ComponentWithDiDeps {
ComponentWithDiDeps(ServiceDep arg1, @Inject(ServiceDep) arg2);
ComponentWithDiDeps(
ServiceDep arg1,
@Inject(ServiceDep) arg2,
@Attribute('one') arg3,
@Self() ServiceDep arg4,
@SkipSelf() ServiceDep arg5,
@Optional() ServiceDep arg6,
@Query(ServiceDep, descendants:true) arg6,
@ViewQuery("one,two") arg7
);
}
@Component(

View File

@ -179,6 +179,39 @@ void allTests() {
expect(cmp.type.diDeps[0].token.moduleUrl).toEqual("moduleUrl");
});
it('should resolve queries and viewQueries.', () async {
barNgMeta.identifiers['Service'] = new CompileTypeMetadata(name: 'Service', moduleUrl: 'moduleUrl');
fooComponentMeta.template = new CompileTemplateMetadata(template: "import 'bar.dart';");
fooComponentMeta.type.diDeps = [
new CompileDiDependencyMetadata(
token: 'someToken',
query: new CompileQueryMetadata(selectors: [new CompileIdentifierMetadata(name: 'Service')])
),
new CompileDiDependencyMetadata(
token: 'someToken',
viewQuery: new CompileQueryMetadata(selectors: [new CompileIdentifierMetadata(name: 'Service')])
)
];
final viewAnnotation = new AnnotationModel()..name = 'View'..isView = true;
final reflectable = fooNgMeta.ngDeps.reflectables.first;
reflectable.annotations.add(viewAnnotation);
fooNgMeta.ngDeps.imports.add(new ImportModel()..uri = 'package:a/bar.dart');
updateReader();
final viewDefResults = await createCompileData(reader, fooAssetId, [], []);
final cmp = viewDefResults.viewDefinitions.values.first.component;
expect(cmp.type.diDeps.length).toEqual(2);
expect(cmp.type.diDeps[0].query.selectors[0].name).toEqual("Service");
expect(cmp.type.diDeps[0].query.selectors[0].moduleUrl).toEqual("moduleUrl");
expect(cmp.type.diDeps[1].viewQuery.selectors[0].name).toEqual("Service");
expect(cmp.type.diDeps[1].viewQuery.selectors[0].moduleUrl).toEqual("moduleUrl");
});
it('should generate providers from Provider objects (references).', () async {
barNgMeta.identifiers['Service1'] = new CompileTypeMetadata(name: 'Service1', moduleUrl: 'moduleUrl');
barNgMeta.identifiers['Service2'] = new CompileTypeMetadata(name: 'Service2', moduleUrl: 'moduleUrl');