Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/platform/instantiation/common/instantiation.ts
5282 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { DisposableStore } from '../../../base/common/lifecycle.js';
7
import * as descriptors from './descriptors.js';
8
import { ServiceCollection } from './serviceCollection.js';
9
10
// ------ internal util
11
12
export namespace _util {
13
14
export const serviceIds = new Map<string, ServiceIdentifier<any>>();
15
16
export const DI_TARGET = '$di$target';
17
export const DI_DEPENDENCIES = '$di$dependencies';
18
19
export function getServiceDependencies(ctor: DI_TARGET_OBJ): { id: ServiceIdentifier<any>; index: number }[] {
20
return ctor[DI_DEPENDENCIES] || [];
21
}
22
23
export interface DI_TARGET_OBJ extends Function {
24
[DI_TARGET]: Function;
25
[DI_DEPENDENCIES]: { id: ServiceIdentifier<any>; index: number }[];
26
}
27
}
28
29
// --- interfaces ------
30
31
export type BrandedService = { _serviceBrand: undefined };
32
33
export interface IConstructorSignature<T, Args extends any[] = []> {
34
new <Services extends BrandedService[]>(...args: [...Args, ...Services]): T;
35
}
36
37
export interface ServicesAccessor {
38
get<T>(id: ServiceIdentifier<T>): T;
39
}
40
41
export const IInstantiationService = createDecorator<IInstantiationService>('instantiationService');
42
43
/**
44
* Given a list of arguments as a tuple, attempt to extract the leading, non-service arguments
45
* to their own tuple.
46
*/
47
export type GetLeadingNonServiceArgs<TArgs extends any[]> =
48
TArgs extends [] ? []
49
: TArgs extends [...infer TFirst, BrandedService] ? GetLeadingNonServiceArgs<TFirst>
50
: TArgs;
51
52
export interface IInstantiationService {
53
54
readonly _serviceBrand: undefined;
55
56
/**
57
* Synchronously creates an instance that is denoted by the descriptor
58
*/
59
createInstance<T>(descriptor: descriptors.SyncDescriptor0<T>): T;
60
createInstance<Ctor extends new (...args: any[]) => unknown, R extends InstanceType<Ctor>>(ctor: Ctor, ...args: GetLeadingNonServiceArgs<ConstructorParameters<Ctor>>): R;
61
62
/**
63
* Calls a function with a service accessor.
64
*/
65
invokeFunction<R, TS extends any[] = []>(fn: (accessor: ServicesAccessor, ...args: TS) => R, ...args: TS): R;
66
67
/**
68
* Creates a child of this service which inherits all current services
69
* and adds/overwrites the given services.
70
*
71
* NOTE that the returned child is `disposable` and should be disposed when not used
72
* anymore. This will also dispose all the services that this service has created.
73
*/
74
createChild(services: ServiceCollection, store?: DisposableStore): IInstantiationService;
75
76
/**
77
* Disposes this instantiation service.
78
*
79
* - Will dispose all services that this instantiation service has created.
80
* - Will dispose all its children but not its parent.
81
* - Will NOT dispose services-instances that this service has been created with
82
* - Will NOT dispose consumer-instances this service has created
83
*/
84
dispose(): void;
85
}
86
87
88
/**
89
* Identifies a service of type `T`.
90
*/
91
export interface ServiceIdentifier<T> {
92
(...args: any[]): void;
93
type: T;
94
}
95
96
97
function storeServiceDependency(id: ServiceIdentifier<unknown>, target: Function, index: number): void {
98
if ((target as _util.DI_TARGET_OBJ)[_util.DI_TARGET] === target) {
99
(target as _util.DI_TARGET_OBJ)[_util.DI_DEPENDENCIES].push({ id, index });
100
} else {
101
(target as _util.DI_TARGET_OBJ)[_util.DI_DEPENDENCIES] = [{ id, index }];
102
(target as _util.DI_TARGET_OBJ)[_util.DI_TARGET] = target;
103
}
104
}
105
106
/**
107
* The *only* valid way to create a {{ServiceIdentifier}}.
108
*/
109
export function createDecorator<T>(serviceId: string): ServiceIdentifier<T> {
110
111
if (_util.serviceIds.has(serviceId)) {
112
return _util.serviceIds.get(serviceId)!;
113
}
114
115
const id = function (target: Function, key: string, index: number) {
116
if (arguments.length !== 3) {
117
throw new Error('@IServiceName-decorator can only be used to decorate a parameter');
118
}
119
storeServiceDependency(id, target, index);
120
} as ServiceIdentifier<T>;
121
122
id.toString = () => serviceId;
123
124
_util.serviceIds.set(serviceId, id);
125
return id;
126
}
127
128
export function refineServiceDecorator<T1, T extends T1>(serviceIdentifier: ServiceIdentifier<T1>): ServiceIdentifier<T> {
129
return <ServiceIdentifier<T>>serviceIdentifier;
130
}
131
132