Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(Reflector): simplify code, add types #12099

Merged
merged 1 commit into from
Oct 6, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion modules/@angular/core/src/reflection/reflection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ export {ReflectionInfo, Reflector} from './reflector';
* The {@link Reflector} used internally in Angular to access metadata
* about symbols.
*/
export var reflector = new Reflector(new ReflectionCapabilities());
export const reflector = new Reflector(new ReflectionCapabilities());
75 changes: 32 additions & 43 deletions modules/@angular/core/src/reflection/reflection_capabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,11 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {

isReflectionEnabled(): boolean { return true; }

factory(t: Type<any>): Function {
var prototype = t.prototype;
return function(...args: any[]) {
var instance = Object.create(prototype);
t.apply(instance, args);
return instance;
};
}
factory<T>(t: Type<T>): (args: any[]) => T { return (...args: any[]) => new t(...args); }

/** @internal */
_zipTypesAndAnnotations(
paramTypes: any /** TODO #9100 */, paramAnnotations: any /** TODO #9100 */): any[][] {
var result: any /** TODO #9100 */;
_zipTypesAndAnnotations(paramTypes: any[], paramAnnotations: any[]): any[][] {
var result: any[][];

if (typeof paramTypes === 'undefined') {
result = new Array(paramAnnotations.length);
Expand All @@ -50,91 +42,88 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {
} else {
result[i] = [];
}
if (isPresent(paramAnnotations) && isPresent(paramAnnotations[i])) {
if (paramAnnotations && isPresent(paramAnnotations[i])) {
result[i] = result[i].concat(paramAnnotations[i]);
}
}
return result;
}

parameters(typeOrFunc: Type<any>): any[][] {
parameters(type: Type<any>): any[][] {
// Prefer the direct API.
if (isPresent((<any>typeOrFunc).parameters)) {
return (<any>typeOrFunc).parameters;
if ((<any>type).parameters) {
return (<any>type).parameters;
}

// API of tsickle for lowering decorators to properties on the class.
if (isPresent((<any>typeOrFunc).ctorParameters)) {
let ctorParameters = (<any>typeOrFunc).ctorParameters;
let paramTypes =
ctorParameters.map((ctorParam: any /** TODO #9100 */) => ctorParam && ctorParam.type);
let paramAnnotations = ctorParameters.map(
(ctorParam: any /** TODO #9100 */) =>
if ((<any>type).ctorParameters) {
const ctorParameters = (<any>type).ctorParameters;
const paramTypes = ctorParameters.map((ctorParam: any) => ctorParam && ctorParam.type);
const paramAnnotations = ctorParameters.map(
(ctorParam: any) =>
ctorParam && convertTsickleDecoratorIntoMetadata(ctorParam.decorators));
return this._zipTypesAndAnnotations(paramTypes, paramAnnotations);
}

// API for metadata created by invoking the decorators.
if (isPresent(this._reflect) && isPresent(this._reflect.getMetadata)) {
var paramAnnotations = this._reflect.getMetadata('parameters', typeOrFunc);
var paramTypes = this._reflect.getMetadata('design:paramtypes', typeOrFunc);
if (isPresent(paramTypes) || isPresent(paramAnnotations)) {
const paramAnnotations = this._reflect.getMetadata('parameters', type);
const paramTypes = this._reflect.getMetadata('design:paramtypes', type);
if (paramTypes || paramAnnotations) {
return this._zipTypesAndAnnotations(paramTypes, paramAnnotations);
}
}
// The array has to be filled with `undefined` because holes would be skipped by `some`
let parameters = new Array((<any>typeOrFunc.length));
parameters.fill(undefined);
return parameters;
return new Array((<any>type.length)).fill(undefined);
}

annotations(typeOrFunc: Type<any>): any[] {
// Prefer the direct API.
if (isPresent((<any>typeOrFunc).annotations)) {
var annotations = (<any>typeOrFunc).annotations;
if ((<any>typeOrFunc).annotations) {
let annotations = (<any>typeOrFunc).annotations;
if (isFunction(annotations) && annotations.annotations) {
annotations = annotations.annotations;
}
return annotations;
}

// API of tsickle for lowering decorators to properties on the class.
if (isPresent((<any>typeOrFunc).decorators)) {
if ((<any>typeOrFunc).decorators) {
return convertTsickleDecoratorIntoMetadata((<any>typeOrFunc).decorators);
}

// API for metadata created by invoking the decorators.
if (isPresent(this._reflect) && isPresent(this._reflect.getMetadata)) {
var annotations = this._reflect.getMetadata('annotations', typeOrFunc);
if (isPresent(annotations)) return annotations;
if (this._reflect && this._reflect.getMetadata) {
const annotations = this._reflect.getMetadata('annotations', typeOrFunc);
if (annotations) return annotations;
}
return [];
}

propMetadata(typeOrFunc: any): {[key: string]: any[]} {
// Prefer the direct API.
if (isPresent((<any>typeOrFunc).propMetadata)) {
var propMetadata = (<any>typeOrFunc).propMetadata;
if ((<any>typeOrFunc).propMetadata) {
let propMetadata = (<any>typeOrFunc).propMetadata;
if (isFunction(propMetadata) && propMetadata.propMetadata) {
propMetadata = propMetadata.propMetadata;
}
return propMetadata;
}

// API of tsickle for lowering decorators to properties on the class.
if (isPresent((<any>typeOrFunc).propDecorators)) {
let propDecorators = (<any>typeOrFunc).propDecorators;
let propMetadata = <{[key: string]: any[]}>{};
if ((<any>typeOrFunc).propDecorators) {
const propDecorators = (<any>typeOrFunc).propDecorators;
const propMetadata = <{[key: string]: any[]}>{};
Object.keys(propDecorators).forEach(prop => {
propMetadata[prop] = convertTsickleDecoratorIntoMetadata(propDecorators[prop]);
});
return propMetadata;
}

// API for metadata created by invoking the decorators.
if (isPresent(this._reflect) && isPresent(this._reflect.getMetadata)) {
var propMetadata = this._reflect.getMetadata('propMetadata', typeOrFunc);
if (isPresent(propMetadata)) return propMetadata;
if (this._reflect && this._reflect.getMetadata) {
const propMetadata = this._reflect.getMetadata('propMetadata', typeOrFunc);
if (propMetadata) return propMetadata;
}
return {};
}
Expand All @@ -147,7 +136,7 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {
hasLifecycleHook(type: any, lcInterface: Type<any>, lcProperty: string): boolean {
if (!(type instanceof Type)) return false;

var proto = (<any>type).prototype;
const proto = (<any>type).prototype;
return !!proto[lcProperty];
}

Expand All @@ -158,7 +147,7 @@ export class ReflectionCapabilities implements PlatformReflectionCapabilities {
}

method(name: string): MethodFn {
let functionBody = `if (!o.${name}) throw new Error('"${name}" is undefined');
const functionBody = `if (!o.${name}) throw new Error('"${name}" is undefined');
return o.${name}.apply(o, args);`;
return <MethodFn>new Function('o', 'args', functionBody);
}
Expand Down
71 changes: 28 additions & 43 deletions modules/@angular/core/src/reflection/reflector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
*/

import {MapWrapper} from '../facade/collection';
import {isPresent} from '../facade/lang';
import {Type} from '../type';
import {PlatformReflectionCapabilities} from './platform_reflection_capabilities';
import {ReflectorReader} from './reflector_reader';
Expand Down Expand Up @@ -60,10 +59,10 @@ export class Reflector extends ReflectorReader {
* potential dead code.
*/
listUnusedKeys(): any[] {
if (this._usedKeys == null) {
if (!this._usedKeys) {
throw new Error('Usage tracking is disabled');
}
var allTypes = MapWrapper.keys(this._injectableInfo);
const allTypes = MapWrapper.keys(this._injectableInfo);
return allTypes.filter(key => !this._usedKeys.has(key));
}

Expand All @@ -83,87 +82,73 @@ export class Reflector extends ReflectorReader {

factory(type: Type<any>): Function {
if (this._containsReflectionInfo(type)) {
var res = this._getReflectionInfo(type).factory;
return isPresent(res) ? res : null;
} else {
return this.reflectionCapabilities.factory(type);
return this._getReflectionInfo(type).factory || null;
}

return this.reflectionCapabilities.factory(type);
}

parameters(typeOrFunc: Type<any>): any[][] {
if (this._injectableInfo.has(typeOrFunc)) {
var res = this._getReflectionInfo(typeOrFunc).parameters;
return isPresent(res) ? res : [];
} else {
return this.reflectionCapabilities.parameters(typeOrFunc);
return this._getReflectionInfo(typeOrFunc).parameters || [];
}

return this.reflectionCapabilities.parameters(typeOrFunc);
}

annotations(typeOrFunc: Type<any>): any[] {
if (this._injectableInfo.has(typeOrFunc)) {
var res = this._getReflectionInfo(typeOrFunc).annotations;
return isPresent(res) ? res : [];
} else {
return this.reflectionCapabilities.annotations(typeOrFunc);
return this._getReflectionInfo(typeOrFunc).annotations || [];
}

return this.reflectionCapabilities.annotations(typeOrFunc);
}

propMetadata(typeOrFunc: Type<any>): {[key: string]: any[]} {
if (this._injectableInfo.has(typeOrFunc)) {
var res = this._getReflectionInfo(typeOrFunc).propMetadata;
return isPresent(res) ? res : {};
} else {
return this.reflectionCapabilities.propMetadata(typeOrFunc);
return this._getReflectionInfo(typeOrFunc).propMetadata || {};
}

return this.reflectionCapabilities.propMetadata(typeOrFunc);
}

interfaces(type: Type<any>): any[] {
if (this._injectableInfo.has(type)) {
var res = this._getReflectionInfo(type).interfaces;
return isPresent(res) ? res : [];
} else {
return this.reflectionCapabilities.interfaces(type);
return this._getReflectionInfo(type).interfaces || [];
}

return this.reflectionCapabilities.interfaces(type);
}

hasLifecycleHook(type: any, lcInterface: Type<any>, lcProperty: string): boolean {
var interfaces = this.interfaces(type);
if (interfaces.indexOf(lcInterface) !== -1) {
if (this.interfaces(type).indexOf(lcInterface) !== -1) {
return true;
} else {
return this.reflectionCapabilities.hasLifecycleHook(type, lcInterface, lcProperty);
}

return this.reflectionCapabilities.hasLifecycleHook(type, lcInterface, lcProperty);
}

getter(name: string): GetterFn {
if (this._getters.has(name)) {
return this._getters.get(name);
} else {
return this.reflectionCapabilities.getter(name);
}
return this._getters.has(name) ? this._getters.get(name) :
this.reflectionCapabilities.getter(name);
}

setter(name: string): SetterFn {
if (this._setters.has(name)) {
return this._setters.get(name);
} else {
return this.reflectionCapabilities.setter(name);
}
return this._setters.has(name) ? this._setters.get(name) :
this.reflectionCapabilities.setter(name);
}

method(name: string): MethodFn {
if (this._methods.has(name)) {
return this._methods.get(name);
} else {
return this.reflectionCapabilities.method(name);
}
return this._methods.has(name) ? this._methods.get(name) :
this.reflectionCapabilities.method(name);
}

/** @internal */
_getReflectionInfo(typeOrFunc: any): ReflectionInfo {
if (isPresent(this._usedKeys)) {
if (this._usedKeys) {
this._usedKeys.add(typeOrFunc);
}

return this._injectableInfo.get(typeOrFunc);
}

Expand Down