feat: track unused reflection data
This commit is contained in:
parent
b0d27ee896
commit
8336881a85
|
@ -4,6 +4,8 @@ import {
|
||||||
ListWrapper,
|
ListWrapper,
|
||||||
Map,
|
Map,
|
||||||
MapWrapper,
|
MapWrapper,
|
||||||
|
Set,
|
||||||
|
SetWrapper,
|
||||||
StringMap,
|
StringMap,
|
||||||
StringMapWrapper
|
StringMapWrapper
|
||||||
} from 'angular2/src/facade/collection';
|
} from 'angular2/src/facade/collection';
|
||||||
|
@ -32,6 +34,7 @@ export class Reflector {
|
||||||
_getters: Map<string, GetterFn>;
|
_getters: Map<string, GetterFn>;
|
||||||
_setters: Map<string, SetterFn>;
|
_setters: Map<string, SetterFn>;
|
||||||
_methods: Map<string, MethodFn>;
|
_methods: Map<string, MethodFn>;
|
||||||
|
_usedKeys: Set<any>;
|
||||||
reflectionCapabilities: PlatformReflectionCapabilities;
|
reflectionCapabilities: PlatformReflectionCapabilities;
|
||||||
|
|
||||||
constructor(reflectionCapabilities: PlatformReflectionCapabilities) {
|
constructor(reflectionCapabilities: PlatformReflectionCapabilities) {
|
||||||
|
@ -39,11 +42,31 @@ export class Reflector {
|
||||||
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._usedKeys = null;
|
||||||
this.reflectionCapabilities = reflectionCapabilities;
|
this.reflectionCapabilities = reflectionCapabilities;
|
||||||
}
|
}
|
||||||
|
|
||||||
isReflectionEnabled(): boolean { return this.reflectionCapabilities.isReflectionEnabled(); }
|
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 {
|
registerFunction(func: Function, funcInfo: ReflectionInfo): void {
|
||||||
this._injectableInfo.set(func, funcInfo);
|
this._injectableInfo.set(func, funcInfo);
|
||||||
}
|
}
|
||||||
|
@ -66,7 +89,7 @@ export class Reflector {
|
||||||
|
|
||||||
factory(type: Type): Function {
|
factory(type: Type): Function {
|
||||||
if (this._containsReflectionInfo(type)) {
|
if (this._containsReflectionInfo(type)) {
|
||||||
var res = this._injectableInfo.get(type)._factory;
|
var res = this._getReflectionInfo(type)._factory;
|
||||||
return isPresent(res) ? res : null;
|
return isPresent(res) ? res : null;
|
||||||
} else {
|
} else {
|
||||||
return this.reflectionCapabilities.factory(type);
|
return this.reflectionCapabilities.factory(type);
|
||||||
|
@ -75,7 +98,7 @@ export class Reflector {
|
||||||
|
|
||||||
parameters(typeOrFunc: /*Type*/ any): List<any> {
|
parameters(typeOrFunc: /*Type*/ any): List<any> {
|
||||||
if (this._injectableInfo.has(typeOrFunc)) {
|
if (this._injectableInfo.has(typeOrFunc)) {
|
||||||
var res = this._injectableInfo.get(typeOrFunc)._parameters;
|
var res = this._getReflectionInfo(typeOrFunc)._parameters;
|
||||||
return isPresent(res) ? res : [];
|
return isPresent(res) ? res : [];
|
||||||
} else {
|
} else {
|
||||||
return this.reflectionCapabilities.parameters(typeOrFunc);
|
return this.reflectionCapabilities.parameters(typeOrFunc);
|
||||||
|
@ -84,7 +107,7 @@ export class Reflector {
|
||||||
|
|
||||||
annotations(typeOrFunc: /*Type*/ any): List<any> {
|
annotations(typeOrFunc: /*Type*/ any): List<any> {
|
||||||
if (this._injectableInfo.has(typeOrFunc)) {
|
if (this._injectableInfo.has(typeOrFunc)) {
|
||||||
var res = this._injectableInfo.get(typeOrFunc)._annotations;
|
var res = this._getReflectionInfo(typeOrFunc)._annotations;
|
||||||
return isPresent(res) ? res : [];
|
return isPresent(res) ? res : [];
|
||||||
} else {
|
} else {
|
||||||
return this.reflectionCapabilities.annotations(typeOrFunc);
|
return this.reflectionCapabilities.annotations(typeOrFunc);
|
||||||
|
@ -93,7 +116,7 @@ export class Reflector {
|
||||||
|
|
||||||
interfaces(type: Type): List<any> {
|
interfaces(type: Type): List<any> {
|
||||||
if (this._injectableInfo.has(type)) {
|
if (this._injectableInfo.has(type)) {
|
||||||
var res = this._injectableInfo.get(type)._interfaces;
|
var res = this._getReflectionInfo(type)._interfaces;
|
||||||
return isPresent(res) ? res : [];
|
return isPresent(res) ? res : [];
|
||||||
} else {
|
} else {
|
||||||
return this.reflectionCapabilities.interfaces(type);
|
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); }
|
_containsReflectionInfo(typeOrFunc) { return this._injectableInfo.has(typeOrFunc); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,29 @@ export function main() {
|
||||||
|
|
||||||
beforeEach(() => { reflector = new Reflector(new ReflectionCapabilities()); });
|
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", () => {
|
describe("factory", () => {
|
||||||
it("should create a factory for the given type", () => {
|
it("should create a factory for the given type", () => {
|
||||||
var obj = reflector.factory(TestObj)(1, 2);
|
var obj = reflector.factory(TestObj)(1, 2);
|
||||||
|
|
Loading…
Reference in New Issue