feat(transformer): Support @Injectable() on static functions
This commit is contained in:
@ -13,22 +13,26 @@ export {SetterFn, GetterFn, MethodFn} from './types';
|
|||||||
export {PlatformReflectionCapabilities} from './platform_reflection_capabilities';
|
export {PlatformReflectionCapabilities} from './platform_reflection_capabilities';
|
||||||
|
|
||||||
export class Reflector {
|
export class Reflector {
|
||||||
_typeInfo: Map<Type, any>;
|
_injectableInfo: Map<any, StringMap<string, any>>;
|
||||||
_getters: Map<string, GetterFn>;
|
_getters: Map<string, GetterFn>;
|
||||||
_setters: Map<string, SetterFn>;
|
_setters: Map<string, SetterFn>;
|
||||||
_methods: Map<string, MethodFn>;
|
_methods: Map<string, MethodFn>;
|
||||||
reflectionCapabilities: PlatformReflectionCapabilities;
|
reflectionCapabilities: PlatformReflectionCapabilities;
|
||||||
|
|
||||||
constructor(reflectionCapabilities: PlatformReflectionCapabilities) {
|
constructor(reflectionCapabilities: PlatformReflectionCapabilities) {
|
||||||
this._typeInfo = new Map();
|
this._injectableInfo = new Map();
|
||||||
this._getters = new Map();
|
this._getters = new Map();
|
||||||
this._setters = new Map();
|
this._setters = new Map();
|
||||||
this._methods = new Map();
|
this._methods = new Map();
|
||||||
this.reflectionCapabilities = reflectionCapabilities;
|
this.reflectionCapabilities = reflectionCapabilities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registerFunction(func: Function, funcInfo: StringMap<string, any>): void {
|
||||||
|
this._injectableInfo.set(func, funcInfo);
|
||||||
|
}
|
||||||
|
|
||||||
registerType(type: Type, typeInfo: StringMap<string, any>): void {
|
registerType(type: Type, typeInfo: StringMap<string, any>): void {
|
||||||
this._typeInfo.set(type, typeInfo);
|
this._injectableInfo.set(type, typeInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
registerGetters(getters: StringMap<string, GetterFn>): void {
|
registerGetters(getters: StringMap<string, GetterFn>): void {
|
||||||
@ -52,7 +56,7 @@ export class Reflector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
parameters(typeOrFunc): List<any> {
|
parameters(typeOrFunc): List<any> {
|
||||||
if (this._typeInfo.has(typeOrFunc)) {
|
if (this._injectableInfo.has(typeOrFunc)) {
|
||||||
return this._getTypeInfoField(typeOrFunc, "parameters", []);
|
return this._getTypeInfoField(typeOrFunc, "parameters", []);
|
||||||
} else {
|
} else {
|
||||||
return this.reflectionCapabilities.parameters(typeOrFunc);
|
return this.reflectionCapabilities.parameters(typeOrFunc);
|
||||||
@ -60,7 +64,7 @@ export class Reflector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
annotations(typeOrFunc): List<any> {
|
annotations(typeOrFunc): List<any> {
|
||||||
if (this._typeInfo.has(typeOrFunc)) {
|
if (this._injectableInfo.has(typeOrFunc)) {
|
||||||
return this._getTypeInfoField(typeOrFunc, "annotations", []);
|
return this._getTypeInfoField(typeOrFunc, "annotations", []);
|
||||||
} else {
|
} else {
|
||||||
return this.reflectionCapabilities.annotations(typeOrFunc);
|
return this.reflectionCapabilities.annotations(typeOrFunc);
|
||||||
@ -68,7 +72,7 @@ export class Reflector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interfaces(type): List<any> {
|
interfaces(type): List<any> {
|
||||||
if (this._typeInfo.has(type)) {
|
if (this._injectableInfo.has(type)) {
|
||||||
return this._getTypeInfoField(type, "interfaces", []);
|
return this._getTypeInfoField(type, "interfaces", []);
|
||||||
} else {
|
} else {
|
||||||
return this.reflectionCapabilities.interfaces(type);
|
return this.reflectionCapabilities.interfaces(type);
|
||||||
@ -100,11 +104,11 @@ export class Reflector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_getTypeInfoField(typeOrFunc, key, defaultValue) {
|
_getTypeInfoField(typeOrFunc, key, defaultValue) {
|
||||||
var res = this._typeInfo.get(typeOrFunc)[key];
|
var res = this._injectableInfo.get(typeOrFunc)[key];
|
||||||
return isPresent(res) ? res : defaultValue;
|
return isPresent(res) ? res : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
_containsTypeInfo(typeOrFunc) { return this._typeInfo.has(typeOrFunc); }
|
_containsTypeInfo(typeOrFunc) { return this._injectableInfo.has(typeOrFunc); }
|
||||||
}
|
}
|
||||||
|
|
||||||
function _mergeMaps(target: Map<any, any>, config: StringMap<string, Function>): void {
|
function _mergeMaps(target: Map<any, any>, config: StringMap<string, Function>): void {
|
||||||
|
@ -172,11 +172,7 @@ class CreateNgDepsVisitor extends Object with SimpleAstVisitor<Object> {
|
|||||||
|
|
||||||
var ctor = _getCtor(node);
|
var ctor = _getCtor(node);
|
||||||
|
|
||||||
if (!_foundNgInjectable) {
|
_maybeWriteReflector();
|
||||||
// The receiver for cascaded calls.
|
|
||||||
writer.print(REFLECTOR_VAR_NAME);
|
|
||||||
_foundNgInjectable = true;
|
|
||||||
}
|
|
||||||
writer.print('..registerType(');
|
writer.print('..registerType(');
|
||||||
node.name.accept(this);
|
node.name.accept(this);
|
||||||
writer.print(''', {'factory': ''');
|
writer.print(''', {'factory': ''');
|
||||||
@ -236,4 +232,32 @@ class CreateNgDepsVisitor extends Object with SimpleAstVisitor<Object> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Object visitSimpleIdentifier(SimpleIdentifier node) => _nodeToSource(node);
|
Object visitSimpleIdentifier(SimpleIdentifier node) => _nodeToSource(node);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool visitFunctionDeclaration(FunctionDeclaration node) {
|
||||||
|
if (!node.metadata.any((a) => _annotationMatcher.hasMatch(a, assetId))) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_maybeWriteReflector();
|
||||||
|
writer.print('..registerFunction(');
|
||||||
|
node.name.accept(this);
|
||||||
|
writer.print(''', {'parameters': const [''');
|
||||||
|
var parameters = node.childEntities
|
||||||
|
.firstWhere((child) => child is FunctionExpression).parameters;
|
||||||
|
parameters.accept(_paramsVisitor);
|
||||||
|
writer.print('''], 'annotations': ''');
|
||||||
|
node.metadata.accept(_metaVisitor);
|
||||||
|
writer.print('})');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Writes out the reflector variable the first time it is called.
|
||||||
|
void _maybeWriteReflector() {
|
||||||
|
if (_foundNgInjectable) return;
|
||||||
|
_foundNgInjectable = true;
|
||||||
|
|
||||||
|
// The receiver for cascaded calls.
|
||||||
|
writer.print(REFLECTOR_VAR_NAME);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,6 +93,9 @@ void allTests() {
|
|||||||
'ERROR: Could not read asset at uri bad_relative_url.css from angular2|'
|
'ERROR: Could not read asset at uri bad_relative_url.css from angular2|'
|
||||||
'test/transform/directive_processor/invalid_url_files/hello.dart'
|
'test/transform/directive_processor/invalid_url_files/hello.dart'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
_testNgDeps('should find and register static functions.',
|
||||||
|
'static_function_files/hello.dart');
|
||||||
}
|
}
|
||||||
|
|
||||||
void _testNgDeps(String name, String inputPath,
|
void _testNgDeps(String name, String inputPath,
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
library static_function_files.hello.ng_deps.dart;
|
||||||
|
|
||||||
|
import 'hello.dart';
|
||||||
|
import 'package:angular2/angular2.dart';
|
||||||
|
|
||||||
|
var _visited = false;
|
||||||
|
void initReflector(reflector) {
|
||||||
|
if (_visited) return;
|
||||||
|
_visited = true;
|
||||||
|
reflector
|
||||||
|
..registerFunction(getMessage, {
|
||||||
|
'parameters': const [const [const Inject(Message)]],
|
||||||
|
'annotations': const Injectable()
|
||||||
|
})
|
||||||
|
..registerType(Message, {
|
||||||
|
'factory': () => new Message(),
|
||||||
|
'parameters': const [],
|
||||||
|
'annotations': const [const Injectable()]
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
library static_function_files.hello;
|
||||||
|
|
||||||
|
import 'package:angular2/angular2.dart';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
String getMessage(@Inject(Message) message) => message.value;
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
class Message {
|
||||||
|
String value = 'hello!';
|
||||||
|
}
|
Reference in New Issue
Block a user