Skip to content

Commit 81beb1c

Browse files
vsavkinvikerman
authored andcommitted
feat(transformers): collect provider information
1 parent 6402d61 commit 81beb1c

File tree

7 files changed

+371
-28
lines changed

7 files changed

+371
-28
lines changed

modules/angular2/src/compiler/directive_metadata.ts

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,15 +177,21 @@ export class CompileProviderMetadata {
177177
static fromJson(data: {[key: string]: any}): CompileProviderMetadata {
178178
return new CompileProviderMetadata({
179179
token: objFromJson(data['token'], CompileIdentifierMetadata.fromJson),
180-
useClass: objFromJson(data['useClass'], CompileTypeMetadata.fromJson)
180+
useClass: objFromJson(data['useClass'], CompileTypeMetadata.fromJson),
181+
useExisting: objFromJson(data['useExisting'], CompileIdentifierMetadata.fromJson),
182+
useValue: objFromJson(data['useValue'], CompileIdentifierMetadata.fromJson),
183+
useFactory: objFromJson(data['useFactory'], CompileFactoryMetadata.fromJson)
181184
});
182185
}
183186

184187
toJson(): {[key: string]: any} {
185188
return {
186189
// Note: Runtime type can't be serialized...
187190
'token': objToJson(this.token),
188-
'useClass': objToJson(this.useClass)
191+
'useClass': objToJson(this.useClass),
192+
'useExisting': objToJson(this.useExisting),
193+
'useValue': objToJson(this.useValue),
194+
'useFactory': objToJson(this.useFactory)
189195
};
190196
}
191197
}
@@ -198,23 +204,43 @@ export class CompileFactoryMetadata implements CompileIdentifierMetadata {
198204
constConstructor: boolean;
199205
diDeps: CompileDiDependencyMetadata[];
200206

201-
constructor({runtime, name, moduleUrl, constConstructor, diDeps}: {
207+
constructor({runtime, name, moduleUrl, prefix, constConstructor, diDeps}: {
202208
runtime?: Function,
203209
name?: string,
210+
prefix?: string,
204211
moduleUrl?: string,
205212
constConstructor?: boolean,
206213
diDeps?: CompileDiDependencyMetadata[]
207214
}) {
208215
this.runtime = runtime;
209216
this.name = name;
217+
this.prefix = prefix;
210218
this.moduleUrl = moduleUrl;
211219
this.diDeps = diDeps;
212220
this.constConstructor = constConstructor;
213221
}
214222

215223
get identifier(): CompileIdentifierMetadata { return this; }
216224

217-
toJson() { return null; }
225+
static fromJson(data: {[key: string]: any}): CompileFactoryMetadata {
226+
return new CompileFactoryMetadata({
227+
name: data['name'],
228+
prefix: data['prefix'],
229+
moduleUrl: data['moduleUrl'],
230+
constConstructor: data['constConstructor'],
231+
diDeps: arrayFromJson(data['diDeps'], CompileDiDependencyMetadata.fromJson)
232+
});
233+
}
234+
235+
toJson(): {[key: string]: any} {
236+
return {
237+
'name': this.name,
238+
'prefix': this.prefix,
239+
'moduleUrl': this.moduleUrl,
240+
'constConstructor': this.constConstructor,
241+
'diDeps': arrayToJson(this.diDeps)
242+
};
243+
}
218244
}
219245

220246
/**

modules/angular2/test/compiler/directive_metadata_spec.ts

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ import {
1818
CompileTemplateMetadata,
1919
CompileProviderMetadata,
2020
CompileDiDependencyMetadata,
21-
CompileQueryMetadata
21+
CompileQueryMetadata,
22+
CompileIdentifierMetadata,
23+
CompileFactoryMetadata
2224
} from 'angular2/src/compiler/directive_metadata';
2325
import {ViewEncapsulation} from 'angular2/src/core/metadata/view';
2426
import {ChangeDetectionStrategy} from 'angular2/src/core/change_detection';
@@ -31,25 +33,21 @@ export function main() {
3133
var fullDirectiveMeta: CompileDirectiveMetadata;
3234

3335
beforeEach(() => {
34-
fullTypeMeta = new CompileTypeMetadata({
35-
name: 'SomeType',
36-
moduleUrl: 'someUrl',
36+
var diDep = new CompileDiDependencyMetadata({
37+
isAttribute: true,
38+
isSelf: true,
3739
isHost: true,
38-
diDeps: [
39-
new CompileDiDependencyMetadata({
40-
isAttribute: true,
41-
isSelf: true,
42-
isHost: true,
43-
isSkipSelf: true,
44-
isOptional: true,
45-
token: 'someToken',
46-
query: new CompileQueryMetadata(
47-
{selectors: ['one'], descendants: true, first: true, propertyName: 'one'}),
48-
viewQuery: new CompileQueryMetadata(
49-
{selectors: ['one'], descendants: true, first: true, propertyName: 'one'})
50-
})
51-
]
40+
isSkipSelf: true,
41+
isOptional: true,
42+
token: 'someToken',
43+
query: new CompileQueryMetadata(
44+
{selectors: ['one'], descendants: true, first: true, propertyName: 'one'}),
45+
viewQuery: new CompileQueryMetadata(
46+
{selectors: ['one'], descendants: true, first: true, propertyName: 'one'})
5247
});
48+
49+
fullTypeMeta = new CompileTypeMetadata(
50+
{name: 'SomeType', moduleUrl: 'someUrl', isHost: true, diDeps: [diDep]});
5351
fullTemplateMeta = new CompileTemplateMetadata({
5452
encapsulation: ViewEncapsulation.Emulated,
5553
template: '<a></a>',
@@ -69,7 +67,15 @@ export function main() {
6967
outputs: ['someEvent'],
7068
host: {'(event1)': 'handler1', '[prop1]': 'expr1', 'attr1': 'attrValue2'},
7169
lifecycleHooks: [LifecycleHooks.OnChanges],
72-
providers: [new CompileProviderMetadata({token: 'token', useClass: fullTypeMeta})]
70+
providers: [
71+
new CompileProviderMetadata({
72+
token: 'token',
73+
useClass: fullTypeMeta,
74+
useExisting: new CompileIdentifierMetadata({name: 'someName'}),
75+
useFactory: new CompileFactoryMetadata({name: 'someName', diDeps: [diDep]}),
76+
useValue: 'someValue',
77+
})
78+
]
7379
});
7480

7581
});

modules_dart/transform/lib/src/transform/common/type_metadata_reader.dart

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,14 +431,38 @@ class _DirectiveMetadataVisitor extends Object
431431
) {
432432
final token = el.argumentList.arguments.first;
433433

434-
var useClass;
434+
var useClass, useExisting, useValue, factoryId, useFactory, deps;
435435
el.argumentList.arguments.skip(1).forEach((arg) {
436436
if (arg.name.toString() == "useClass:") {
437437
final id = _readIdentifier(arg.expression);
438438
useClass = new CompileTypeMetadata(prefix: id.prefix, name: id.name);
439+
} else if (arg.name.toString() == "toClass:") {
440+
final id = _readIdentifier(arg.expression);
441+
useClass = new CompileTypeMetadata(prefix: id.prefix, name: id.name);
442+
443+
} else if (arg.name.toString() == "useExisting:") {
444+
useExisting = _readIdentifier(arg.expression);
445+
} else if (arg.name.toString() == "toAlias:") {
446+
useExisting = _readIdentifier(arg.expression);
447+
448+
} else if (arg.name.toString() == "useValue:") {
449+
useValue = _readIdentifier(arg.expression);
450+
} else if (arg.name.toString() == "toValue:") {
451+
useValue = _readIdentifier(arg.expression);
452+
453+
} else if (arg.name.toString() == "useFactory:") {
454+
factoryId = _readIdentifier(arg.expression);
455+
} else if (arg.name.toString() == "toFactory:") {
456+
factoryId = _readIdentifier(arg.expression);
457+
458+
} else if (arg.name.toString() == "deps:") {
459+
deps = _readDeps(arg.expression);
439460
}
440461
});
441-
return new CompileProviderMetadata(token: _readIdentifier(token), useClass: useClass);
462+
if (factoryId != null) {
463+
useFactory = new CompileFactoryMetadata(name: factoryId.name, prefix: factoryId.prefix);
464+
}
465+
return new CompileProviderMetadata(token: _readIdentifier(token), useClass: useClass, useExisting: useExisting, useValue: useValue, useFactory: useFactory, deps: deps);
442466

443467
} else {
444468
throw new ArgumentError(
@@ -451,6 +475,29 @@ class _DirectiveMetadataVisitor extends Object
451475
}
452476
}
453477

478+
List<CompileDiDependencyMetadata> _readDeps(ListLiteral deps) {
479+
return deps.elements.map((p) {
480+
final list = p is ListLiteral ? p.elements : [p];
481+
final first = list.first;
482+
483+
var token;
484+
if (first is InstanceCreationExpression && first.constructorName.toString() == "Inject") {
485+
token = _readIdentifier(first.argumentList.arguments[0]);
486+
} else {
487+
token = _readIdentifier(first);
488+
}
489+
490+
return new CompileDiDependencyMetadata(
491+
token: token,
492+
isSelf: _hasConst(list, "Self"),
493+
isHost: _hasConst(list, "Host"),
494+
isSkipSelf: _hasConst(list, "SkipSelf"),
495+
isOptional: _hasConst(list, "Optional"));
496+
}).toList();
497+
}
498+
499+
bool _hasConst(List list, String name) => list.where((m) => m is InstanceCreationExpression && m.constructorName.toString() == name).isNotEmpty;
500+
454501
//TODO Use AnnotationMatcher instead of string matching
455502
bool _isAnnotation(Annotation node, String annotationName) {
456503
var id = node.name;

modules_dart/transform/lib/src/transform/template_compiler/compile_data_creator.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,17 @@ class _CompileDataCreator {
162162
if (provider.useClass != null) {
163163
provider.useClass = _resolveIdentifier(ngMetaMap, neededBy, provider.useClass);
164164
}
165+
if (provider.useExisting != null) {
166+
provider.useExisting = _resolveIdentifier(ngMetaMap, neededBy, provider.useExisting);
167+
}
168+
if (provider.useValue != null) {
169+
provider.useValue = _resolveIdentifier(ngMetaMap, neededBy, provider.useValue);
170+
}
171+
if (provider.useFactory != null) {
172+
final resolved = _resolveIdentifier(ngMetaMap, neededBy, provider.useFactory);
173+
provider.useFactory.moduleUrl = resolved.moduleUrl;
174+
_resolveDiDependencyMetadata(ngMetaMap, neededBy, provider.useFactory.diDeps);
175+
}
165176
resolvedProviders.add(provider);
166177
}
167178
}

modules_dart/transform/test/transform/directive_processor/all_tests.dart

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,160 @@ void allTests() {
671671
expect(useClass.name).toEqual("ServiceDep");
672672
});
673673

674+
it('should populate `providers` using toClass.',
675+
() async {
676+
var cmp =
677+
(await _testCreateModel('directives_files/components.dart')).identifiers['ComponentWithProvidersToClass'];
678+
679+
expect(cmp).toBeNotNull();
680+
expect(cmp.providers).toBeNotNull();
681+
expect(cmp.providers.length).toEqual(1);
682+
683+
var token = cmp.providers.first.token;
684+
var useExisting = cmp.providers.first.useClass;
685+
686+
expect(useExisting.prefix).toEqual(null);
687+
expect(useExisting.name).toEqual("ServiceDep");
688+
});
689+
690+
it('should populate `providers` using useExisting.',
691+
() async {
692+
var cmp =
693+
(await _testCreateModel('directives_files/components.dart')).identifiers['ComponentWithProvidersUseExisting'];
694+
695+
expect(cmp).toBeNotNull();
696+
expect(cmp.providers).toBeNotNull();
697+
expect(cmp.providers.length).toEqual(1);
698+
699+
var token = cmp.providers.first.token;
700+
var useExisting = cmp.providers.first.useExisting;
701+
702+
expect(useExisting.prefix).toEqual(null);
703+
expect(useExisting.name).toEqual("ServiceDep");
704+
});
705+
706+
it('should populate `providers` using toAlias.',
707+
() async {
708+
var cmp =
709+
(await _testCreateModel('directives_files/components.dart')).identifiers['ComponentWithProvidersToAlias'];
710+
711+
expect(cmp).toBeNotNull();
712+
expect(cmp.providers).toBeNotNull();
713+
expect(cmp.providers.length).toEqual(1);
714+
715+
var token = cmp.providers.first.token;
716+
var useExisting = cmp.providers.first.useExisting;
717+
718+
expect(useExisting.prefix).toEqual(null);
719+
expect(useExisting.name).toEqual("ServiceDep");
720+
});
721+
722+
it('should populate `providers` using useExisting (string token).',
723+
() async {
724+
var cmp =
725+
(await _testCreateModel('directives_files/components.dart')).identifiers['ComponentWithProvidersUseExistingStr'];
726+
727+
expect(cmp).toBeNotNull();
728+
expect(cmp.providers).toBeNotNull();
729+
expect(cmp.providers.length).toEqual(1);
730+
731+
var token = cmp.providers.first.token;
732+
var useExisting = cmp.providers.first.useExisting;
733+
734+
expect(useExisting).toEqual("StrToken");
735+
});
736+
737+
it('should populate `providers` using useValue.',
738+
() async {
739+
var cmp =
740+
(await _testCreateModel('directives_files/components.dart')).identifiers['ComponentWithProvidersUseValue'];
741+
742+
expect(cmp).toBeNotNull();
743+
expect(cmp.providers).toBeNotNull();
744+
expect(cmp.providers.length).toEqual(1);
745+
746+
var token = cmp.providers.first.token;
747+
var useValue = cmp.providers.first.useValue;
748+
749+
expect(useValue.prefix).toEqual(null);
750+
expect(useValue.name).toEqual("ServiceDep");
751+
});
752+
753+
it('should populate `providers` using toValue.',
754+
() async {
755+
var cmp =
756+
(await _testCreateModel('directives_files/components.dart')).identifiers['ComponentWithProvidersToValue'];
757+
758+
expect(cmp).toBeNotNull();
759+
expect(cmp.providers).toBeNotNull();
760+
expect(cmp.providers.length).toEqual(1);
761+
762+
var token = cmp.providers.first.token;
763+
var useValue = cmp.providers.first.useValue;
764+
765+
expect(useValue.prefix).toEqual(null);
766+
expect(useValue.name).toEqual("ServiceDep");
767+
});
768+
769+
it('should populate `providers` using useValue (string token).',
770+
() async {
771+
var cmp =
772+
(await _testCreateModel('directives_files/components.dart')).identifiers['ComponentWithProvidersUseValueStr'];
773+
774+
expect(cmp).toBeNotNull();
775+
expect(cmp.providers).toBeNotNull();
776+
expect(cmp.providers.length).toEqual(1);
777+
778+
var token = cmp.providers.first.token;
779+
var useValue = cmp.providers.first.useValue;
780+
781+
expect(useValue).toEqual("StrToken");
782+
});
783+
784+
it('should populate `providers` using useFactory.',
785+
() async {
786+
var cmp =
787+
(await _testCreateModel('directives_files/components.dart')).identifiers['ComponentWithProvidersUseFactory'];
788+
789+
expect(cmp).toBeNotNull();
790+
expect(cmp.providers).toBeNotNull();
791+
expect(cmp.providers.length).toEqual(1);
792+
793+
var token = cmp.providers.first.token;
794+
var useFactory = cmp.providers.first.useFactory;
795+
var deps = cmp.providers.first.deps;
796+
797+
expect(useFactory.prefix).toEqual(null);
798+
expect(useFactory.name).toEqual("funcDep");
799+
800+
expect(deps[0].token.name).toEqual("ServiceDep");
801+
expect(deps[1].token).toEqual("Str");
802+
expect(deps[2].token.name).toEqual("ServiceDep");
803+
expect(deps[3].token.name).toEqual("ServiceDep");
804+
expect(deps[3].isSelf).toEqual(true);
805+
expect(deps[4].token.name).toEqual("ServiceDep");
806+
expect(deps[4].isSkipSelf).toEqual(true);
807+
expect(deps[5].token.name).toEqual("ServiceDep");
808+
expect(deps[5].isOptional).toEqual(true);
809+
});
810+
811+
it('should populate `providers` using toFactory.',
812+
() async {
813+
var cmp =
814+
(await _testCreateModel('directives_files/components.dart')).identifiers['ComponentWithProvidersToFactory'];
815+
816+
expect(cmp).toBeNotNull();
817+
expect(cmp.providers).toBeNotNull();
818+
expect(cmp.providers.length).toEqual(1);
819+
820+
var token = cmp.providers.first.token;
821+
var useFactory = cmp.providers.first.useFactory;
822+
var deps = cmp.providers.first.deps;
823+
824+
expect(useFactory.prefix).toEqual(null);
825+
expect(useFactory.name).toEqual("funcDep");
826+
});
827+
674828
it('should populate `providers` using a string token.',
675829
() async {
676830
var cmp =

0 commit comments

Comments
 (0)