chore(transformer): Use class for reflection info instead of a map
closes https://github.com/angular/angular/issues/906
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
import {Type, isPresent} from 'angular2/src/facade/lang';
|
||||
import {List, ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {Reflector} from './reflector';
|
||||
export {Reflector} from './reflector';
|
||||
export {Reflector, ReflectionInfo} from './reflector';
|
||||
import {ReflectionCapabilities} from './reflection_capabilities';
|
||||
|
||||
export var reflector = new Reflector(new ReflectionCapabilities());
|
||||
|
@ -12,8 +12,23 @@ import {PlatformReflectionCapabilities} from './platform_reflection_capabilities
|
||||
export {SetterFn, GetterFn, MethodFn} from './types';
|
||||
export {PlatformReflectionCapabilities} from './platform_reflection_capabilities';
|
||||
|
||||
export class ReflectionInfo {
|
||||
_factory: Function;
|
||||
_annotations: List<any>;
|
||||
_parameters: List<List<any>>;
|
||||
_interfaces: List<any>;
|
||||
|
||||
constructor(annotations?: List<any>, parameters?: List<List<any>>, factory?: Function,
|
||||
interfaces?: List<any>) {
|
||||
this._annotations = annotations;
|
||||
this._parameters = parameters;
|
||||
this._factory = factory;
|
||||
this._interfaces = interfaces;
|
||||
}
|
||||
}
|
||||
|
||||
export class Reflector {
|
||||
_injectableInfo: Map<any, StringMap<string, any>>;
|
||||
_injectableInfo: Map<any, ReflectionInfo>;
|
||||
_getters: Map<string, GetterFn>;
|
||||
_setters: Map<string, SetterFn>;
|
||||
_methods: Map<string, MethodFn>;
|
||||
@ -29,11 +44,11 @@ export class Reflector {
|
||||
|
||||
isReflectionEnabled(): boolean { return this.reflectionCapabilities.isReflectionEnabled(); }
|
||||
|
||||
registerFunction(func: Function, funcInfo: StringMap<string, any>): void {
|
||||
registerFunction(func: Function, funcInfo: ReflectionInfo): void {
|
||||
this._injectableInfo.set(func, funcInfo);
|
||||
}
|
||||
|
||||
registerType(type: Type, typeInfo: StringMap<string, any>): void {
|
||||
registerType(type: Type, typeInfo: ReflectionInfo): void {
|
||||
this._injectableInfo.set(type, typeInfo);
|
||||
}
|
||||
|
||||
@ -50,8 +65,9 @@ export class Reflector {
|
||||
}
|
||||
|
||||
factory(type: Type): Function {
|
||||
if (this._containsTypeInfo(type)) {
|
||||
return this._getTypeInfoField(type, "factory", null);
|
||||
if (this._containsReflectionInfo(type)) {
|
||||
var res = this._injectableInfo.get(type)._factory;
|
||||
return isPresent(res) ? res : null;
|
||||
} else {
|
||||
return this.reflectionCapabilities.factory(type);
|
||||
}
|
||||
@ -59,7 +75,8 @@ export class Reflector {
|
||||
|
||||
parameters(typeOrFunc: /*Type*/ any): List<any> {
|
||||
if (this._injectableInfo.has(typeOrFunc)) {
|
||||
return this._getTypeInfoField(typeOrFunc, "parameters", []);
|
||||
var res = this._injectableInfo.get(typeOrFunc)._parameters;
|
||||
return isPresent(res) ? res : [];
|
||||
} else {
|
||||
return this.reflectionCapabilities.parameters(typeOrFunc);
|
||||
}
|
||||
@ -67,7 +84,8 @@ export class Reflector {
|
||||
|
||||
annotations(typeOrFunc: /*Type*/ any): List<any> {
|
||||
if (this._injectableInfo.has(typeOrFunc)) {
|
||||
return this._getTypeInfoField(typeOrFunc, "annotations", []);
|
||||
var res = this._injectableInfo.get(typeOrFunc)._annotations;
|
||||
return isPresent(res) ? res : [];
|
||||
} else {
|
||||
return this.reflectionCapabilities.annotations(typeOrFunc);
|
||||
}
|
||||
@ -75,7 +93,8 @@ export class Reflector {
|
||||
|
||||
interfaces(type: Type): List<any> {
|
||||
if (this._injectableInfo.has(type)) {
|
||||
return this._getTypeInfoField(type, "interfaces", []);
|
||||
var res = this._injectableInfo.get(type)._interfaces;
|
||||
return isPresent(res) ? res : [];
|
||||
} else {
|
||||
return this.reflectionCapabilities.interfaces(type);
|
||||
}
|
||||
@ -105,12 +124,7 @@ export class Reflector {
|
||||
}
|
||||
}
|
||||
|
||||
_getTypeInfoField(typeOrFunc, key, defaultValue) {
|
||||
var res = this._injectableInfo.get(typeOrFunc)[key];
|
||||
return isPresent(res) ? res : defaultValue;
|
||||
}
|
||||
|
||||
_containsTypeInfo(typeOrFunc) { return this._injectableInfo.has(typeOrFunc); }
|
||||
_containsReflectionInfo(typeOrFunc) { return this._injectableInfo.has(typeOrFunc); }
|
||||
}
|
||||
|
||||
function _mergeMaps(target: Map<any, any>, config: StringMap<string, Function>): void {
|
||||
|
@ -15,12 +15,17 @@ dynamic initZoned(Transform t, _SimpleCallback fn, {String errorMessage: ''}) =>
|
||||
setZoned(new BuildLogger(t), fn, errorMessage: errorMessage);
|
||||
|
||||
dynamic setZoned(BuildLogger logger, _SimpleCallback fn,
|
||||
{String errorMessage: ''}) => runZoned(fn,
|
||||
zoneValues: {_key: logger}, onError: (e, stackTrace) {
|
||||
logger.error('$errorMessage\n'
|
||||
'Exception: $e\n'
|
||||
'Stack Trace: $stackTrace');
|
||||
});
|
||||
{String errorMessage}) {
|
||||
var onError;
|
||||
if (errorMessage != null) {
|
||||
onError = (e, stackTrace) {
|
||||
logger.error('$errorMessage\n'
|
||||
'Exception: $e\n'
|
||||
'Stack Trace: $stackTrace');
|
||||
};
|
||||
}
|
||||
return runZoned(fn, zoneValues: {_key: logger}, onError: onError);
|
||||
}
|
||||
|
||||
/// The logger for the current {@link Zone}.
|
||||
BuildLogger get logger {
|
||||
|
@ -63,26 +63,22 @@ class _ParseRegisterTypeVisitor extends Object
|
||||
typeName = node.argumentList.arguments[0] is Identifier
|
||||
? node.argumentList.arguments[0]
|
||||
: null;
|
||||
return super.visitMethodInvocation(node);
|
||||
}
|
||||
|
||||
@override
|
||||
Object visitMapLiteralEntry(MapLiteralEntry node) {
|
||||
if (node.key is StringLiteral) {
|
||||
var key = stringLiteralToString(node.key);
|
||||
switch (key) {
|
||||
case 'annotations':
|
||||
annotations = node.value;
|
||||
break;
|
||||
case 'factory':
|
||||
factoryFn = node.value;
|
||||
break;
|
||||
case 'parameters':
|
||||
parameters = node.value;
|
||||
break;
|
||||
// The second argument to a `registerType` call is the RegistrationInfo
|
||||
// object creation.
|
||||
var info = node.argumentList.arguments[1] as InstanceCreationExpression;
|
||||
var args = info.argumentList.arguments;
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
var arg = args[i];
|
||||
if (i == 0) {
|
||||
annotations = arg;
|
||||
} else if (i == 1) {
|
||||
parameters = arg;
|
||||
} else if (i == 2) {
|
||||
factoryFn = arg;
|
||||
}
|
||||
}
|
||||
// Do not need to descend any further.
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -30,14 +30,9 @@ Future<String> createNgDeps(AssetReader reader, AssetId assetId,
|
||||
// TODO(kegluneq): Shortcut if we can determine that there are no
|
||||
// [Directive]s present, taking into account `export`s.
|
||||
var writer = new AsyncStringWriter();
|
||||
var visitor = new CreateNgDepsVisitor(
|
||||
writer,
|
||||
assetId,
|
||||
new XhrImpl(reader, assetId),
|
||||
annotationMatcher,
|
||||
_interfaceMatcher,
|
||||
ngMeta,
|
||||
inlineViews: inlineViews);
|
||||
var visitor = new CreateNgDepsVisitor(writer, assetId,
|
||||
new XhrImpl(reader, assetId), annotationMatcher, _interfaceMatcher,
|
||||
ngMeta, inlineViews: inlineViews);
|
||||
var code = await reader.readAsString(assetId);
|
||||
parseCompilationUnit(code, name: assetId.path).accept(visitor);
|
||||
|
||||
@ -81,14 +76,9 @@ class CreateNgDepsVisitor extends Object with SimpleAstVisitor<Object> {
|
||||
/// The assetId for the file which we are parsing.
|
||||
final AssetId assetId;
|
||||
|
||||
CreateNgDepsVisitor(
|
||||
AsyncStringWriter writer,
|
||||
AssetId assetId,
|
||||
XHR xhr,
|
||||
AnnotationMatcher annotationMatcher,
|
||||
InterfaceMatcher interfaceMatcher,
|
||||
this.ngMeta,
|
||||
{bool inlineViews})
|
||||
CreateNgDepsVisitor(AsyncStringWriter writer, AssetId assetId, XHR xhr,
|
||||
AnnotationMatcher annotationMatcher, InterfaceMatcher interfaceMatcher,
|
||||
this.ngMeta, {bool inlineViews})
|
||||
: writer = writer,
|
||||
_copyVisitor = new ToSourceVisitor(writer),
|
||||
_factoryVisitor = new FactoryTransformVisitor(writer),
|
||||
@ -215,31 +205,31 @@ class CreateNgDepsVisitor extends Object with SimpleAstVisitor<Object> {
|
||||
_maybeWriteReflector();
|
||||
writer.print('..registerType(');
|
||||
node.name.accept(this);
|
||||
writer.print(''', {'factory': ''');
|
||||
if (ctor == null) {
|
||||
_generateEmptyFactory(node.name.toString());
|
||||
} else {
|
||||
ctor.accept(_factoryVisitor);
|
||||
}
|
||||
writer.print(''', 'parameters': ''');
|
||||
writer.print(', new ${_REF_PREFIX}.ReflectionInfo(');
|
||||
node.accept(_metaVisitor);
|
||||
writer.print(', ');
|
||||
if (ctor == null) {
|
||||
_generateEmptyParams();
|
||||
} else {
|
||||
ctor.accept(_paramsVisitor);
|
||||
}
|
||||
writer.print(''', 'annotations': ''');
|
||||
node.accept(_metaVisitor);
|
||||
writer.print(', ');
|
||||
if (ctor == null) {
|
||||
_generateEmptyFactory(node.name.toString());
|
||||
} else {
|
||||
ctor.accept(_factoryVisitor);
|
||||
}
|
||||
if (node.implementsClause != null &&
|
||||
node.implementsClause.interfaces != null &&
|
||||
node.implementsClause.interfaces.isNotEmpty) {
|
||||
writer
|
||||
..print(''', 'interfaces': const [''')
|
||||
..print(', const [')
|
||||
..print(node.implementsClause.interfaces
|
||||
.map((interface) => interface.name)
|
||||
.join(', '))
|
||||
..print(']');
|
||||
}
|
||||
writer.print('})');
|
||||
writer.print('))');
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -307,11 +297,11 @@ class CreateNgDepsVisitor extends Object with SimpleAstVisitor<Object> {
|
||||
_maybeWriteReflector();
|
||||
writer.print('..registerFunction(');
|
||||
node.name.accept(this);
|
||||
writer.print(''', {'parameters': const [''');
|
||||
node.functionExpression.parameters.accept(_paramsVisitor);
|
||||
writer.print('''], 'annotations': ''');
|
||||
writer.print(', new ${_REF_PREFIX}.ReflectionInfo(');
|
||||
node.metadata.accept(_metaVisitor);
|
||||
writer.print('})');
|
||||
writer.print(', const [');
|
||||
node.functionExpression.parameters.accept(_paramsVisitor);
|
||||
writer.print(']))');
|
||||
return null;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user