mirror of
https://github.com/Microsoft/vscode
synced 2024-10-12 22:37:41 +00:00
Our code currently uses the `IConstructorSignature` types in a two main ways: - As argument types in functions that take a service constructor. - As return types or property types when we expose a service constructor in the API This first usage is not valid with strict function types. The reason is that the `IConstructorSignature` types takes a rest array of `...services: BrandedService[]` , while the concrete constructors you pass in use actual services. With strict function types, you cannot convert the concrete constructor type to an `IConstructorSignature` because this would drop important type information that the implementation needs. As an example ```ts class Foo { constructor(@ILogService service: ILogService) {} } registerFoo(Foo); // The type of `ctor` inlines `IConstructorSignature0` function registerFoo(ctor: { new(....serivces: BrandedService[]): Foo}) { // When registerFoo(Foo) is called, the implementation here would need to know that // ctor needs to be invoked with exactly one `ILogService`. However the type of `IConstructorSignature0` // does not express this. Strict function types therefore disallows this conversion } ``` To fix this, I have converted a few places were we were taking `IConstructorSignature` arguments so that they preserve the full type of the constructor. This fixed over half of our 900 strict function type errors. Unfortunatly I can not figure out a more elegant way to express this besides inlining the types However, even after this change, we still need to figure out how to deal with: - Places in the code where `IConstructorSignature` is exposed as a return type or object property - How to deal with all of our descriptor types (such as `SyncActionDescriptor`)
This commit is contained in:
parent
92caa97a1a
commit
a77da1b1d8
|
@ -16,7 +16,7 @@ import { ITextModelService } from 'vs/editor/common/services/resolverService';
|
|||
import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions';
|
||||
import { CommandsRegistry, ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
|
||||
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IConstructorSignature1, ServicesAccessor as InstantiationServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IConstructorSignature1, ServicesAccessor as InstantiationServicesAccessor, BrandedService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IKeybindings, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
|
@ -303,7 +303,7 @@ export function registerInstantiatedEditorAction(editorAction: EditorAction): vo
|
|||
EditorContributionRegistry.INSTANCE.registerEditorAction(editorAction);
|
||||
}
|
||||
|
||||
export function registerEditorContribution(id: string, ctor: IEditorContributionCtor): void {
|
||||
export function registerEditorContribution<Services extends BrandedService[]>(id: string, ctor: { new(editor: ICodeEditor, ...services: Services): IEditorContribution }): void {
|
||||
EditorContributionRegistry.INSTANCE.registerEditorContribution(id, ctor);
|
||||
}
|
||||
|
||||
|
@ -355,7 +355,7 @@ class EditorContributionRegistry {
|
|||
this.editorCommands = Object.create(null);
|
||||
}
|
||||
|
||||
public registerEditorContribution(id: string, ctor: IEditorContributionCtor): void {
|
||||
public registerEditorContribution<Services extends BrandedService[]>(id: string, ctor: { new(editor: ICodeEditor, ...services: Services): IEditorContribution }): void {
|
||||
this.editorContributions.push({ id, ctor });
|
||||
}
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { SyncDescriptor } from './descriptors';
|
||||
import { ServiceIdentifier, IConstructorSignature0 } from './instantiation';
|
||||
import { ServiceIdentifier, BrandedService } from './instantiation';
|
||||
|
||||
const _registry: [ServiceIdentifier<any>, SyncDescriptor<any>][] = [];
|
||||
|
||||
export function registerSingleton<T>(id: ServiceIdentifier<T>, ctor: IConstructorSignature0<T>, supportsDelayedInstantiation?: boolean): void {
|
||||
export function registerSingleton<T, Services extends BrandedService[]>(id: ServiceIdentifier<T>, ctor: { new(...services: Services): T }, supportsDelayedInstantiation?: boolean): void {
|
||||
_registry.push([id, new SyncDescriptor<T>(ctor, [], supportsDelayedInstantiation)]);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ export namespace _util {
|
|||
|
||||
// --- interfaces ------
|
||||
|
||||
type BrandedService = { _serviceBrand: undefined };
|
||||
export type BrandedService = { _serviceBrand: undefined };
|
||||
|
||||
export interface IConstructorSignature0<T> {
|
||||
new(...services: BrandedService[]): T;
|
||||
|
@ -101,7 +101,8 @@ export interface IInstantiationService {
|
|||
createInstance<A1, A2, A3, A4, A5, A6, A7, T>(descriptor: descriptors.SyncDescriptor7<A1, A2, A3, A4, A5, A6, A7, T>, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6, a7: A7): T;
|
||||
createInstance<A1, A2, A3, A4, A5, A6, A7, A8, T>(descriptor: descriptors.SyncDescriptor8<A1, A2, A3, A4, A5, A6, A7, A8, T>, a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6, a7: A7, a8: A8): T;
|
||||
|
||||
createInstance<Ctor extends new (...args: any) => any, R extends InstanceType<Ctor>>(t: Ctor, ...args: GetLeadingNonServiceArgs<ConstructorParameters<Ctor>>): R;
|
||||
createInstance<Ctor extends new (...args: any[]) => any, R extends InstanceType<Ctor>>(t: Ctor, ...args: GetLeadingNonServiceArgs<ConstructorParameters<Ctor>>): R;
|
||||
createInstance<Services extends BrandedService[], Ctor extends new (...services: Services) => any, R extends InstanceType<Ctor>>(t: Ctor): R;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IConstructorSignature1 } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IConstructorSignature1, BrandedService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtHostContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ProxyIdentifier } from 'vs/workbench/services/extensions/common/proxyIdentifier';
|
||||
|
||||
|
@ -13,12 +13,12 @@ export type IExtHostNamedCustomer<T extends IDisposable> = [ProxyIdentifier<T>,
|
|||
export type IExtHostCustomerCtor<T extends IDisposable> = IConstructorSignature1<IExtHostContext, T>;
|
||||
|
||||
export function extHostNamedCustomer<T extends IDisposable>(id: ProxyIdentifier<T>) {
|
||||
return function (ctor: IExtHostCustomerCtor<T>): void {
|
||||
return function <Services extends BrandedService[]>(ctor: { new(context: IExtHostContext, ...services: Services): T }): void {
|
||||
ExtHostCustomersRegistryImpl.INSTANCE.registerNamedCustomer(id, ctor);
|
||||
};
|
||||
}
|
||||
|
||||
export function extHostCustomer<T extends IDisposable>(ctor: IExtHostCustomerCtor<T>): void {
|
||||
export function extHostCustomer<T extends IDisposable, Services extends BrandedService[]>(ctor: { new(context: IExtHostContext, ...services: Services): T }): void {
|
||||
ExtHostCustomersRegistryImpl.INSTANCE.registerCustomer(ctor);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
|
|||
import { IAction } from 'vs/base/common/actions';
|
||||
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { ITree, IActionProvider } from 'vs/base/parts/tree/browser/tree';
|
||||
import { IInstantiationService, IConstructorSignature0, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IInstantiationService, IConstructorSignature0, ServicesAccessor, BrandedService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
/**
|
||||
* The action bar contributor allows to add actions to an actionbar in a given context.
|
||||
|
@ -134,7 +134,7 @@ export interface IActionBarRegistry {
|
|||
* Registers an Actionbar contributor. It will be called to contribute actions to all the action bars
|
||||
* that are used in the Workbench in the given scope.
|
||||
*/
|
||||
registerActionBarContributor(scope: string, ctor: IConstructorSignature0<ActionBarContributor>): void;
|
||||
registerActionBarContributor<Services extends BrandedService[]>(scope: string, ctor: { new(...services: Services): ActionBarContributor }): void;
|
||||
|
||||
/**
|
||||
* Returns an array of registered action bar contributors known to the workbench for the given scope.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IInstantiationService, IConstructorSignature0, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IInstantiationService, IConstructorSignature0, ServicesAccessor, BrandedService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ILifecycleService, LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { runWhenIdle, IdleDeadline } from 'vs/base/common/async';
|
||||
|
@ -19,7 +19,7 @@ export namespace Extensions {
|
|||
export const Workbench = 'workbench.contributions.kind';
|
||||
}
|
||||
|
||||
export type IWorkbenchContributionSignature = IConstructorSignature0<IWorkbenchContribution>;
|
||||
type IWorkbenchContributionSignature<Service extends BrandedService[]> = new (...services: Service) => IWorkbenchContribution;
|
||||
|
||||
export interface IWorkbenchContributionsRegistry {
|
||||
|
||||
|
@ -29,7 +29,7 @@ export interface IWorkbenchContributionsRegistry {
|
|||
*
|
||||
* @param phase the lifecycle phase when to instantiate the contribution.
|
||||
*/
|
||||
registerWorkbenchContribution(contribution: IWorkbenchContributionSignature, phase: LifecyclePhase): void;
|
||||
registerWorkbenchContribution<Services extends BrandedService[]>(contribution: IWorkbenchContributionSignature<Services>, phase: LifecyclePhase): void;
|
||||
|
||||
/**
|
||||
* Starts the registry by providing the required services.
|
||||
|
@ -43,8 +43,7 @@ class WorkbenchContributionsRegistry implements IWorkbenchContributionsRegistry
|
|||
|
||||
private readonly toBeInstantiated: Map<LifecyclePhase, IConstructorSignature0<IWorkbenchContribution>[]> = new Map<LifecyclePhase, IConstructorSignature0<IWorkbenchContribution>[]>();
|
||||
|
||||
registerWorkbenchContribution(ctor: IWorkbenchContributionSignature, phase: LifecyclePhase = LifecyclePhase.Starting): void {
|
||||
|
||||
registerWorkbenchContribution<Services extends BrandedService[]>(ctor: { new(...services: Services): IWorkbenchContribution }, phase: LifecyclePhase = LifecyclePhase.Starting): void {
|
||||
// Instantiate directly if we are already matching the provided phase
|
||||
if (this.instantiationService && this.lifecycleService && this.lifecycleService.phase >= phase) {
|
||||
this.instantiationService.createInstance(ctor);
|
||||
|
|
Loading…
Reference in a new issue