Skip to content

Commit 7986e7c

Browse files
committed
feat(transformer): Support @Injectable() on static functions
1 parent 311b477 commit 7986e7c

File tree

5 files changed

+75
-13
lines changed

5 files changed

+75
-13
lines changed

modules/angular2/src/reflection/reflector.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,26 @@ export {SetterFn, GetterFn, MethodFn} from './types';
1313
export {PlatformReflectionCapabilities} from './platform_reflection_capabilities';
1414

1515
export class Reflector {
16-
_typeInfo: Map<Type, any>;
16+
_injectableInfo: Map<any, StringMap<string, any>>;
1717
_getters: Map<string, GetterFn>;
1818
_setters: Map<string, SetterFn>;
1919
_methods: Map<string, MethodFn>;
2020
reflectionCapabilities: PlatformReflectionCapabilities;
2121

2222
constructor(reflectionCapabilities: PlatformReflectionCapabilities) {
23-
this._typeInfo = new Map();
23+
this._injectableInfo = new Map();
2424
this._getters = new Map();
2525
this._setters = new Map();
2626
this._methods = new Map();
2727
this.reflectionCapabilities = reflectionCapabilities;
2828
}
2929

30+
registerFunction(func: Function, funcInfo: StringMap<string, any>): void {
31+
this._injectableInfo.set(func, funcInfo);
32+
}
33+
3034
registerType(type: Type, typeInfo: StringMap<string, any>): void {
31-
this._typeInfo.set(type, typeInfo);
35+
this._injectableInfo.set(type, typeInfo);
3236
}
3337

3438
registerGetters(getters: StringMap<string, GetterFn>): void {
@@ -52,23 +56,23 @@ export class Reflector {
5256
}
5357

5458
parameters(typeOrFunc): List<any> {
55-
if (this._typeInfo.has(typeOrFunc)) {
59+
if (this._injectableInfo.has(typeOrFunc)) {
5660
return this._getTypeInfoField(typeOrFunc, "parameters", []);
5761
} else {
5862
return this.reflectionCapabilities.parameters(typeOrFunc);
5963
}
6064
}
6165

6266
annotations(typeOrFunc): List<any> {
63-
if (this._typeInfo.has(typeOrFunc)) {
67+
if (this._injectableInfo.has(typeOrFunc)) {
6468
return this._getTypeInfoField(typeOrFunc, "annotations", []);
6569
} else {
6670
return this.reflectionCapabilities.annotations(typeOrFunc);
6771
}
6872
}
6973

7074
interfaces(type): List<any> {
71-
if (this._typeInfo.has(type)) {
75+
if (this._injectableInfo.has(type)) {
7276
return this._getTypeInfoField(type, "interfaces", []);
7377
} else {
7478
return this.reflectionCapabilities.interfaces(type);
@@ -100,11 +104,11 @@ export class Reflector {
100104
}
101105

102106
_getTypeInfoField(typeOrFunc, key, defaultValue) {
103-
var res = this._typeInfo.get(typeOrFunc)[key];
107+
var res = this._injectableInfo.get(typeOrFunc)[key];
104108
return isPresent(res) ? res : defaultValue;
105109
}
106110

107-
_containsTypeInfo(typeOrFunc) { return this._typeInfo.has(typeOrFunc); }
111+
_containsTypeInfo(typeOrFunc) { return this._injectableInfo.has(typeOrFunc); }
108112
}
109113

110114
function _mergeMaps(target: Map<any, any>, config: StringMap<string, Function>): void {

modules/angular2/src/transform/directive_processor/rewriter.dart

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -172,11 +172,7 @@ class CreateNgDepsVisitor extends Object with SimpleAstVisitor<Object> {
172172

173173
var ctor = _getCtor(node);
174174

175-
if (!_foundNgInjectable) {
176-
// The receiver for cascaded calls.
177-
writer.print(REFLECTOR_VAR_NAME);
178-
_foundNgInjectable = true;
179-
}
175+
_maybeWriteReflector();
180176
writer.print('..registerType(');
181177
node.name.accept(this);
182178
writer.print(''', {'factory': ''');
@@ -236,4 +232,32 @@ class CreateNgDepsVisitor extends Object with SimpleAstVisitor<Object> {
236232

237233
@override
238234
Object visitSimpleIdentifier(SimpleIdentifier node) => _nodeToSource(node);
235+
236+
@override
237+
bool visitFunctionDeclaration(FunctionDeclaration node) {
238+
if (!node.metadata.any((a) => _annotationMatcher.hasMatch(a, assetId))) {
239+
return null;
240+
}
241+
242+
_maybeWriteReflector();
243+
writer.print('..registerFunction(');
244+
node.name.accept(this);
245+
writer.print(''', {'parameters': const [''');
246+
var parameters = node.childEntities
247+
.firstWhere((child) => child is FunctionExpression).parameters;
248+
parameters.accept(_paramsVisitor);
249+
writer.print('''], 'annotations': ''');
250+
node.metadata.accept(_metaVisitor);
251+
writer.print('})');
252+
return null;
253+
}
254+
255+
/// Writes out the reflector variable the first time it is called.
256+
void _maybeWriteReflector() {
257+
if (_foundNgInjectable) return;
258+
_foundNgInjectable = true;
259+
260+
// The receiver for cascaded calls.
261+
writer.print(REFLECTOR_VAR_NAME);
262+
}
239263
}

modules/angular2/test/transform/directive_processor/all_tests.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ void allTests() {
9393
'ERROR: Could not read asset at uri bad_relative_url.css from angular2|'
9494
'test/transform/directive_processor/invalid_url_files/hello.dart'
9595
]);
96+
97+
_testNgDeps('should find and register static functions.',
98+
'static_function_files/hello.dart');
9699
}
97100

98101
void _testNgDeps(String name, String inputPath,
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
library static_function_files.hello.ng_deps.dart;
2+
3+
import 'hello.dart';
4+
import 'package:angular2/angular2.dart';
5+
6+
var _visited = false;
7+
void initReflector(reflector) {
8+
if (_visited) return;
9+
_visited = true;
10+
reflector
11+
..registerFunction(getMessage, {
12+
'parameters': const [const [const Inject(Message)]],
13+
'annotations': const Injectable()
14+
})
15+
..registerType(Message, {
16+
'factory': () => new Message(),
17+
'parameters': const [],
18+
'annotations': const [const Injectable()]
19+
});
20+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
library static_function_files.hello;
2+
3+
import 'package:angular2/angular2.dart';
4+
5+
@Injectable()
6+
String getMessage(@Inject(Message) message) => message.value;
7+
8+
@Injectable()
9+
class Message {
10+
String value = 'hello!';
11+
}

0 commit comments

Comments
 (0)