Path: blob/main/src/vs/platform/instantiation/common/instantiation.ts
5282 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { DisposableStore } from '../../../base/common/lifecycle.js';6import * as descriptors from './descriptors.js';7import { ServiceCollection } from './serviceCollection.js';89// ------ internal util1011export namespace _util {1213export const serviceIds = new Map<string, ServiceIdentifier<any>>();1415export const DI_TARGET = '$di$target';16export const DI_DEPENDENCIES = '$di$dependencies';1718export function getServiceDependencies(ctor: DI_TARGET_OBJ): { id: ServiceIdentifier<any>; index: number }[] {19return ctor[DI_DEPENDENCIES] || [];20}2122export interface DI_TARGET_OBJ extends Function {23[DI_TARGET]: Function;24[DI_DEPENDENCIES]: { id: ServiceIdentifier<any>; index: number }[];25}26}2728// --- interfaces ------2930export type BrandedService = { _serviceBrand: undefined };3132export interface IConstructorSignature<T, Args extends any[] = []> {33new <Services extends BrandedService[]>(...args: [...Args, ...Services]): T;34}3536export interface ServicesAccessor {37get<T>(id: ServiceIdentifier<T>): T;38}3940export const IInstantiationService = createDecorator<IInstantiationService>('instantiationService');4142/**43* Given a list of arguments as a tuple, attempt to extract the leading, non-service arguments44* to their own tuple.45*/46export type GetLeadingNonServiceArgs<TArgs extends any[]> =47TArgs extends [] ? []48: TArgs extends [...infer TFirst, BrandedService] ? GetLeadingNonServiceArgs<TFirst>49: TArgs;5051export interface IInstantiationService {5253readonly _serviceBrand: undefined;5455/**56* Synchronously creates an instance that is denoted by the descriptor57*/58createInstance<T>(descriptor: descriptors.SyncDescriptor0<T>): T;59createInstance<Ctor extends new (...args: any[]) => unknown, R extends InstanceType<Ctor>>(ctor: Ctor, ...args: GetLeadingNonServiceArgs<ConstructorParameters<Ctor>>): R;6061/**62* Calls a function with a service accessor.63*/64invokeFunction<R, TS extends any[] = []>(fn: (accessor: ServicesAccessor, ...args: TS) => R, ...args: TS): R;6566/**67* Creates a child of this service which inherits all current services68* and adds/overwrites the given services.69*70* NOTE that the returned child is `disposable` and should be disposed when not used71* anymore. This will also dispose all the services that this service has created.72*/73createChild(services: ServiceCollection, store?: DisposableStore): IInstantiationService;7475/**76* Disposes this instantiation service.77*78* - Will dispose all services that this instantiation service has created.79* - Will dispose all its children but not its parent.80* - Will NOT dispose services-instances that this service has been created with81* - Will NOT dispose consumer-instances this service has created82*/83dispose(): void;84}858687/**88* Identifies a service of type `T`.89*/90export interface ServiceIdentifier<T> {91(...args: any[]): void;92type: T;93}949596function storeServiceDependency(id: ServiceIdentifier<unknown>, target: Function, index: number): void {97if ((target as _util.DI_TARGET_OBJ)[_util.DI_TARGET] === target) {98(target as _util.DI_TARGET_OBJ)[_util.DI_DEPENDENCIES].push({ id, index });99} else {100(target as _util.DI_TARGET_OBJ)[_util.DI_DEPENDENCIES] = [{ id, index }];101(target as _util.DI_TARGET_OBJ)[_util.DI_TARGET] = target;102}103}104105/**106* The *only* valid way to create a {{ServiceIdentifier}}.107*/108export function createDecorator<T>(serviceId: string): ServiceIdentifier<T> {109110if (_util.serviceIds.has(serviceId)) {111return _util.serviceIds.get(serviceId)!;112}113114const id = function (target: Function, key: string, index: number) {115if (arguments.length !== 3) {116throw new Error('@IServiceName-decorator can only be used to decorate a parameter');117}118storeServiceDependency(id, target, index);119} as ServiceIdentifier<T>;120121id.toString = () => serviceId;122123_util.serviceIds.set(serviceId, id);124return id;125}126127export function refineServiceDecorator<T1, T extends T1>(serviceIdentifier: ServiceIdentifier<T1>): ServiceIdentifier<T> {128return <ServiceIdentifier<T>>serviceIdentifier;129}130131132