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