feat: track unused reflection data

This commit is contained in:
yjbanov 2015-08-19 14:07:30 -07:00 committed by Yegor Jbanov
parent b0d27ee896
commit 8336881a85
2 changed files with 57 additions and 4 deletions

View File

@ -4,6 +4,8 @@ import {
ListWrapper,
Map,
MapWrapper,
Set,
SetWrapper,
StringMap,
StringMapWrapper
} from 'angular2/src/facade/collection';
@ -32,6 +34,7 @@ export class Reflector {
_getters: Map<string, GetterFn>;
_setters: Map<string, SetterFn>;
_methods: Map<string, MethodFn>;
_usedKeys: Set<any>;
reflectionCapabilities: PlatformReflectionCapabilities;
constructor(reflectionCapabilities: PlatformReflectionCapabilities) {
@ -39,11 +42,31 @@ export class Reflector {
this._getters = new Map();
this._setters = new Map();
this._methods = new Map();
this._usedKeys = null;
this.reflectionCapabilities = reflectionCapabilities;
}
isReflectionEnabled(): boolean { return this.reflectionCapabilities.isReflectionEnabled(); }
/**
* Causes `this` reflector to track keys used to access
* {@link ReflectionInfo} objects.
*/
trackUsage(): void { this._usedKeys = new Set(); }
/**
* Lists types for which reflection information was not requested since
* {@link #trackUsage} was called. This list could later be audited as
* potential dead code.
*/
listUnusedKeys(): List<any> {
if (this._usedKeys == null) {
throw new BaseException('Usage tracking is disabled');
}
var allTypes = MapWrapper.keys(this._injectableInfo);
return ListWrapper.filter(allTypes, (key) => { return !SetWrapper.has(this._usedKeys, key); });
}
registerFunction(func: Function, funcInfo: ReflectionInfo): void {
this._injectableInfo.set(func, funcInfo);
}
@ -66,7 +89,7 @@ export class Reflector {
factory(type: Type): Function {
if (this._containsReflectionInfo(type)) {
var res = this._injectableInfo.get(type)._factory;
var res = this._getReflectionInfo(type)._factory;
return isPresent(res) ? res : null;
} else {
return this.reflectionCapabilities.factory(type);
@ -75,7 +98,7 @@ export class Reflector {
parameters(typeOrFunc: /*Type*/ any): List<any> {
if (this._injectableInfo.has(typeOrFunc)) {
var res = this._injectableInfo.get(typeOrFunc)._parameters;
var res = this._getReflectionInfo(typeOrFunc)._parameters;
return isPresent(res) ? res : [];
} else {
return this.reflectionCapabilities.parameters(typeOrFunc);
@ -84,7 +107,7 @@ export class Reflector {
annotations(typeOrFunc: /*Type*/ any): List<any> {
if (this._injectableInfo.has(typeOrFunc)) {
var res = this._injectableInfo.get(typeOrFunc)._annotations;
var res = this._getReflectionInfo(typeOrFunc)._annotations;
return isPresent(res) ? res : [];
} else {
return this.reflectionCapabilities.annotations(typeOrFunc);
@ -93,7 +116,7 @@ export class Reflector {
interfaces(type: Type): List<any> {
if (this._injectableInfo.has(type)) {
var res = this._injectableInfo.get(type)._interfaces;
var res = this._getReflectionInfo(type)._interfaces;
return isPresent(res) ? res : [];
} else {
return this.reflectionCapabilities.interfaces(type);
@ -124,6 +147,13 @@ export class Reflector {
}
}
_getReflectionInfo(typeOrFunc) {
if (isPresent(this._usedKeys)) {
this._usedKeys.add(typeOrFunc);
}
return this._injectableInfo.get(typeOrFunc);
}
_containsReflectionInfo(typeOrFunc) { return this._injectableInfo.has(typeOrFunc); }
}

View File

@ -48,6 +48,29 @@ export function main() {
beforeEach(() => { reflector = new Reflector(new ReflectionCapabilities()); });
describe("usage tracking", () => {
beforeEach(() => { reflector = new Reflector(null); });
it("should be disabled by default", () => {
expect(() => reflector.listUnusedKeys()).toThrowError('Usage tracking is disabled');
});
it("should report unused keys", () => {
reflector.trackUsage();
expect(reflector.listUnusedKeys()).toEqual([]);
reflector.registerType(AType, new ReflectionInfo(null, null, () => "AType"));
reflector.registerType(TestObj, new ReflectionInfo(null, null, () => "TestObj"));
expect(reflector.listUnusedKeys()).toEqual([AType, TestObj]);
reflector.factory(AType);
expect(reflector.listUnusedKeys()).toEqual([TestObj]);
reflector.factory(TestObj);
expect(reflector.listUnusedKeys()).toEqual([]);
});
});
describe("factory", () => {
it("should create a factory for the given type", () => {
var obj = reflector.factory(TestObj)(1, 2);