mirror of
https://github.com/Microsoft/vscode
synced 2024-08-27 13:00:58 +00:00
propose extensions.allAcrossExtensionHosts
and related APIs, https://github.com/microsoft/vscode/issues/145307
This commit is contained in:
parent
9cd932c92f
commit
ad4470522e
|
@ -95,8 +95,13 @@ import { checkProposedApiEnabled, isProposedApiEnabled } from 'vs/workbench/serv
|
|||
import { DebugConfigurationProviderTriggerKind } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { ExtHostNotebookProxyKernels } from 'vs/workbench/api/common/extHostNotebookProxyKernels';
|
||||
|
||||
export interface IExtensionRegistries {
|
||||
mine: ExtensionDescriptionRegistry;
|
||||
all: ExtensionDescriptionRegistry;
|
||||
}
|
||||
|
||||
export interface IExtensionApiFactory {
|
||||
(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode;
|
||||
(extension: IExtensionDescription, extensionInfo: IExtensionRegistries, configProvider: ExtHostConfigProvider): typeof vscode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -196,7 +201,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
|||
// Register API-ish commands
|
||||
ExtHostApiCommands.register(extHostCommands);
|
||||
|
||||
return function (extension: IExtensionDescription, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode {
|
||||
return function (extension: IExtensionDescription, extensionInfo: IExtensionRegistries, configProvider: ExtHostConfigProvider): typeof vscode {
|
||||
|
||||
// Check document selectors for being overly generic. Technically this isn't a problem but
|
||||
// in practice many extensions say they support `fooLang` but need fs-access to do so. Those
|
||||
|
@ -360,10 +365,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
|||
Object.freeze(env);
|
||||
}
|
||||
|
||||
const extensionKind = initData.remote.isRemote
|
||||
? extHostTypes.ExtensionKind.Workspace
|
||||
: extHostTypes.ExtensionKind.UI;
|
||||
|
||||
// namespace: tests
|
||||
const tests: typeof vscode.tests = {
|
||||
createTestController(provider, label, refreshHandler?: (token: vscode.CancellationToken) => Thenable<void> | void) {
|
||||
return extHostTesting.createTestController(provider, label, refreshHandler);
|
||||
|
@ -387,19 +389,50 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
|||
};
|
||||
|
||||
// namespace: extensions
|
||||
const extensionKind = initData.remote.isRemote
|
||||
? extHostTypes.ExtensionKind.Workspace
|
||||
: extHostTypes.ExtensionKind.UI;
|
||||
|
||||
const extensions: typeof vscode.extensions = {
|
||||
getExtension(extensionId: string): vscode.Extension<any> | undefined {
|
||||
const desc = extensionRegistry.getExtensionDescription(extensionId);
|
||||
if (desc) {
|
||||
return new Extension(extensionService, extension.identifier, desc, extensionKind);
|
||||
getExtension(extensionId: string, includeFromDifferentExtensionHosts?: boolean): vscode.Extension<any> | undefined {
|
||||
if (!isProposedApiEnabled(extension, 'extensionsAny')) {
|
||||
includeFromDifferentExtensionHosts = false;
|
||||
}
|
||||
const mine = extensionInfo.mine.getExtensionDescription(extensionId);
|
||||
if (mine) {
|
||||
return new Extension(extensionService, extension.identifier, mine, extensionKind, false);
|
||||
}
|
||||
if (includeFromDifferentExtensionHosts) {
|
||||
const foreign = extensionInfo.all.getExtensionDescription(extensionId);
|
||||
if (foreign) {
|
||||
return new Extension(extensionService, extension.identifier, foreign, extensionKind /* TODO@alexdima THIS IS WRONG */, true);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
get all(): vscode.Extension<any>[] {
|
||||
return extensionRegistry.getAllExtensionDescriptions().map((desc) => new Extension(extensionService, extension.identifier, desc, extensionKind));
|
||||
const result: vscode.Extension<any>[] = [];
|
||||
for (const desc of extensionInfo.mine.getAllExtensionDescriptions()) {
|
||||
result.push(new Extension(extensionService, extension.identifier, desc, extensionKind, false));
|
||||
}
|
||||
return result;
|
||||
},
|
||||
get allAcrossExtensionHosts(): vscode.Extension<any>[] {
|
||||
checkProposedApiEnabled(extension, 'extensionsAny');
|
||||
const result: vscode.Extension<any>[] = [];
|
||||
for (const desc of extensionInfo.mine.getAllExtensionDescriptions()) {
|
||||
result.push(new Extension(extensionService, extension.identifier, desc, extensionKind, false));
|
||||
}
|
||||
for (const desc of extensionInfo.all.getAllExtensionDescriptions()) {
|
||||
result.push(new Extension(extensionService, extension.identifier, desc, extensionKind /* TODO@alexdima THIS IS WRONG */, true));
|
||||
}
|
||||
return result;
|
||||
},
|
||||
get onDidChange() {
|
||||
return extensionRegistry.onDidChange;
|
||||
if (isProposedApiEnabled(extension, 'extensionsAny')) {
|
||||
return Event.any(extensionInfo.mine.onDidChange, extensionInfo.all.onDidChange);
|
||||
}
|
||||
return extensionInfo.mine.onDidChange;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -513,7 +513,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme
|
|||
get extensionMode() { return extensionMode; },
|
||||
get extension() {
|
||||
if (extension === undefined) {
|
||||
extension = new Extension(that, extensionDescription.identifier, extensionDescription, extensionKind);
|
||||
extension = new Extension(that, extensionDescription.identifier, extensionDescription, extensionKind, false);
|
||||
}
|
||||
return extension;
|
||||
},
|
||||
|
@ -983,8 +983,9 @@ export class Extension<T extends object | null | undefined> implements vscode.Ex
|
|||
readonly extensionPath: string;
|
||||
readonly packageJSON: IExtensionDescription;
|
||||
readonly extensionKind: vscode.ExtensionKind;
|
||||
readonly isFromDifferentExtensionHost: boolean;
|
||||
|
||||
constructor(extensionService: IExtHostExtensionService, originExtensionId: ExtensionIdentifier, description: IExtensionDescription, kind: ExtensionKind) {
|
||||
constructor(extensionService: IExtHostExtensionService, originExtensionId: ExtensionIdentifier, description: IExtensionDescription, kind: ExtensionKind, isFromDifferentExtensionHost: boolean) {
|
||||
this.#extensionService = extensionService;
|
||||
this.#originExtensionId = originExtensionId;
|
||||
this.#identifier = description.identifier;
|
||||
|
@ -993,21 +994,27 @@ export class Extension<T extends object | null | undefined> implements vscode.Ex
|
|||
this.extensionPath = path.normalize(originalFSPath(description.extensionLocation));
|
||||
this.packageJSON = description;
|
||||
this.extensionKind = kind;
|
||||
this.isFromDifferentExtensionHost = isFromDifferentExtensionHost;
|
||||
}
|
||||
|
||||
get isActive(): boolean {
|
||||
// TODO@alexdima support this
|
||||
return this.#extensionService.isActivated(this.#identifier);
|
||||
}
|
||||
|
||||
get exports(): T {
|
||||
if (this.packageJSON.api === 'none') {
|
||||
if (this.packageJSON.api === 'none' || this.isFromDifferentExtensionHost) {
|
||||
return undefined!; // Strict nulloverride - Public api
|
||||
}
|
||||
return <T>this.#extensionService.getExtensionExports(this.#identifier);
|
||||
}
|
||||
|
||||
activate(): Thenable<T> {
|
||||
return this.#extensionService.activateByIdWithErrors(this.#identifier, { startup: false, extensionId: this.#originExtensionId, activationEvent: 'api' }).then(() => this.exports);
|
||||
async activate(): Promise<T> {
|
||||
if (this.isFromDifferentExtensionHost) {
|
||||
throw new Error('Cannot activate foreign extension'); // TODO@alexdima support this
|
||||
}
|
||||
await this.#extensionService.activateByIdWithErrors(this.#identifier, { startup: false, extensionId: this.#originExtensionId, activationEvent: 'api' });
|
||||
return this.exports;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,10 +8,9 @@ import { URI } from 'vs/base/common/uri';
|
|||
import { MainThreadTelemetryShape, MainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostConfigProvider, IExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { nullExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/common/extensionDescriptionRegistry';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtensionApiFactory } from 'vs/workbench/api/common/extHost.api.impl';
|
||||
import { IExtensionApiFactory, IExtensionRegistries } from 'vs/workbench/api/common/extHost.api.impl';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
@ -41,7 +40,7 @@ export abstract class RequireInterceptor {
|
|||
|
||||
constructor(
|
||||
private _apiFactory: IExtensionApiFactory,
|
||||
private _extensionRegistry: ExtensionDescriptionRegistry,
|
||||
private _extensionRegistry: IExtensionRegistries,
|
||||
@IInstantiationService private readonly _instaService: IInstantiationService,
|
||||
@IExtHostConfiguration private readonly _extHostConfiguration: IExtHostConfiguration,
|
||||
@IExtHostExtensionService private readonly _extHostExtensionService: IExtHostExtensionService,
|
||||
|
@ -156,7 +155,7 @@ class VSCodeNodeModuleFactory implements INodeModuleFactory {
|
|||
constructor(
|
||||
private readonly _apiFactory: IExtensionApiFactory,
|
||||
private readonly _extensionPaths: ExtensionPaths,
|
||||
private readonly _extensionRegistry: ExtensionDescriptionRegistry,
|
||||
private readonly _extensionRegistry: IExtensionRegistries,
|
||||
private readonly _configProvider: ExtHostConfigProvider,
|
||||
private readonly _logService: ILogService,
|
||||
) {
|
||||
|
|
|
@ -72,7 +72,7 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService {
|
|||
}
|
||||
|
||||
// Module loading tricks
|
||||
const interceptor = this._instaService.createInstance(NodeModuleRequireInterceptor, extensionApiFactory, this._myRegistry);
|
||||
const interceptor = this._instaService.createInstance(NodeModuleRequireInterceptor, extensionApiFactory, { mine: this._myRegistry, all: this._globalRegistry });
|
||||
await interceptor.install();
|
||||
performance.mark('code/extHost/didInitAPI');
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService {
|
|||
|
||||
// initialize API and register actors
|
||||
const apiFactory = this._instaService.invokeFunction(createApiFactoryAndRegisterActors);
|
||||
this._fakeModules = this._instaService.createInstance(WorkerRequireInterceptor, apiFactory, this._myRegistry);
|
||||
this._fakeModules = this._instaService.createInstance(WorkerRequireInterceptor, apiFactory, { mine: this._myRegistry, all: this._globalRegistry });
|
||||
await this._fakeModules.install();
|
||||
performance.mark('code/extHost/didInitAPI');
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ export const allApiProposals = Object.freeze({
|
|||
documentFiltersExclusive: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.documentFiltersExclusive.d.ts',
|
||||
editorInsets: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.editorInsets.d.ts',
|
||||
extensionRuntime: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.extensionRuntime.d.ts',
|
||||
extensionsAny: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.extensionsAny.d.ts',
|
||||
externalUriOpener: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.externalUriOpener.d.ts',
|
||||
fileSearchProvider: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.fileSearchProvider.d.ts',
|
||||
findTextInFiles: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.findTextInFiles.d.ts',
|
||||
|
|
40
src/vscode-dts/vscode.proposed.extensionsAny.d.ts
vendored
Normal file
40
src/vscode-dts/vscode.proposed.extensionsAny.d.ts
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
declare module 'vscode' {
|
||||
|
||||
// https://github.com/microsoft/vscode/issues/145307
|
||||
|
||||
export interface Extension<T> {
|
||||
|
||||
/**
|
||||
* `true` when the extension is associated to another extension host.
|
||||
*
|
||||
* *Note* that an extension from another extension host cannot export
|
||||
* API, e.g {@link Extension.exports its exports} are always `undefined`.
|
||||
*/
|
||||
readonly isFromDifferentExtensionHost: boolean;
|
||||
}
|
||||
|
||||
export namespace extensions {
|
||||
|
||||
/**
|
||||
* Get an extension by its full identifier in the form of: `publisher.name`.
|
||||
*
|
||||
* @param extensionId An extension identifier.
|
||||
* @param includeDifferentExtensionHosts Include extensions from different extension host
|
||||
* @return An extension or `undefined`.
|
||||
*/
|
||||
export function getExtension<T = any>(extensionId: string, includeDifferentExtensionHosts: boolean): Extension<T> | undefined;
|
||||
|
||||
/**
|
||||
* All extensions across all extension hosts.
|
||||
*
|
||||
* @see {@link Extension.isFromDifferentExtensionHost}
|
||||
*/
|
||||
export const allAcrossExtensionHosts: readonly Extension<void>[];
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue