diff --git a/src/extension/method/provider/provider.ts b/src/extension/method/provider/provider.ts index e6b50dd72..e20c931a0 100644 --- a/src/extension/method/provider/provider.ts +++ b/src/extension/method/provider/provider.ts @@ -1,3 +1,4 @@ +import { applyIdentityProperty } from '../../../utils/applyIdentityProperty'; import { functionMethod } from './functionMethod'; // eslint-disable-next-line @typescript-eslint/no-explicit-any type Method = (name: string, value: any) => () => any; @@ -45,6 +46,10 @@ export class Provider { return this._method(name, value()); } - return this._method(name, value); + // FIXME: Do this smarter, it's a bit counter intuitive to return a new + // proxy every single time this function is called. It should probably mock + // based on name if that ends up being a string representing the type + // signature. + return applyIdentityProperty(this._method, name)(name, value); } } diff --git a/src/repository/repository.ts b/src/repository/repository.ts index 7cca95d4e..8a5706a52 100644 --- a/src/repository/repository.ts +++ b/src/repository/repository.ts @@ -1,4 +1,7 @@ -type Factory = Function; +import { applyIdentityProperty } from '../utils/applyIdentityProperty'; + +// eslint-disable-next-line +type Factory = (...args: any[]) => any; export class Repository { private readonly _repository: { [key: string]: Factory }; @@ -15,7 +18,7 @@ export class Repository { } public registerFactory(key: string, factory: Factory): void { - this._repository[key] = factory; + this._repository[key] = applyIdentityProperty(factory, key); } public getFactory(key: string): Factory { diff --git a/src/utils/applyIdentityProperty.ts b/src/utils/applyIdentityProperty.ts new file mode 100644 index 000000000..1b8ce0181 --- /dev/null +++ b/src/utils/applyIdentityProperty.ts @@ -0,0 +1,34 @@ +// eslint-disable-next-line +type Function = (...args: any[]) => K; +type IdentityFlavored = K & { __ident?: string }; + +export function applyIdentityProperty>(target: T, identity: string): T { + return new Proxy( + target, + { + apply(func: T, _this: unknown, args: Parameters): IdentityFlavored | undefined { + const t: IdentityFlavored = func(...args); + + if (typeof t === 'undefined') { + return; + } + + if (!(t instanceof Object)) { + return t; + } + + if (typeof t.__ident !== 'undefined') { + return t; + } + + Object.defineProperty(t, '__ident', { + enumerable: false, + writable: false, + value: identity, + }); + + return t; + }, + }, + ); +}