mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-27 12:04:04 +01:00
Merge remote-tracking branch 'origin/master' into aeschli/theming-api
This commit is contained in:
@@ -8,7 +8,7 @@ import * as objects from 'vs/base/common/objects';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
import { ExtensionsRegistry, IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry';
|
||||
import { IConfigurationNode, IConfigurationRegistry, Extensions, editorConfigurationSchemaId, IDefaultConfigurationExtension, validateProperty, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IConfigurationNode, IConfigurationRegistry, Extensions, resourceLanguageSettingsSchemaId, IDefaultConfigurationExtension, validateProperty, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
|
||||
import { workspaceSettingsSchemaId, launchSchemaId, tasksSchemaId } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { isObject } from 'vs/base/common/types';
|
||||
@@ -48,7 +48,7 @@ const configurationEntrySchema: IJSONSchema = {
|
||||
nls.localize('scope.resource.description', "Configuration that can be configured in the user, remote, workspace or folder settings."),
|
||||
nls.localize('scope.machine-overridable.description', "Machine configuration that can be configured also in workspace or folder settings.")
|
||||
],
|
||||
description: nls.localize('scope.description', "Scope in which the configuration is applicable. Available scopes are `application`, `machine`, `window`, `resource` and `machine-overridable`.")
|
||||
description: nls.localize('scope.description', "Scope in which the configuration is applicable. Available scopes are `application`, `machine`, `window`, `resource`, and `machine-overridable`.")
|
||||
},
|
||||
enumDescriptions: {
|
||||
type: 'array',
|
||||
@@ -57,12 +57,12 @@ const configurationEntrySchema: IJSONSchema = {
|
||||
},
|
||||
description: nls.localize('scope.enumDescriptions', 'Descriptions for enum values')
|
||||
},
|
||||
markdownEnumDescription: {
|
||||
markdownEnumDescriptions: {
|
||||
type: 'array',
|
||||
items: {
|
||||
type: 'string',
|
||||
},
|
||||
description: nls.localize('scope.markdownEnumDescription', 'Descriptions for enum values in the markdown format.')
|
||||
description: nls.localize('scope.markdownEnumDescriptions', 'Descriptions for enum values in the markdown format.')
|
||||
},
|
||||
markdownDescription: {
|
||||
type: 'string',
|
||||
@@ -90,7 +90,7 @@ const defaultConfigurationExtPoint = ExtensionsRegistry.registerExtensionPoint<I
|
||||
'\\[.*\\]$': {
|
||||
type: 'object',
|
||||
default: {},
|
||||
$ref: editorConfigurationSchemaId,
|
||||
$ref: resourceLanguageSettingsSchemaId,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -218,6 +218,8 @@ function validateProperties(configuration: IConfigurationNode, extension: IExten
|
||||
propertyConfiguration.scope = ConfigurationScope.RESOURCE;
|
||||
} else if (propertyConfiguration.scope.toString() === 'machine-overridable') {
|
||||
propertyConfiguration.scope = ConfigurationScope.MACHINE_OVERRIDABLE;
|
||||
} else if (propertyConfiguration.scope.toString() === 'resource-language') {
|
||||
propertyConfiguration.scope = ConfigurationScope.RESOURCE_LANGUAGE;
|
||||
} else {
|
||||
propertyConfiguration.scope = ConfigurationScope.WINDOW;
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ import { IURITransformerService } from 'vs/workbench/api/common/extHostUriTransf
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { ExtHostTheming } from 'vs/workbench/api/common/extHostTheming';
|
||||
import { IExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
|
||||
export interface IExtensionApiFactory {
|
||||
(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode;
|
||||
@@ -87,6 +88,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
const rpcProtocol = accessor.get(IExtHostRpcService);
|
||||
const extHostStorage = accessor.get(IExtHostStorage);
|
||||
const extHostLogService = accessor.get(ILogService);
|
||||
const extHostTunnelService = accessor.get(IExtHostTunnelService);
|
||||
|
||||
// register addressable instances
|
||||
rpcProtocol.set(ExtHostContext.ExtHostLogService, <ExtHostLogServiceShape><any>extHostLogService);
|
||||
@@ -94,6 +96,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
rpcProtocol.set(ExtHostContext.ExtHostConfiguration, extHostConfiguration);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostExtensionService, extensionService);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostStorage, extHostStorage);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostTunnelService, extHostTunnelService);
|
||||
|
||||
// automatically create and register addressable instances
|
||||
const extHostDecorations = rpcProtocol.set(ExtHostContext.ExtHostDecorations, accessor.get(IExtHostDecorations));
|
||||
@@ -227,10 +230,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
get appName() { return initData.environment.appName; },
|
||||
get appRoot() { return initData.environment.appRoot!.fsPath; },
|
||||
get uriScheme() { return initData.environment.appUriScheme; },
|
||||
createAppUri(options?) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostUrls.proposedCreateAppUri(extension.identifier, options);
|
||||
},
|
||||
get logLevel() {
|
||||
checkProposedApiEnabled(extension);
|
||||
return typeConverters.LogLevel.to(extHostLogService.getLevel());
|
||||
@@ -502,7 +501,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
return extHostStatusBar.setStatusBarMessage(text, timeoutOrThenable);
|
||||
},
|
||||
withScmProgress<R>(task: (progress: vscode.Progress<number>) => Thenable<R>) {
|
||||
console.warn(`[Deprecation Warning] function 'withScmProgress' is deprecated and should no longer be used. Use 'withProgress' instead.`);
|
||||
return extHostProgress.withProgress(extension, { location: extHostTypes.ProgressLocation.SourceControl }, (progress, token) => task({ report(n: number) { /*noop*/ } }));
|
||||
},
|
||||
withProgress<R>(options: vscode.ProgressOptions, task: (progress: vscode.Progress<{ message?: string; worked?: number }>, token: vscode.CancellationToken) => Thenable<R>) {
|
||||
@@ -536,9 +534,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
registerWebviewPanelSerializer: (viewType: string, serializer: vscode.WebviewPanelSerializer) => {
|
||||
return extHostWebviews.registerWebviewPanelSerializer(extension, viewType, serializer);
|
||||
},
|
||||
registerWebviewEditorProvider: (viewType: string, provider: vscode.WebviewEditorProvider, options?: vscode.WebviewPanelOptions) => {
|
||||
registerWebviewCustomEditorProvider: (viewType: string, provider: vscode.WebviewCustomEditorProvider, options?: vscode.WebviewPanelOptions) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostWebviews.registerWebviewEditorProvider(extension, viewType, provider, options);
|
||||
return extHostWebviews.registerWebviewCustomEditorProvider(extension, viewType, provider, options);
|
||||
},
|
||||
registerDecorationProvider(provider: vscode.DecorationProvider) {
|
||||
checkProposedApiEnabled(extension);
|
||||
@@ -567,7 +565,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
get rootPath() {
|
||||
if (extension.isUnderDevelopment && !warnedRootPathDeprecated) {
|
||||
warnedRootPathDeprecated = true;
|
||||
console.warn(`[Deprecation Warning] 'workspace.rootPath' is deprecated and should no longer be used. Please use 'workspace.workspaceFolders' instead. More details: https://aka.ms/vscode-eliminating-rootpath`);
|
||||
extHostLogService.warn(`[Deprecation Warning] 'workspace.rootPath' is deprecated and should no longer be used. Please use 'workspace.workspaceFolders' instead. More details: https://aka.ms/vscode-eliminating-rootpath`);
|
||||
}
|
||||
|
||||
return extHostWorkspace.getPath();
|
||||
@@ -674,9 +672,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
onDidChangeConfiguration: (listener: (_: any) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) => {
|
||||
return configProvider.onDidChangeConfiguration(listener, thisArgs, disposables);
|
||||
},
|
||||
getConfiguration(section?: string, resource?: vscode.Uri): vscode.WorkspaceConfiguration {
|
||||
resource = arguments.length === 1 ? undefined : resource;
|
||||
return configProvider.getConfiguration(section, resource, extension.identifier);
|
||||
getConfiguration(section?: string, scope?: vscode.ConfigurationScope | null): vscode.WorkspaceConfiguration {
|
||||
scope = arguments.length === 1 ? undefined : scope;
|
||||
return configProvider.getConfiguration(section, scope, extension);
|
||||
},
|
||||
registerTextDocumentContentProvider(scheme: string, provider: vscode.TextDocumentContentProvider) {
|
||||
return extHostDocumentContentProviders.registerTextDocumentContentProvider(scheme, provider);
|
||||
@@ -707,28 +705,26 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
return extHostLabelService.$registerResourceLabelFormatter(formatter);
|
||||
},
|
||||
onDidCreateFiles: (listener, thisArg, disposables) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostFileSystemEvent.onDidCreateFile(listener, thisArg, disposables);
|
||||
},
|
||||
onDidDeleteFiles: (listener, thisArg, disposables) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostFileSystemEvent.onDidDeleteFile(listener, thisArg, disposables);
|
||||
},
|
||||
onDidRenameFiles: (listener, thisArg, disposables) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostFileSystemEvent.onDidRenameFile(listener, thisArg, disposables);
|
||||
},
|
||||
onWillCreateFiles: (listener: (e: vscode.FileWillCreateEvent) => any, thisArg?: any, disposables?: vscode.Disposable[]) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostFileSystemEvent.getOnWillCreateFileEvent(extension)(listener, thisArg, disposables);
|
||||
},
|
||||
onWillDeleteFiles: (listener: (e: vscode.FileWillDeleteEvent) => any, thisArg?: any, disposables?: vscode.Disposable[]) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostFileSystemEvent.getOnWillDeleteFileEvent(extension)(listener, thisArg, disposables);
|
||||
},
|
||||
onWillRenameFiles: (listener: (e: vscode.FileWillRenameEvent) => any, thisArg?: any, disposables?: vscode.Disposable[]) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostFileSystemEvent.getOnWillRenameFileEvent(extension)(listener, thisArg, disposables);
|
||||
},
|
||||
openTunnel: (forward: vscode.TunnelOptions) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostTunnelService.openTunnel(forward);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import { IModelChangedEvent } from 'vs/editor/common/model/mirrorTextModel';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { CharacterPair, CommentRule, EnterAction } from 'vs/editor/common/modes/languageConfiguration';
|
||||
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
|
||||
import { ConfigurationTarget, IConfigurationData, IConfigurationModel } from 'vs/platform/configuration/common/configuration';
|
||||
import { ConfigurationTarget, IConfigurationData, IConfigurationChange, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration';
|
||||
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import * as files from 'vs/platform/files/common/files';
|
||||
@@ -47,6 +47,8 @@ import { createExtHostContextProxyIdentifier as createExtId, createMainContextPr
|
||||
import * as search from 'vs/workbench/services/search/common/search';
|
||||
import { SaveReason } from 'vs/workbench/common/editor';
|
||||
import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator';
|
||||
import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { TunnelOptions } from 'vs/platform/remote/common/tunnel';
|
||||
|
||||
export interface IEnvironment {
|
||||
isExtensionDevelopmentDebug: boolean;
|
||||
@@ -86,6 +88,7 @@ export interface IInitData {
|
||||
telemetryInfo: ITelemetryInfo;
|
||||
logLevel: LogLevel;
|
||||
logsLocation: URI;
|
||||
logFile: URI;
|
||||
autoStart: boolean;
|
||||
remote: { isRemote: boolean; authority: string | undefined; };
|
||||
uiKind: UIKind;
|
||||
@@ -95,11 +98,6 @@ export interface IConfigurationInitData extends IConfigurationData {
|
||||
configurationScopes: [string, ConfigurationScope | undefined][];
|
||||
}
|
||||
|
||||
export interface IWorkspaceConfigurationChangeEventData {
|
||||
changedConfiguration: IConfigurationModel;
|
||||
changedConfigurationByResource: { [folder: string]: IConfigurationModel; };
|
||||
}
|
||||
|
||||
export interface IExtHostContext extends IRPCProtocol {
|
||||
remoteAuthority: string;
|
||||
}
|
||||
@@ -150,8 +148,8 @@ export interface MainThreadCommentsShape extends IDisposable {
|
||||
}
|
||||
|
||||
export interface MainThreadConfigurationShape extends IDisposable {
|
||||
$updateConfigurationOption(target: ConfigurationTarget | null, key: string, value: any, resource: UriComponents | undefined): Promise<void>;
|
||||
$removeConfigurationOption(target: ConfigurationTarget | null, key: string, resource: UriComponents | undefined): Promise<void>;
|
||||
$updateConfigurationOption(target: ConfigurationTarget | null, key: string, value: any, overrides: IConfigurationOverrides | undefined, scopeToLanguage: boolean | undefined): Promise<void>;
|
||||
$removeConfigurationOption(target: ConfigurationTarget | null, key: string, overrides: IConfigurationOverrides | undefined, scopeToLanguage: boolean | undefined): Promise<void>;
|
||||
}
|
||||
|
||||
export interface MainThreadDiagnosticsShape extends IDisposable {
|
||||
@@ -556,6 +554,10 @@ export interface WebviewExtensionDescription {
|
||||
readonly location: UriComponents;
|
||||
}
|
||||
|
||||
export enum WebviewEditorCapabilities {
|
||||
Editable,
|
||||
}
|
||||
|
||||
export interface MainThreadWebviewsShape extends IDisposable {
|
||||
$createWebviewPanel(extension: WebviewExtensionDescription, handle: WebviewPanelHandle, viewType: string, title: string, showOptions: WebviewPanelShowOptions, options: modes.IWebviewPanelOptions & modes.IWebviewOptions): void;
|
||||
$disposeWebview(handle: WebviewPanelHandle): void;
|
||||
@@ -571,10 +573,10 @@ export interface MainThreadWebviewsShape extends IDisposable {
|
||||
$registerSerializer(viewType: string): void;
|
||||
$unregisterSerializer(viewType: string): void;
|
||||
|
||||
$registerEditorProvider(extension: WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions): void;
|
||||
$registerEditorProvider(extension: WebviewExtensionDescription, viewType: string, options: modes.IWebviewPanelOptions, capabilities: readonly WebviewEditorCapabilities[]): void;
|
||||
$unregisterEditorProvider(viewType: string): void;
|
||||
|
||||
$onEdit(handle: WebviewPanelHandle, editJson: any): void;
|
||||
$onEdit(resource: UriComponents, viewType: string, editJson: any): void;
|
||||
}
|
||||
|
||||
export interface WebviewPanelViewStateData {
|
||||
@@ -592,20 +594,19 @@ export interface ExtHostWebviewsShape {
|
||||
$onDidDisposeWebviewPanel(handle: WebviewPanelHandle): Promise<void>;
|
||||
|
||||
$deserializeWebviewPanel(newWebviewHandle: WebviewPanelHandle, viewType: string, title: string, state: any, position: EditorViewColumn, options: modes.IWebviewOptions & modes.IWebviewPanelOptions): Promise<void>;
|
||||
$resolveWebviewEditor(input: { resource: UriComponents, edits: readonly any[] }, newWebviewHandle: WebviewPanelHandle, viewType: string, title: string, position: EditorViewColumn, options: modes.IWebviewOptions & modes.IWebviewPanelOptions): Promise<void>;
|
||||
$resolveWebviewEditor(resource: UriComponents, newWebviewHandle: WebviewPanelHandle, viewType: string, title: string, position: EditorViewColumn, options: modes.IWebviewOptions & modes.IWebviewPanelOptions): Promise<void>;
|
||||
|
||||
$undoEdits(handle: WebviewPanelHandle, edits: readonly any[]): void;
|
||||
$applyEdits(handle: WebviewPanelHandle, edits: readonly any[]): void;
|
||||
$undoEdits(resource: UriComponents, viewType: string, edits: readonly any[]): void;
|
||||
$applyEdits(resource: UriComponents, viewType: string, edits: readonly any[]): void;
|
||||
|
||||
$onSave(handle: WebviewPanelHandle): Promise<void>;
|
||||
$onSaveAs(handle: WebviewPanelHandle, resource: UriComponents, targetResource: UriComponents): Promise<void>;
|
||||
$onSave(resource: UriComponents, viewType: string): Promise<void>;
|
||||
$onSaveAs(resource: UriComponents, viewType: string, targetResource: UriComponents): Promise<void>;
|
||||
}
|
||||
|
||||
export interface MainThreadUrlsShape extends IDisposable {
|
||||
$registerUriHandler(handle: number, extensionId: ExtensionIdentifier): Promise<void>;
|
||||
$unregisterUriHandler(handle: number): Promise<void>;
|
||||
$createAppUri(uri: UriComponents): Promise<UriComponents>;
|
||||
$proposedCreateAppUri(extensionId: ExtensionIdentifier, options?: { payload?: Partial<UriComponents>; }): Promise<UriComponents>;
|
||||
}
|
||||
|
||||
export interface ExtHostUrlsShape {
|
||||
@@ -772,6 +773,13 @@ export interface MainThreadWindowShape extends IDisposable {
|
||||
$asExternalUri(uri: UriComponents, options: IOpenUriOptions): Promise<UriComponents>;
|
||||
}
|
||||
|
||||
export interface MainThreadTunnelServiceShape extends IDisposable {
|
||||
$openTunnel(tunnelOptions: TunnelOptions): Promise<TunnelDto | undefined>;
|
||||
$closeTunnel(remote: { host: string, port: number }): Promise<void>;
|
||||
$registerCandidateFinder(): Promise<void>;
|
||||
$setTunnelProvider(): Promise<void>;
|
||||
}
|
||||
|
||||
// -- extension host
|
||||
|
||||
export interface ExtHostCommandsShape {
|
||||
@@ -781,7 +789,7 @@ export interface ExtHostCommandsShape {
|
||||
|
||||
export interface ExtHostConfigurationShape {
|
||||
$initializeConfiguration(data: IConfigurationInitData): void;
|
||||
$acceptConfigurationChanged(data: IConfigurationInitData, eventData: IWorkspaceConfigurationChangeEventData): void;
|
||||
$acceptConfigurationChanged(data: IConfigurationInitData, change: IConfigurationChange): void;
|
||||
}
|
||||
|
||||
export interface ExtHostDiagnosticsShape {
|
||||
@@ -1181,7 +1189,7 @@ export interface ExtHostLanguageFeaturesShape {
|
||||
$provideColorPresentations(handle: number, resource: UriComponents, colorInfo: IRawColorInfo, token: CancellationToken): Promise<modes.IColorPresentation[] | undefined>;
|
||||
$provideFoldingRanges(handle: number, resource: UriComponents, context: modes.FoldingContext, token: CancellationToken): Promise<modes.FoldingRange[] | undefined>;
|
||||
$provideSelectionRanges(handle: number, resource: UriComponents, positions: IPosition[], token: CancellationToken): Promise<modes.SelectionRange[][]>;
|
||||
$prepareCallHierarchy(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<ICallHierarchyItemDto | undefined>;
|
||||
$prepareCallHierarchy(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<ICallHierarchyItemDto[] | undefined>;
|
||||
$provideCallHierarchyIncomingCalls(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<IIncomingCallDto[] | undefined>;
|
||||
$provideCallHierarchyOutgoingCalls(handle: number, sessionId: string, itemId: string, token: CancellationToken): Promise<IOutgoingCallDto[] | undefined>;
|
||||
$releaseCallHierarchy(handle: number, sessionId: string): void;
|
||||
@@ -1282,6 +1290,7 @@ export interface IDataBreakpointDto extends IBreakpointDto {
|
||||
dataId: string;
|
||||
canPersist: boolean;
|
||||
label: string;
|
||||
accessTypes?: DebugProtocol.DataBreakpointAccessType[];
|
||||
}
|
||||
|
||||
export interface ISourceBreakpointDto extends IBreakpointDto {
|
||||
@@ -1391,6 +1400,13 @@ export interface ExtHostThemingShape {
|
||||
|
||||
export interface MainThreadThemingShape extends IDisposable {
|
||||
}
|
||||
|
||||
export interface ExtHostTunnelServiceShape {
|
||||
$findCandidatePorts(): Promise<{ host: string, port: number, detail: string }[]>;
|
||||
$forwardPort(tunnelOptions: TunnelOptions): Promise<TunnelDto> | undefined;
|
||||
$closeTunnel(remote: { host: string, port: number }): Promise<void>;
|
||||
}
|
||||
|
||||
// --- proxy identifiers
|
||||
|
||||
export const MainContext = {
|
||||
@@ -1432,7 +1448,8 @@ export const MainContext = {
|
||||
MainThreadTask: createMainId<MainThreadTaskShape>('MainThreadTask'),
|
||||
MainThreadWindow: createMainId<MainThreadWindowShape>('MainThreadWindow'),
|
||||
MainThreadLabelService: createMainId<MainThreadLabelServiceShape>('MainThreadLabelService'),
|
||||
MainThreadTheming: createMainId<MainThreadThemingShape>('MainThreadTheming')
|
||||
MainThreadTheming: createMainId<MainThreadThemingShape>('MainThreadTheming'),
|
||||
MainThreadTunnelService: createMainId<MainThreadTunnelServiceShape>('MainThreadTunnelService')
|
||||
};
|
||||
|
||||
export const ExtHostContext = {
|
||||
@@ -1467,5 +1484,6 @@ export const ExtHostContext = {
|
||||
ExtHostUrls: createExtId<ExtHostUrlsShape>('ExtHostUrls'),
|
||||
ExtHostOutputService: createMainId<ExtHostOutputServiceShape>('ExtHostOutputService'),
|
||||
ExtHostLabelService: createMainId<ExtHostLabelServiceShape>('ExtHostLabelService'),
|
||||
ExtHostTheming: createMainId<ExtHostThemingShape>('ExtHostTheming')
|
||||
ExtHostTheming: createMainId<ExtHostThemingShape>('ExtHostTheming'),
|
||||
ExtHostTunnelService: createMainId<ExtHostTunnelServiceShape>('ExtHostTunnelService')
|
||||
};
|
||||
|
||||
@@ -27,6 +27,7 @@ export class ApiCommandArgument<V, O = V> {
|
||||
|
||||
static readonly Uri = new ApiCommandArgument<URI>('uri', 'Uri of a text document', v => URI.isUri(v), v => v);
|
||||
static readonly Position = new ApiCommandArgument<types.Position, IPosition>('position', 'A position in a text document', v => types.Position.isPosition(v), typeConverters.Position.from);
|
||||
static readonly Range = new ApiCommandArgument<types.Range, IRange>('range', 'A range in a text document', v => types.Range.isRange(v), typeConverters.Range.from);
|
||||
|
||||
static readonly CallHierarchyItem = new ApiCommandArgument('item', 'A call hierarchy item', v => v instanceof types.CallHierarchyItem, typeConverters.CallHierarchyItem.to);
|
||||
|
||||
@@ -42,7 +43,7 @@ export class ApiCommandResult<V, O = V> {
|
||||
|
||||
constructor(
|
||||
readonly description: string,
|
||||
readonly convert: (v: V) => O
|
||||
readonly convert: (v: V, apiArgs: any[]) => O
|
||||
) { }
|
||||
}
|
||||
|
||||
@@ -68,7 +69,7 @@ export class ApiCommand {
|
||||
});
|
||||
|
||||
const internalResult = await commands.executeCommand(this.internalId, ...internalArgs);
|
||||
return this.result.convert(internalResult);
|
||||
return this.result.convert(internalResult, apiArgs);
|
||||
}, undefined, this._getCommandHandlerDesc());
|
||||
}
|
||||
|
||||
@@ -83,6 +84,123 @@ export class ApiCommand {
|
||||
|
||||
|
||||
const newCommands: ApiCommand[] = [
|
||||
// -- document highlights
|
||||
new ApiCommand(
|
||||
'vscode.executeDocumentHighlights', '_executeDocumentHighlights', 'Execute document highlight provider.',
|
||||
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
|
||||
new ApiCommandResult<modes.DocumentHighlight[], types.DocumentHighlight[] | undefined>('A promise that resolves to an array of SymbolInformation and DocumentSymbol instances.', tryMapWith(typeConverters.DocumentHighlight.to))
|
||||
),
|
||||
// -- document symbols
|
||||
new ApiCommand(
|
||||
'vscode.executeDocumentSymbolProvider', '_executeDocumentSymbolProvider', 'Execute document symbol provider.',
|
||||
[ApiCommandArgument.Uri],
|
||||
new ApiCommandResult<modes.DocumentSymbol[], vscode.SymbolInformation[] | undefined>('A promise that resolves to an array of DocumentHighlight-instances.', (value, apiArgs) => {
|
||||
|
||||
if (isFalsyOrEmpty(value)) {
|
||||
return undefined;
|
||||
}
|
||||
class MergedInfo extends types.SymbolInformation implements vscode.DocumentSymbol {
|
||||
static to(symbol: modes.DocumentSymbol): MergedInfo {
|
||||
const res = new MergedInfo(
|
||||
symbol.name,
|
||||
typeConverters.SymbolKind.to(symbol.kind),
|
||||
symbol.containerName || '',
|
||||
new types.Location(apiArgs[0], typeConverters.Range.to(symbol.range))
|
||||
);
|
||||
res.detail = symbol.detail;
|
||||
res.range = res.location.range;
|
||||
res.selectionRange = typeConverters.Range.to(symbol.selectionRange);
|
||||
res.children = symbol.children ? symbol.children.map(MergedInfo.to) : [];
|
||||
return res;
|
||||
}
|
||||
|
||||
detail!: string;
|
||||
range!: vscode.Range;
|
||||
selectionRange!: vscode.Range;
|
||||
children!: vscode.DocumentSymbol[];
|
||||
containerName!: string;
|
||||
}
|
||||
return value.map(MergedInfo.to);
|
||||
|
||||
})
|
||||
),
|
||||
// -- formatting
|
||||
new ApiCommand(
|
||||
'vscode.executeFormatDocumentProvider', '_executeFormatDocumentProvider', 'Execute document format provider.',
|
||||
[ApiCommandArgument.Uri, new ApiCommandArgument('options', 'Formatting options', _ => true, v => v)],
|
||||
new ApiCommandResult<ISingleEditOperation[], types.TextEdit[] | undefined>('A promise that resolves to an array of TextEdits.', tryMapWith(typeConverters.TextEdit.to))
|
||||
),
|
||||
new ApiCommand(
|
||||
'vscode.executeFormatRangeProvider', '_executeFormatRangeProvider', 'Execute range format provider.',
|
||||
[ApiCommandArgument.Uri, ApiCommandArgument.Range, new ApiCommandArgument('options', 'Formatting options', _ => true, v => v)],
|
||||
new ApiCommandResult<ISingleEditOperation[], types.TextEdit[] | undefined>('A promise that resolves to an array of TextEdits.', tryMapWith(typeConverters.TextEdit.to))
|
||||
),
|
||||
new ApiCommand(
|
||||
'vscode.executeFormatOnTypeProvider', '_executeFormatOnTypeProvider', 'Execute format on type provider.',
|
||||
[ApiCommandArgument.Uri, ApiCommandArgument.Position, new ApiCommandArgument('ch', 'Trigger character', v => typeof v === 'string', v => v), new ApiCommandArgument('options', 'Formatting options', _ => true, v => v)],
|
||||
new ApiCommandResult<ISingleEditOperation[], types.TextEdit[] | undefined>('A promise that resolves to an array of TextEdits.', tryMapWith(typeConverters.TextEdit.to))
|
||||
),
|
||||
// -- go to symbol (definition, type definition, declaration, impl, references)
|
||||
new ApiCommand(
|
||||
'vscode.executeDefinitionProvider', '_executeDefinitionProvider', 'Execute all definition provider.',
|
||||
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
|
||||
new ApiCommandResult<modes.Location[], types.Location[] | undefined>('A promise that resolves to an array of Location-instances.', tryMapWith(typeConverters.location.to))
|
||||
),
|
||||
new ApiCommand(
|
||||
'vscode.executeTypeDefinitionProvider', '_executeTypeDefinitionProvider', 'Execute all type definition providers.',
|
||||
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
|
||||
new ApiCommandResult<modes.Location[], types.Location[] | undefined>('A promise that resolves to an array of Location-instances.', tryMapWith(typeConverters.location.to))
|
||||
),
|
||||
new ApiCommand(
|
||||
'vscode.executeDeclarationProvider', '_executeDeclarationProvider', 'Execute all declaration providers.',
|
||||
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
|
||||
new ApiCommandResult<modes.Location[], types.Location[] | undefined>('A promise that resolves to an array of Location-instances.', tryMapWith(typeConverters.location.to))
|
||||
),
|
||||
new ApiCommand(
|
||||
'vscode.executeImplementationProvider', '_executeImplementationProvider', 'Execute all implementation providers.',
|
||||
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
|
||||
new ApiCommandResult<modes.Location[], types.Location[] | undefined>('A promise that resolves to an array of Location-instances.', tryMapWith(typeConverters.location.to))
|
||||
),
|
||||
new ApiCommand(
|
||||
'vscode.executeReferenceProvider', '_executeReferenceProvider', 'Execute all reference providers.',
|
||||
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
|
||||
new ApiCommandResult<modes.Location[], types.Location[] | undefined>('A promise that resolves to an array of Location-instances.', tryMapWith(typeConverters.location.to))
|
||||
),
|
||||
// -- hover
|
||||
new ApiCommand(
|
||||
'vscode.executeHoverProvider', '_executeHoverProvider', 'Execute all hover provider.',
|
||||
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
|
||||
new ApiCommandResult<modes.Hover[], types.Hover[] | undefined>('A promise that resolves to an array of Hover-instances.', tryMapWith(typeConverters.Hover.to))
|
||||
),
|
||||
// -- selection range
|
||||
new ApiCommand(
|
||||
'vscode.executeSelectionRangeProvider', '_executeSelectionRangeProvider', 'Execute selection range provider.',
|
||||
[ApiCommandArgument.Uri, new ApiCommandArgument('position', 'A positions in a text document', v => Array.isArray(v) && v.every(v => types.Position.isPosition(v)), v => v.map(typeConverters.Position.from))],
|
||||
new ApiCommandResult<IRange[][], types.SelectionRange[]>('A promise that resolves to an array of ranges.', result => {
|
||||
return result.map(ranges => {
|
||||
let node: types.SelectionRange | undefined;
|
||||
for (const range of ranges.reverse()) {
|
||||
node = new types.SelectionRange(typeConverters.Range.to(range), node);
|
||||
}
|
||||
return node!;
|
||||
});
|
||||
})
|
||||
),
|
||||
// -- symbol search
|
||||
new ApiCommand(
|
||||
'vscode.executeWorkspaceSymbolProvider', '_executeWorkspaceSymbolProvider', 'Execute all workspace symbol provider.',
|
||||
[new ApiCommandArgument('query', 'Search string', v => typeof v === 'string', v => v)],
|
||||
new ApiCommandResult<[search.IWorkspaceSymbolProvider, search.IWorkspaceSymbol[]][], types.SymbolInformation[]>('A promise that resolves to an array of SymbolInformation-instances.', value => {
|
||||
const result: types.SymbolInformation[] = [];
|
||||
if (Array.isArray(value)) {
|
||||
for (let tuple of value) {
|
||||
result.push(...tuple[1].map(typeConverters.WorkspaceSymbol.to));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
})
|
||||
),
|
||||
// --- call hierarchy
|
||||
new ApiCommand(
|
||||
'vscode.prepareCallHierarchy', '_executePrepareCallHierarchy', 'Prepare call hierarchy at a position inside a document',
|
||||
[ApiCommandArgument.Uri, ApiCommandArgument.Position],
|
||||
@@ -121,68 +239,6 @@ export class ExtHostApiCommands {
|
||||
}
|
||||
|
||||
registerCommands() {
|
||||
this._register('vscode.executeWorkspaceSymbolProvider', this._executeWorkspaceSymbolProvider, {
|
||||
description: 'Execute all workspace symbol provider.',
|
||||
args: [{ name: 'query', description: 'Search string', constraint: String }],
|
||||
returns: 'A promise that resolves to an array of SymbolInformation-instances.'
|
||||
|
||||
});
|
||||
this._register('vscode.executeDefinitionProvider', this._executeDefinitionProvider, {
|
||||
description: 'Execute all definition provider.',
|
||||
args: [
|
||||
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
|
||||
{ name: 'position', description: 'Position of a symbol', constraint: types.Position }
|
||||
],
|
||||
returns: 'A promise that resolves to an array of Location-instances.'
|
||||
});
|
||||
this._register('vscode.executeDeclarationProvider', this._executeDeclaraionProvider, {
|
||||
description: 'Execute all declaration provider.',
|
||||
args: [
|
||||
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
|
||||
{ name: 'position', description: 'Position of a symbol', constraint: types.Position }
|
||||
],
|
||||
returns: 'A promise that resolves to an array of Location-instances.'
|
||||
});
|
||||
this._register('vscode.executeTypeDefinitionProvider', this._executeTypeDefinitionProvider, {
|
||||
description: 'Execute all type definition providers.',
|
||||
args: [
|
||||
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
|
||||
{ name: 'position', description: 'Position of a symbol', constraint: types.Position }
|
||||
],
|
||||
returns: 'A promise that resolves to an array of Location-instances.'
|
||||
});
|
||||
this._register('vscode.executeImplementationProvider', this._executeImplementationProvider, {
|
||||
description: 'Execute all implementation providers.',
|
||||
args: [
|
||||
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
|
||||
{ name: 'position', description: 'Position of a symbol', constraint: types.Position }
|
||||
],
|
||||
returns: 'A promise that resolves to an array of Location-instance.'
|
||||
});
|
||||
this._register('vscode.executeHoverProvider', this._executeHoverProvider, {
|
||||
description: 'Execute all hover provider.',
|
||||
args: [
|
||||
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
|
||||
{ name: 'position', description: 'Position of a symbol', constraint: types.Position }
|
||||
],
|
||||
returns: 'A promise that resolves to an array of Hover-instances.'
|
||||
});
|
||||
this._register('vscode.executeDocumentHighlights', this._executeDocumentHighlights, {
|
||||
description: 'Execute document highlight provider.',
|
||||
args: [
|
||||
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
|
||||
{ name: 'position', description: 'Position in a text document', constraint: types.Position }
|
||||
],
|
||||
returns: 'A promise that resolves to an array of DocumentHighlight-instances.'
|
||||
});
|
||||
this._register('vscode.executeReferenceProvider', this._executeReferenceProvider, {
|
||||
description: 'Execute reference provider.',
|
||||
args: [
|
||||
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
|
||||
{ name: 'position', description: 'Position in a text document', constraint: types.Position }
|
||||
],
|
||||
returns: 'A promise that resolves to an array of Location-instances.'
|
||||
});
|
||||
this._register('vscode.executeDocumentRenameProvider', this._executeDocumentRenameProvider, {
|
||||
description: 'Execute rename provider.',
|
||||
args: [
|
||||
@@ -201,13 +257,6 @@ export class ExtHostApiCommands {
|
||||
],
|
||||
returns: 'A promise that resolves to SignatureHelp.'
|
||||
});
|
||||
this._register('vscode.executeDocumentSymbolProvider', this._executeDocumentSymbolProvider, {
|
||||
description: 'Execute document symbol provider.',
|
||||
args: [
|
||||
{ name: 'uri', description: 'Uri of a text document', constraint: URI }
|
||||
],
|
||||
returns: 'A promise that resolves to an array of SymbolInformation and DocumentSymbol instances.'
|
||||
});
|
||||
this._register('vscode.executeCompletionItemProvider', this._executeCompletionItemProvider, {
|
||||
description: 'Execute completion item provider.',
|
||||
args: [
|
||||
@@ -235,33 +284,7 @@ export class ExtHostApiCommands {
|
||||
],
|
||||
returns: 'A promise that resolves to an array of CodeLens-instances.'
|
||||
});
|
||||
this._register('vscode.executeFormatDocumentProvider', this._executeFormatDocumentProvider, {
|
||||
description: 'Execute document format provider.',
|
||||
args: [
|
||||
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
|
||||
{ name: 'options', description: 'Formatting options' }
|
||||
],
|
||||
returns: 'A promise that resolves to an array of TextEdits.'
|
||||
});
|
||||
this._register('vscode.executeFormatRangeProvider', this._executeFormatRangeProvider, {
|
||||
description: 'Execute range format provider.',
|
||||
args: [
|
||||
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
|
||||
{ name: 'range', description: 'Range in a text document', constraint: types.Range },
|
||||
{ name: 'options', description: 'Formatting options' }
|
||||
],
|
||||
returns: 'A promise that resolves to an array of TextEdits.'
|
||||
});
|
||||
this._register('vscode.executeFormatOnTypeProvider', this._executeFormatOnTypeProvider, {
|
||||
description: 'Execute document format provider.',
|
||||
args: [
|
||||
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
|
||||
{ name: 'position', description: 'Position in a text document', constraint: types.Position },
|
||||
{ name: 'ch', description: 'Character that got typed', constraint: String },
|
||||
{ name: 'options', description: 'Formatting options' }
|
||||
],
|
||||
returns: 'A promise that resolves to an array of TextEdits.'
|
||||
});
|
||||
|
||||
this._register('vscode.executeLinkProvider', this._executeDocumentLinkProvider, {
|
||||
description: 'Execute document link provider.',
|
||||
args: [
|
||||
@@ -284,14 +307,6 @@ export class ExtHostApiCommands {
|
||||
],
|
||||
returns: 'A promise that resolves to an array of ColorPresentation objects.'
|
||||
});
|
||||
this._register('vscode.executeSelectionRangeProvider', this._executeSelectionRangeProvider, {
|
||||
description: 'Execute selection range provider.',
|
||||
args: [
|
||||
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
|
||||
{ name: 'positions', description: 'Positions in a text document', constraint: Array.isArray }
|
||||
],
|
||||
returns: 'A promise that resolves to an array of ranges.'
|
||||
});
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// The following commands are registered on both sides separately.
|
||||
@@ -362,87 +377,6 @@ export class ExtHostApiCommands {
|
||||
this._disposables.add(disposable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute workspace symbol provider.
|
||||
*
|
||||
* @param query Search string to match query symbol names
|
||||
* @return A promise that resolves to an array of symbol information.
|
||||
*/
|
||||
private _executeWorkspaceSymbolProvider(query: string): Promise<types.SymbolInformation[]> {
|
||||
return this._commands.executeCommand<[search.IWorkspaceSymbolProvider, search.IWorkspaceSymbol[]][]>('_executeWorkspaceSymbolProvider', { query }).then(value => {
|
||||
const result: types.SymbolInformation[] = [];
|
||||
if (Array.isArray(value)) {
|
||||
for (let tuple of value) {
|
||||
result.push(...tuple[1].map(typeConverters.WorkspaceSymbol.to));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
private _executeDefinitionProvider(resource: URI, position: types.Position): Promise<types.Location[] | undefined> {
|
||||
const args = {
|
||||
resource,
|
||||
position: position && typeConverters.Position.from(position)
|
||||
};
|
||||
return this._commands.executeCommand<modes.Location[]>('_executeDefinitionProvider', args)
|
||||
.then(tryMapWith(typeConverters.location.to));
|
||||
}
|
||||
|
||||
private _executeDeclaraionProvider(resource: URI, position: types.Position): Promise<types.Location[] | undefined> {
|
||||
const args = {
|
||||
resource,
|
||||
position: position && typeConverters.Position.from(position)
|
||||
};
|
||||
return this._commands.executeCommand<modes.Location[]>('_executeDeclarationProvider', args)
|
||||
.then(tryMapWith(typeConverters.location.to));
|
||||
}
|
||||
|
||||
private _executeTypeDefinitionProvider(resource: URI, position: types.Position): Promise<types.Location[] | undefined> {
|
||||
const args = {
|
||||
resource,
|
||||
position: position && typeConverters.Position.from(position)
|
||||
};
|
||||
return this._commands.executeCommand<modes.Location[]>('_executeTypeDefinitionProvider', args)
|
||||
.then(tryMapWith(typeConverters.location.to));
|
||||
}
|
||||
|
||||
private _executeImplementationProvider(resource: URI, position: types.Position): Promise<types.Location[] | undefined> {
|
||||
const args = {
|
||||
resource,
|
||||
position: position && typeConverters.Position.from(position)
|
||||
};
|
||||
return this._commands.executeCommand<modes.Location[]>('_executeImplementationProvider', args)
|
||||
.then(tryMapWith(typeConverters.location.to));
|
||||
}
|
||||
|
||||
private _executeHoverProvider(resource: URI, position: types.Position): Promise<types.Hover[] | undefined> {
|
||||
const args = {
|
||||
resource,
|
||||
position: position && typeConverters.Position.from(position)
|
||||
};
|
||||
return this._commands.executeCommand<modes.Hover[]>('_executeHoverProvider', args)
|
||||
.then(tryMapWith(typeConverters.Hover.to));
|
||||
}
|
||||
|
||||
private _executeDocumentHighlights(resource: URI, position: types.Position): Promise<types.DocumentHighlight[] | undefined> {
|
||||
const args = {
|
||||
resource,
|
||||
position: position && typeConverters.Position.from(position)
|
||||
};
|
||||
return this._commands.executeCommand<modes.DocumentHighlight[]>('_executeDocumentHighlights', args)
|
||||
.then(tryMapWith(typeConverters.DocumentHighlight.to));
|
||||
}
|
||||
|
||||
private _executeReferenceProvider(resource: URI, position: types.Position): Promise<types.Location[] | undefined> {
|
||||
const args = {
|
||||
resource,
|
||||
position: position && typeConverters.Position.from(position)
|
||||
};
|
||||
return this._commands.executeCommand<modes.Location[]>('_executeReferenceProvider', args)
|
||||
.then(tryMapWith(typeConverters.location.to));
|
||||
}
|
||||
|
||||
private _executeDocumentRenameProvider(resource: URI, position: types.Position, newName: string): Promise<types.WorkspaceEdit> {
|
||||
const args = {
|
||||
resource,
|
||||
@@ -502,24 +436,6 @@ export class ExtHostApiCommands {
|
||||
});
|
||||
}
|
||||
|
||||
private _executeSelectionRangeProvider(resource: URI, positions: types.Position[]): Promise<vscode.SelectionRange[]> {
|
||||
const pos = positions.map(typeConverters.Position.from);
|
||||
const args = {
|
||||
resource,
|
||||
position: pos[0],
|
||||
positions: pos
|
||||
};
|
||||
return this._commands.executeCommand<IRange[][]>('_executeSelectionRangeProvider', args).then(result => {
|
||||
return result.map(ranges => {
|
||||
let node: types.SelectionRange | undefined;
|
||||
for (const range of ranges.reverse()) {
|
||||
node = new types.SelectionRange(typeConverters.Range.to(range), node);
|
||||
}
|
||||
return node!;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private _executeColorPresentationProvider(color: types.Color, context: { uri: URI, range: types.Range; }): Promise<types.ColorPresentation[]> {
|
||||
const args = {
|
||||
resource: context.uri,
|
||||
@@ -534,38 +450,6 @@ export class ExtHostApiCommands {
|
||||
});
|
||||
}
|
||||
|
||||
private _executeDocumentSymbolProvider(resource: URI): Promise<vscode.SymbolInformation[] | undefined> {
|
||||
const args = {
|
||||
resource
|
||||
};
|
||||
return this._commands.executeCommand<modes.DocumentSymbol[]>('_executeDocumentSymbolProvider', args).then((value): vscode.SymbolInformation[] | undefined => {
|
||||
if (isFalsyOrEmpty(value)) {
|
||||
return undefined;
|
||||
}
|
||||
class MergedInfo extends types.SymbolInformation implements vscode.DocumentSymbol {
|
||||
static to(symbol: modes.DocumentSymbol): MergedInfo {
|
||||
const res = new MergedInfo(
|
||||
symbol.name,
|
||||
typeConverters.SymbolKind.to(symbol.kind),
|
||||
symbol.containerName || '',
|
||||
new types.Location(resource, typeConverters.Range.to(symbol.range))
|
||||
);
|
||||
res.detail = symbol.detail;
|
||||
res.range = res.location.range;
|
||||
res.selectionRange = typeConverters.Range.to(symbol.selectionRange);
|
||||
res.children = symbol.children ? symbol.children.map(MergedInfo.to) : [];
|
||||
return res;
|
||||
}
|
||||
|
||||
detail!: string;
|
||||
range!: vscode.Range;
|
||||
selectionRange!: vscode.Range;
|
||||
children!: vscode.DocumentSymbol[];
|
||||
containerName!: string;
|
||||
}
|
||||
return value.map(MergedInfo.to);
|
||||
});
|
||||
}
|
||||
|
||||
private _executeCodeActionProvider(resource: URI, rangeOrSelection: types.Range | types.Selection, kind?: string): Promise<(vscode.CodeAction | vscode.Command | undefined)[] | undefined> {
|
||||
const args = {
|
||||
@@ -610,36 +494,6 @@ export class ExtHostApiCommands {
|
||||
|
||||
}
|
||||
|
||||
private _executeFormatDocumentProvider(resource: URI, options: vscode.FormattingOptions): Promise<vscode.TextEdit[] | undefined> {
|
||||
const args = {
|
||||
resource,
|
||||
options
|
||||
};
|
||||
return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatDocumentProvider', args)
|
||||
.then(tryMapWith(edit => new types.TextEdit(typeConverters.Range.to(edit.range), edit.text)));
|
||||
}
|
||||
|
||||
private _executeFormatRangeProvider(resource: URI, range: types.Range, options: vscode.FormattingOptions): Promise<vscode.TextEdit[] | undefined> {
|
||||
const args = {
|
||||
resource,
|
||||
range: typeConverters.Range.from(range),
|
||||
options
|
||||
};
|
||||
return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatRangeProvider', args)
|
||||
.then(tryMapWith(edit => new types.TextEdit(typeConverters.Range.to(edit.range), edit.text)));
|
||||
}
|
||||
|
||||
private _executeFormatOnTypeProvider(resource: URI, position: types.Position, ch: string, options: vscode.FormattingOptions): Promise<vscode.TextEdit[] | undefined> {
|
||||
const args = {
|
||||
resource,
|
||||
position: typeConverters.Position.from(position),
|
||||
ch,
|
||||
options
|
||||
};
|
||||
return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatOnTypeProvider', args)
|
||||
.then(tryMapWith(edit => new types.TextEdit(typeConverters.Range.to(edit.range), edit.text)));
|
||||
}
|
||||
|
||||
private _executeDocumentLinkProvider(resource: URI): Promise<vscode.DocumentLink[] | undefined> {
|
||||
return this._commands.executeCommand<modes.ILink[]>('_executeLinkProvider', resource)
|
||||
.then(tryMapWith(typeConverters.DocumentLink.to));
|
||||
|
||||
@@ -4,23 +4,23 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { mixin, deepClone } from 'vs/base/common/objects';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtHostWorkspace, IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { ExtHostConfigurationShape, MainThreadConfigurationShape, IWorkspaceConfigurationChangeEventData, IConfigurationInitData, MainContext } from './extHost.protocol';
|
||||
import { ExtHostConfigurationShape, MainThreadConfigurationShape, IConfigurationInitData, MainContext } from './extHost.protocol';
|
||||
import { ConfigurationTarget as ExtHostConfigurationTarget } from './extHostTypes';
|
||||
import { IConfigurationData, ConfigurationTarget, IConfigurationModel } from 'vs/platform/configuration/common/configuration';
|
||||
import { Configuration, ConfigurationChangeEvent, ConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
|
||||
import { WorkspaceConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels';
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { ConfigurationTarget, IConfigurationChange, IConfigurationData, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration';
|
||||
import { Configuration, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels';
|
||||
import { ConfigurationScope, OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { isObject } from 'vs/base/common/types';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { Barrier } from 'vs/base/common/async';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { Workspace } from 'vs/platform/workspace/common/workspace';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
|
||||
|
||||
function lookUp(tree: any, key: string) {
|
||||
if (key) {
|
||||
@@ -35,12 +35,57 @@ function lookUp(tree: any, key: string) {
|
||||
|
||||
type ConfigurationInspect<T> = {
|
||||
key: string;
|
||||
|
||||
defaultValue?: T;
|
||||
globalValue?: T;
|
||||
workspaceValue?: T;
|
||||
workspaceFolderValue?: T;
|
||||
workspaceValue?: T,
|
||||
workspaceFolderValue?: T,
|
||||
|
||||
defaultLanguageValue?: T;
|
||||
userLanguageValue?: T;
|
||||
workspaceLanguageValue?: T;
|
||||
workspaceFolderLanguageValue?: T;
|
||||
};
|
||||
|
||||
function isTextDocument(thing: any): thing is vscode.TextDocument {
|
||||
return thing
|
||||
&& thing.uri instanceof URI
|
||||
&& (!thing.languageId || typeof thing.languageId === 'string');
|
||||
}
|
||||
|
||||
function isWorkspaceFolder(thing: any): thing is vscode.WorkspaceFolder {
|
||||
return thing
|
||||
&& thing.uri instanceof URI
|
||||
&& (!thing.name || typeof thing.name === 'string')
|
||||
&& (!thing.index || typeof thing.index === 'number');
|
||||
}
|
||||
|
||||
function isUri(thing: any): thing is vscode.Uri {
|
||||
return thing instanceof URI;
|
||||
}
|
||||
|
||||
function isResourceLanguage(thing: any): thing is { resource: URI, languageId: string } {
|
||||
return thing
|
||||
&& thing.resource instanceof URI
|
||||
&& (!thing.languageId || typeof thing.languageId === 'string');
|
||||
}
|
||||
|
||||
function scopeToOverrides(scope: vscode.ConfigurationScope | undefined | null): IConfigurationOverrides | undefined {
|
||||
if (isUri(scope)) {
|
||||
return { resource: scope };
|
||||
}
|
||||
if (isWorkspaceFolder(scope)) {
|
||||
return { resource: scope.uri };
|
||||
}
|
||||
if (isTextDocument(scope)) {
|
||||
return { resource: scope.uri, overrideIdentifier: scope.languageId };
|
||||
}
|
||||
if (isResourceLanguage(scope)) {
|
||||
return scope;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export class ExtHostConfiguration implements ExtHostConfigurationShape {
|
||||
|
||||
readonly _serviceBrand: undefined;
|
||||
@@ -72,8 +117,8 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
|
||||
this._barrier.open();
|
||||
}
|
||||
|
||||
$acceptConfigurationChanged(data: IConfigurationInitData, eventData: IWorkspaceConfigurationChangeEventData): void {
|
||||
this.getConfigProvider().then(provider => provider.$acceptConfigurationChanged(data, eventData));
|
||||
$acceptConfigurationChanged(data: IConfigurationInitData, change: IConfigurationChange): void {
|
||||
this.getConfigProvider().then(provider => provider.$acceptConfigurationChanged(data, change));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +135,7 @@ export class ExtHostConfigProvider {
|
||||
this._proxy = proxy;
|
||||
this._logService = logService;
|
||||
this._extHostWorkspace = extHostWorkspace;
|
||||
this._configuration = ExtHostConfigProvider.parse(data);
|
||||
this._configuration = Configuration.parse(data);
|
||||
this._configurationScopes = this._toMap(data.configurationScopes);
|
||||
}
|
||||
|
||||
@@ -98,19 +143,24 @@ export class ExtHostConfigProvider {
|
||||
return this._onDidChangeConfiguration && this._onDidChangeConfiguration.event;
|
||||
}
|
||||
|
||||
$acceptConfigurationChanged(data: IConfigurationInitData, eventData: IWorkspaceConfigurationChangeEventData) {
|
||||
this._configuration = ExtHostConfigProvider.parse(data);
|
||||
$acceptConfigurationChanged(data: IConfigurationInitData, change: IConfigurationChange) {
|
||||
const previous = { data: this._configuration.toData(), workspace: this._extHostWorkspace.workspace };
|
||||
this._configuration = Configuration.parse(data);
|
||||
this._configurationScopes = this._toMap(data.configurationScopes);
|
||||
this._onDidChangeConfiguration.fire(this._toConfigurationChangeEvent(eventData));
|
||||
this._onDidChangeConfiguration.fire(this._toConfigurationChangeEvent(change, previous));
|
||||
}
|
||||
|
||||
getConfiguration(section?: string, resource?: URI, extensionId?: ExtensionIdentifier): vscode.WorkspaceConfiguration {
|
||||
getConfiguration(section?: string, scope?: vscode.ConfigurationScope | null, extensionDescription?: IExtensionDescription): vscode.WorkspaceConfiguration {
|
||||
const overrides = scopeToOverrides(scope) || {};
|
||||
if (overrides.overrideIdentifier && extensionDescription) {
|
||||
checkProposedApiEnabled(extensionDescription);
|
||||
}
|
||||
const config = this._toReadonlyValue(section
|
||||
? lookUp(this._configuration.getValue(undefined, { resource }, this._extHostWorkspace.workspace), section)
|
||||
: this._configuration.getValue(undefined, { resource }, this._extHostWorkspace.workspace));
|
||||
? lookUp(this._configuration.getValue(undefined, overrides, this._extHostWorkspace.workspace), section)
|
||||
: this._configuration.getValue(undefined, overrides, this._extHostWorkspace.workspace));
|
||||
|
||||
if (section) {
|
||||
this._validateConfigurationAccess(section, resource, extensionId);
|
||||
this._validateConfigurationAccess(section, overrides, extensionDescription?.identifier);
|
||||
}
|
||||
|
||||
function parseConfigurationTarget(arg: boolean | ExtHostConfigurationTarget): ConfigurationTarget | null {
|
||||
@@ -133,7 +183,7 @@ export class ExtHostConfigProvider {
|
||||
return typeof lookUp(config, key) !== 'undefined';
|
||||
},
|
||||
get: <T>(key: string, defaultValue?: T) => {
|
||||
this._validateConfigurationAccess(section ? `${section}.${key}` : key, resource, extensionId);
|
||||
this._validateConfigurationAccess(section ? `${section}.${key}` : key, overrides, extensionDescription?.identifier);
|
||||
let result = lookUp(config, key);
|
||||
if (typeof result === 'undefined') {
|
||||
result = defaultValue;
|
||||
@@ -189,25 +239,31 @@ export class ExtHostConfigProvider {
|
||||
}
|
||||
return result;
|
||||
},
|
||||
update: (key: string, value: any, arg: ExtHostConfigurationTarget | boolean) => {
|
||||
update: (key: string, value: any, extHostConfigurationTarget: ExtHostConfigurationTarget | boolean, scopeToLanguage?: boolean) => {
|
||||
key = section ? `${section}.${key}` : key;
|
||||
const target = parseConfigurationTarget(arg);
|
||||
const target = parseConfigurationTarget(extHostConfigurationTarget);
|
||||
if (value !== undefined) {
|
||||
return this._proxy.$updateConfigurationOption(target, key, value, resource);
|
||||
return this._proxy.$updateConfigurationOption(target, key, value, overrides, scopeToLanguage);
|
||||
} else {
|
||||
return this._proxy.$removeConfigurationOption(target, key, resource);
|
||||
return this._proxy.$removeConfigurationOption(target, key, overrides, scopeToLanguage);
|
||||
}
|
||||
},
|
||||
inspect: <T>(key: string): ConfigurationInspect<T> | undefined => {
|
||||
key = section ? `${section}.${key}` : key;
|
||||
const config = deepClone(this._configuration.inspect<T>(key, { resource }, this._extHostWorkspace.workspace));
|
||||
const config = deepClone(this._configuration.inspect<T>(key, overrides, this._extHostWorkspace.workspace));
|
||||
if (config) {
|
||||
return {
|
||||
key,
|
||||
defaultValue: config.default,
|
||||
globalValue: config.user,
|
||||
workspaceValue: config.workspace,
|
||||
workspaceFolderValue: config.workspaceFolder
|
||||
|
||||
defaultValue: config.defaultValue,
|
||||
globalValue: config.userValue,
|
||||
workspaceValue: config.workspaceValue,
|
||||
workspaceFolderValue: config.workspaceFolderValue,
|
||||
|
||||
defaultLanguageValue: config.default?.override,
|
||||
userLanguageValue: config.user?.override,
|
||||
workspaceLanguageValue: config.workspace?.override,
|
||||
workspaceFolderLanguageValue: config.workspaceFolder?.override,
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
@@ -237,34 +293,27 @@ export class ExtHostConfigProvider {
|
||||
return readonlyProxy(result);
|
||||
}
|
||||
|
||||
private _validateConfigurationAccess(key: string, resource: URI | undefined, extensionId?: ExtensionIdentifier): void {
|
||||
private _validateConfigurationAccess(key: string, overrides?: IConfigurationOverrides, extensionId?: ExtensionIdentifier): void {
|
||||
const scope = OVERRIDE_PROPERTY_PATTERN.test(key) ? ConfigurationScope.RESOURCE : this._configurationScopes.get(key);
|
||||
const extensionIdText = extensionId ? `[${extensionId.value}] ` : '';
|
||||
if (ConfigurationScope.RESOURCE === scope) {
|
||||
if (resource === undefined) {
|
||||
if (overrides?.resource) {
|
||||
this._logService.warn(`${extensionIdText}Accessing a resource scoped configuration without providing a resource is not expected. To get the effective value for '${key}', provide the URI of a resource or 'null' for any resource.`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (ConfigurationScope.WINDOW === scope) {
|
||||
if (resource) {
|
||||
if (overrides?.resource) {
|
||||
this._logService.warn(`${extensionIdText}Accessing a window scoped configuration for a resource is not expected. To associate '${key}' to a resource, define its scope to 'resource' in configuration contributions in 'package.json'.`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private _toConfigurationChangeEvent(data: IWorkspaceConfigurationChangeEventData): vscode.ConfigurationChangeEvent {
|
||||
const changedConfiguration = new ConfigurationModel(data.changedConfiguration.contents, data.changedConfiguration.keys, data.changedConfiguration.overrides);
|
||||
const changedConfigurationByResource: ResourceMap<ConfigurationModel> = new ResourceMap<ConfigurationModel>();
|
||||
for (const key of Object.keys(data.changedConfigurationByResource)) {
|
||||
const resource = URI.parse(key);
|
||||
const model = data.changedConfigurationByResource[key];
|
||||
changedConfigurationByResource.set(resource, new ConfigurationModel(model.contents, model.keys, model.overrides));
|
||||
}
|
||||
const event = new WorkspaceConfigurationChangeEvent(new ConfigurationChangeEvent(changedConfiguration, changedConfigurationByResource), this._extHostWorkspace.workspace);
|
||||
private _toConfigurationChangeEvent(change: IConfigurationChange, previous: { data: IConfigurationData, workspace: Workspace | undefined }): vscode.ConfigurationChangeEvent {
|
||||
const event = new ConfigurationChangeEvent(change, previous, this._configuration, this._extHostWorkspace.workspace);
|
||||
return Object.freeze({
|
||||
affectsConfiguration: (section: string, resource?: URI) => event.affectsConfiguration(section, resource)
|
||||
affectsConfiguration: (section: string, scope?: vscode.ConfigurationScope) => event.affectsConfiguration(section, scopeToOverrides(scope))
|
||||
});
|
||||
}
|
||||
|
||||
@@ -272,20 +321,6 @@ export class ExtHostConfigProvider {
|
||||
return scopes.reduce((result, scope) => { result.set(scope[0], scope[1]); return result; }, new Map<string, ConfigurationScope | undefined>());
|
||||
}
|
||||
|
||||
private static parse(data: IConfigurationData): Configuration {
|
||||
const defaultConfiguration = ExtHostConfigProvider.parseConfigurationModel(data.defaults);
|
||||
const userConfiguration = ExtHostConfigProvider.parseConfigurationModel(data.user);
|
||||
const workspaceConfiguration = ExtHostConfigProvider.parseConfigurationModel(data.workspace);
|
||||
const folders: ResourceMap<ConfigurationModel> = data.folders.reduce((result, value) => {
|
||||
result.set(URI.revive(value[0]), ExtHostConfigProvider.parseConfigurationModel(value[1]));
|
||||
return result;
|
||||
}, new ResourceMap<ConfigurationModel>());
|
||||
return new Configuration(defaultConfiguration, userConfiguration, new ConfigurationModel(), workspaceConfiguration, folders, new ConfigurationModel(), new ResourceMap<ConfigurationModel>(), false);
|
||||
}
|
||||
|
||||
private static parseConfigurationModel(model: IConfigurationModel): ConfigurationModel {
|
||||
return new ConfigurationModel(model.contents, model.keys, model.overrides).freeze();
|
||||
}
|
||||
}
|
||||
|
||||
export const IExtHostConfiguration = createDecorator<IExtHostConfiguration>('IExtHostConfiguration');
|
||||
|
||||
@@ -825,7 +825,7 @@ export class ExtHostDebugServiceBase implements IExtHostDebugService, ExtHostDeb
|
||||
if (aex) {
|
||||
const folder = session.workspaceFolder;
|
||||
const rootFolder = folder ? folder.uri.toString() : undefined;
|
||||
return this._commandService.executeCommand(aex, rootFolder).then((ae: { command: string, args: string[] }) => {
|
||||
return this._commandService.executeCommand(aex, rootFolder).then((ae: any) => {
|
||||
return new DebugAdapterExecutable(ae.command, ae.args || []);
|
||||
});
|
||||
}
|
||||
@@ -1049,9 +1049,9 @@ class DirectDebugAdapter extends AbstractDebugAdapter {
|
||||
constructor(private implementation: vscode.DebugAdapter) {
|
||||
super();
|
||||
|
||||
if (this.implementation.onSendMessage) {
|
||||
implementation.onSendMessage((message: DebugProtocol.ProtocolMessage) => {
|
||||
this.acceptMessage(message);
|
||||
if (this.implementation.onDidSendMessage) {
|
||||
implementation.onDidSendMessage((message: vscode.DebugProtocolMessage) => {
|
||||
this.acceptMessage(message as DebugProtocol.ProtocolMessage);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import { ExtHostDocumentData } from 'vs/workbench/api/common/extHostDocumentData
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { ExtHostTextEditor } from 'vs/workbench/api/common/extHostTextEditor';
|
||||
import * as typeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
||||
export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsShape {
|
||||
|
||||
@@ -35,6 +36,7 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
|
||||
|
||||
constructor(
|
||||
@IExtHostRpcService private readonly _extHostRpc: IExtHostRpcService,
|
||||
@ILogService private readonly _logService: ILogService
|
||||
) { }
|
||||
|
||||
$acceptDocumentsAndEditorsDelta(delta: IDocumentsAndEditorsDelta): void {
|
||||
@@ -92,8 +94,9 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
|
||||
|
||||
const documentData = this._documents.get(resource.toString())!;
|
||||
const editor = new ExtHostTextEditor(
|
||||
this._extHostRpc.getProxy(MainContext.MainThreadTextEditors),
|
||||
data.id,
|
||||
this._extHostRpc.getProxy(MainContext.MainThreadTextEditors),
|
||||
this._logService,
|
||||
documentData,
|
||||
data.selections.map(typeConverters.Selection.to),
|
||||
data.options,
|
||||
|
||||
@@ -32,6 +32,7 @@ import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitData
|
||||
import { IExtensionStoragePaths } from 'vs/workbench/api/common/extHostStoragePaths';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { IExtHostTunnelService } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
|
||||
interface ITestRunner {
|
||||
/** Old test runner API, as exported from `vscode/lib/testrunner` */
|
||||
@@ -76,6 +77,7 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
|
||||
protected readonly _extHostWorkspace: ExtHostWorkspace;
|
||||
protected readonly _extHostConfiguration: ExtHostConfiguration;
|
||||
protected readonly _logService: ILogService;
|
||||
protected readonly _extHostTunnelService: IExtHostTunnelService;
|
||||
|
||||
protected readonly _mainThreadWorkspaceProxy: MainThreadWorkspaceShape;
|
||||
protected readonly _mainThreadTelemetryProxy: MainThreadTelemetryShape;
|
||||
@@ -104,7 +106,8 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
|
||||
@IExtHostConfiguration extHostConfiguration: IExtHostConfiguration,
|
||||
@ILogService logService: ILogService,
|
||||
@IExtHostInitDataService initData: IExtHostInitDataService,
|
||||
@IExtensionStoragePaths storagePath: IExtensionStoragePaths
|
||||
@IExtensionStoragePaths storagePath: IExtensionStoragePaths,
|
||||
@IExtHostTunnelService extHostTunnelService: IExtHostTunnelService
|
||||
) {
|
||||
this._hostUtils = hostUtils;
|
||||
this._extHostContext = extHostContext;
|
||||
@@ -113,6 +116,7 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
|
||||
this._extHostWorkspace = extHostWorkspace;
|
||||
this._extHostConfiguration = extHostConfiguration;
|
||||
this._logService = logService;
|
||||
this._extHostTunnelService = extHostTunnelService;
|
||||
this._disposables = new DisposableStore();
|
||||
|
||||
this._mainThreadWorkspaceProxy = this._extHostContext.getProxy(MainContext.MainThreadWorkspace);
|
||||
@@ -641,6 +645,7 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
|
||||
|
||||
try {
|
||||
const result = await resolver.resolve(remoteAuthority, { resolveAttempt });
|
||||
this._disposables.add(await this._extHostTunnelService.setForwardPortProvider(resolver));
|
||||
|
||||
// Split merged API result into separate authority/options
|
||||
const authority: ResolvedAuthority = {
|
||||
@@ -656,7 +661,8 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
|
||||
type: 'ok',
|
||||
value: {
|
||||
authority,
|
||||
options
|
||||
options,
|
||||
tunnelInformation: { environmentTunnels: result.environmentTunnels }
|
||||
}
|
||||
};
|
||||
} catch (err) {
|
||||
|
||||
@@ -389,7 +389,7 @@ class CodeActionAdapter {
|
||||
edit: candidate.edit && typeConvert.WorkspaceEdit.from(candidate.edit),
|
||||
kind: candidate.kind && candidate.kind.value,
|
||||
isPreferred: candidate.isPreferred,
|
||||
disabled: candidate.disabled
|
||||
disabled: candidate.disabled?.reason
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -740,11 +740,16 @@ class SuggestAdapter {
|
||||
private _cache = new Cache<vscode.CompletionItem>('CompletionItem');
|
||||
private _disposables = new Map<number, DisposableStore>();
|
||||
|
||||
private _didWarnMust: boolean = false;
|
||||
private _didWarnShould: boolean = false;
|
||||
|
||||
constructor(
|
||||
private readonly _documents: ExtHostDocuments,
|
||||
private readonly _commands: CommandsConverter,
|
||||
private readonly _provider: vscode.CompletionItemProvider,
|
||||
private readonly _logService: ILogService
|
||||
private readonly _logService: ILogService,
|
||||
private readonly _telemetry: extHostProtocol.MainThreadTelemetryShape,
|
||||
private readonly _extensionId: ExtensionIdentifier
|
||||
) { }
|
||||
|
||||
provideCompletionItems(resource: URI, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise<extHostProtocol.ISuggestResultDto | undefined> {
|
||||
@@ -809,12 +814,37 @@ class SuggestAdapter {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
const _mustNotChange = SuggestAdapter._mustNotChangeHash(item);
|
||||
const _mayNotChange = SuggestAdapter._mayNotChangeHash(item);
|
||||
|
||||
return asPromise(() => this._provider.resolveCompletionItem!(item, token)).then(resolvedItem => {
|
||||
|
||||
if (!resolvedItem) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
type BlameExtension = {
|
||||
extensionId: string;
|
||||
kind: string
|
||||
};
|
||||
|
||||
type BlameExtensionMeta = {
|
||||
extensionId: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' };
|
||||
kind: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' };
|
||||
};
|
||||
|
||||
if (!this._didWarnMust && _mustNotChange !== SuggestAdapter._mustNotChangeHash(resolvedItem)) {
|
||||
this._logService.warn(`[${this._extensionId.value}] INVALID result from 'resolveCompletionItem', extension MUST NOT change any of: label, sortText, filterText, insertText, or textEdit`);
|
||||
this._telemetry.$publicLog2<BlameExtension, BlameExtensionMeta>('resolveCompletionItem/invalid', { extensionId: this._extensionId.value, kind: 'must' });
|
||||
this._didWarnMust = true;
|
||||
}
|
||||
|
||||
if (!this._didWarnShould && _mayNotChange !== SuggestAdapter._mayNotChangeHash(resolvedItem)) {
|
||||
this._logService.info(`[${this._extensionId.value}] UNSAVE result from 'resolveCompletionItem', extension SHOULD NOT change any of: additionalTextEdits, or command`);
|
||||
this._telemetry.$publicLog2<BlameExtension, BlameExtensionMeta>('resolveCompletionItem/invalid', { extensionId: this._extensionId.value, kind: 'should' });
|
||||
this._didWarnShould = true;
|
||||
}
|
||||
|
||||
const pos = typeConvert.Position.to(position);
|
||||
return this._convertCompletionItem(resolvedItem, pos, id);
|
||||
});
|
||||
@@ -908,6 +938,16 @@ class SuggestAdapter {
|
||||
private static _isValidRangeForCompletion(range: vscode.Range, position: vscode.Position): boolean {
|
||||
return range.isSingleLine || range.start.line === position.line;
|
||||
}
|
||||
|
||||
private static _mustNotChangeHash(item: vscode.CompletionItem) {
|
||||
const args = [item.label, item.sortText, item.filterText, item.insertText, item.range, item.range2];
|
||||
const res = JSON.stringify(args);
|
||||
return res;
|
||||
}
|
||||
|
||||
private static _mayNotChangeHash(item: vscode.CompletionItem) {
|
||||
return JSON.stringify([item.additionalTextEdits, item.command]);
|
||||
}
|
||||
}
|
||||
|
||||
class SignatureHelpAdapter {
|
||||
@@ -1160,18 +1200,23 @@ class CallHierarchyAdapter {
|
||||
private readonly _provider: vscode.CallHierarchyProvider
|
||||
) { }
|
||||
|
||||
async prepareSession(uri: URI, position: IPosition, token: CancellationToken): Promise<extHostProtocol.ICallHierarchyItemDto | undefined> {
|
||||
async prepareSession(uri: URI, position: IPosition, token: CancellationToken): Promise<extHostProtocol.ICallHierarchyItemDto[] | undefined> {
|
||||
const doc = this._documents.getDocument(uri);
|
||||
const pos = typeConvert.Position.to(position);
|
||||
|
||||
const item = await this._provider.prepareCallHierarchy(doc, pos, token);
|
||||
if (!item) {
|
||||
const items = await this._provider.prepareCallHierarchy(doc, pos, token);
|
||||
if (!items) {
|
||||
return undefined;
|
||||
}
|
||||
const sessionId = this._idPool.nextId();
|
||||
|
||||
const sessionId = this._idPool.nextId();
|
||||
this._cache.set(sessionId, new Map());
|
||||
return this._cacheAndConvertItem(sessionId, item);
|
||||
|
||||
if (Array.isArray(items)) {
|
||||
return items.map(item => this._cacheAndConvertItem(sessionId, item));
|
||||
} else {
|
||||
return [this._cacheAndConvertItem(sessionId, items)];
|
||||
}
|
||||
}
|
||||
|
||||
async provideCallsTo(sessionId: string, itemId: string, token: CancellationToken): Promise<extHostProtocol.IIncomingCallDto[] | undefined> {
|
||||
@@ -1209,11 +1254,10 @@ class CallHierarchyAdapter {
|
||||
}
|
||||
|
||||
releaseSession(sessionId: string): void {
|
||||
this._cache.delete(sessionId.charAt(0));
|
||||
this._cache.delete(sessionId);
|
||||
}
|
||||
|
||||
private _cacheAndConvertItem(itemOrSessionId: string, item: vscode.CallHierarchyItem): extHostProtocol.ICallHierarchyItemDto {
|
||||
const sessionId = itemOrSessionId.charAt(0);
|
||||
private _cacheAndConvertItem(sessionId: string, item: vscode.CallHierarchyItem): extHostProtocol.ICallHierarchyItemDto {
|
||||
const map = this._cache.get(sessionId)!;
|
||||
const dto: extHostProtocol.ICallHierarchyItemDto = {
|
||||
_sessionId: sessionId,
|
||||
@@ -1231,7 +1275,7 @@ class CallHierarchyAdapter {
|
||||
|
||||
private _itemFromCache(sessionId: string, itemId: string): vscode.CallHierarchyItem | undefined {
|
||||
const map = this._cache.get(sessionId);
|
||||
return map && map.get(itemId);
|
||||
return map?.get(itemId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1254,7 +1298,8 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
|
||||
private static _handlePool: number = 0;
|
||||
|
||||
private readonly _uriTransformer: IURITransformer | null;
|
||||
private _proxy: extHostProtocol.MainThreadLanguageFeaturesShape;
|
||||
private readonly _proxy: extHostProtocol.MainThreadLanguageFeaturesShape;
|
||||
private readonly _telemetryShape: extHostProtocol.MainThreadTelemetryShape;
|
||||
private _documents: ExtHostDocuments;
|
||||
private _commands: ExtHostCommands;
|
||||
private _diagnostics: ExtHostDiagnostics;
|
||||
@@ -1271,6 +1316,7 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
|
||||
) {
|
||||
this._uriTransformer = uriTransformer;
|
||||
this._proxy = mainContext.getProxy(extHostProtocol.MainContext.MainThreadLanguageFeatures);
|
||||
this._telemetryShape = mainContext.getProxy(extHostProtocol.MainContext.MainThreadTelemetry);
|
||||
this._documents = documents;
|
||||
this._commands = commands;
|
||||
this._diagnostics = diagnostics;
|
||||
@@ -1585,7 +1631,7 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
|
||||
// --- suggestion
|
||||
|
||||
registerCompletionItemProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new SuggestAdapter(this._documents, this._commands.converter, provider, this._logService), extension);
|
||||
const handle = this._addNewAdapter(new SuggestAdapter(this._documents, this._commands.converter, provider, this._logService, this._telemetryShape, extension.identifier), extension);
|
||||
this._proxy.$registerSuggestSupport(handle, this._transformDocumentSelector(selector), triggerCharacters, SuggestAdapter.supportsResolving(provider), extension.identifier);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
@@ -1686,7 +1732,7 @@ export class ExtHostLanguageFeatures implements extHostProtocol.ExtHostLanguageF
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$prepareCallHierarchy(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<extHostProtocol.ICallHierarchyItemDto | undefined> {
|
||||
$prepareCallHierarchy(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<extHostProtocol.ICallHierarchyItemDto[] | undefined> {
|
||||
return this._withAdapter(handle, CallHierarchyAdapter, adapter => Promise.resolve(adapter.prepareSession(URI.revive(resource), position, token)), undefined);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import { ProgressLocation } from './extHostTypeConverters';
|
||||
import { Progress, IProgressStep } from 'vs/platform/progress/common/progress';
|
||||
import { localize } from 'vs/nls';
|
||||
import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { debounce } from 'vs/base/common/decorators';
|
||||
import { throttle } from 'vs/base/common/decorators';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
|
||||
export class ExtHostProgress implements ExtHostProgressShape {
|
||||
@@ -85,7 +85,7 @@ class ProgressCallback extends Progress<IProgressStep> {
|
||||
super(p => this.throttledReport(p));
|
||||
}
|
||||
|
||||
@debounce(100, (result: IProgressStep, currentValue: IProgressStep) => mergeProgress(result, currentValue), () => Object.create(null))
|
||||
@throttle(100, (result: IProgressStep, currentValue: IProgressStep) => mergeProgress(result, currentValue), () => Object.create(null))
|
||||
throttledReport(p: IProgressStep): void {
|
||||
this._proxy.$progressReport(this._handle, p);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import { ExtHostDocumentData } from 'vs/workbench/api/common/extHostDocumentData
|
||||
import * as TypeConverters from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { EndOfLine, Position, Range, Selection, SnippetString, TextEditorLineNumbersStyle, TextEditorRevealType } from 'vs/workbench/api/common/extHostTypes';
|
||||
import * as vscode from 'vscode';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
||||
export class TextEditorDecorationType implements vscode.TextEditorDecorationType {
|
||||
|
||||
@@ -133,23 +134,11 @@ export class TextEditorEdit {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function deprecated(name: string, message: string = 'Refer to the documentation for further details.') {
|
||||
return (target: Object, key: string, descriptor: TypedPropertyDescriptor<any>) => {
|
||||
const originalMethod = descriptor.value;
|
||||
descriptor.value = function (...args: any[]) {
|
||||
console.warn(`[Deprecation Warning] method '${name}' is deprecated and should no longer be used. ${message}`);
|
||||
return originalMethod.apply(this, args);
|
||||
};
|
||||
|
||||
return descriptor;
|
||||
};
|
||||
}
|
||||
|
||||
export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
|
||||
|
||||
private _proxy: MainThreadTextEditorsShape;
|
||||
private _id: string;
|
||||
private _logService: ILogService;
|
||||
|
||||
private _tabSize!: number;
|
||||
private _indentSize!: number;
|
||||
@@ -157,10 +146,11 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
|
||||
private _cursorStyle!: TextEditorCursorStyle;
|
||||
private _lineNumbers!: TextEditorLineNumbersStyle;
|
||||
|
||||
constructor(proxy: MainThreadTextEditorsShape, id: string, source: IResolvedTextEditorConfiguration) {
|
||||
constructor(proxy: MainThreadTextEditorsShape, id: string, source: IResolvedTextEditorConfiguration, logService: ILogService) {
|
||||
this._proxy = proxy;
|
||||
this._id = id;
|
||||
this._accept(source);
|
||||
this._logService = logService;
|
||||
}
|
||||
|
||||
public _accept(source: IResolvedTextEditorConfiguration): void {
|
||||
@@ -207,7 +197,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
|
||||
// reflect the new tabSize value immediately
|
||||
this._tabSize = tabSize;
|
||||
}
|
||||
warnOnError(this._proxy.$trySetOptions(this._id, {
|
||||
this._warnOnError(this._proxy.$trySetOptions(this._id, {
|
||||
tabSize: tabSize
|
||||
}));
|
||||
}
|
||||
@@ -248,7 +238,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
|
||||
// reflect the new indentSize value immediately
|
||||
this._indentSize = indentSize;
|
||||
}
|
||||
warnOnError(this._proxy.$trySetOptions(this._id, {
|
||||
this._warnOnError(this._proxy.$trySetOptions(this._id, {
|
||||
indentSize: indentSize
|
||||
}));
|
||||
}
|
||||
@@ -274,7 +264,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
|
||||
// reflect the new insertSpaces value immediately
|
||||
this._insertSpaces = insertSpaces;
|
||||
}
|
||||
warnOnError(this._proxy.$trySetOptions(this._id, {
|
||||
this._warnOnError(this._proxy.$trySetOptions(this._id, {
|
||||
insertSpaces: insertSpaces
|
||||
}));
|
||||
}
|
||||
@@ -289,7 +279,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
|
||||
return;
|
||||
}
|
||||
this._cursorStyle = value;
|
||||
warnOnError(this._proxy.$trySetOptions(this._id, {
|
||||
this._warnOnError(this._proxy.$trySetOptions(this._id, {
|
||||
cursorStyle: value
|
||||
}));
|
||||
}
|
||||
@@ -304,7 +294,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
|
||||
return;
|
||||
}
|
||||
this._lineNumbers = value;
|
||||
warnOnError(this._proxy.$trySetOptions(this._id, {
|
||||
this._warnOnError(this._proxy.$trySetOptions(this._id, {
|
||||
lineNumbers: TypeConverters.TextEditorLineNumbersStyle.from(value)
|
||||
}));
|
||||
}
|
||||
@@ -369,15 +359,17 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
|
||||
}
|
||||
|
||||
if (hasUpdate) {
|
||||
warnOnError(this._proxy.$trySetOptions(this._id, bulkConfigurationUpdate));
|
||||
this._warnOnError(this._proxy.$trySetOptions(this._id, bulkConfigurationUpdate));
|
||||
}
|
||||
}
|
||||
|
||||
private _warnOnError(promise: Promise<any>): void {
|
||||
promise.catch(err => this._logService.warn(err));
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostTextEditor implements vscode.TextEditor {
|
||||
|
||||
private readonly _proxy: MainThreadTextEditorsShape;
|
||||
private readonly _id: string;
|
||||
private readonly _documentData: ExtHostDocumentData;
|
||||
|
||||
private _selections: Selection[];
|
||||
@@ -387,18 +379,17 @@ export class ExtHostTextEditor implements vscode.TextEditor {
|
||||
private _disposed: boolean = false;
|
||||
private _hasDecorationsForKey: { [key: string]: boolean; };
|
||||
|
||||
get id(): string { return this._id; }
|
||||
|
||||
constructor(
|
||||
proxy: MainThreadTextEditorsShape, id: string, document: ExtHostDocumentData,
|
||||
readonly id: string,
|
||||
private readonly _proxy: MainThreadTextEditorsShape,
|
||||
private readonly _logService: ILogService,
|
||||
document: ExtHostDocumentData,
|
||||
selections: Selection[], options: IResolvedTextEditorConfiguration,
|
||||
visibleRanges: Range[], viewColumn: vscode.ViewColumn | undefined
|
||||
) {
|
||||
this._proxy = proxy;
|
||||
this._id = id;
|
||||
this._documentData = document;
|
||||
this._selections = selections;
|
||||
this._options = new ExtHostTextEditorOptions(this._proxy, this._id, options);
|
||||
this._options = new ExtHostTextEditorOptions(this._proxy, this.id, options, _logService);
|
||||
this._visibleRanges = visibleRanges;
|
||||
this._viewColumn = viewColumn;
|
||||
this._hasDecorationsForKey = Object.create(null);
|
||||
@@ -409,12 +400,12 @@ export class ExtHostTextEditor implements vscode.TextEditor {
|
||||
this._disposed = true;
|
||||
}
|
||||
|
||||
@deprecated('TextEditor.show') show(column: vscode.ViewColumn) {
|
||||
this._proxy.$tryShowEditor(this._id, TypeConverters.ViewColumn.from(column));
|
||||
show(column: vscode.ViewColumn) {
|
||||
this._proxy.$tryShowEditor(this.id, TypeConverters.ViewColumn.from(column));
|
||||
}
|
||||
|
||||
@deprecated('TextEditor.hide') hide() {
|
||||
this._proxy.$tryHideEditor(this._id);
|
||||
hide() {
|
||||
this._proxy.$tryHideEditor(this.id);
|
||||
}
|
||||
|
||||
// ---- the document
|
||||
@@ -515,7 +506,7 @@ export class ExtHostTextEditor implements vscode.TextEditor {
|
||||
() => {
|
||||
if (TypeConverters.isDecorationOptionsArr(ranges)) {
|
||||
return this._proxy.$trySetDecorations(
|
||||
this._id,
|
||||
this.id,
|
||||
decorationType.key,
|
||||
TypeConverters.fromRangeOrRangeWithMessage(ranges)
|
||||
);
|
||||
@@ -529,7 +520,7 @@ export class ExtHostTextEditor implements vscode.TextEditor {
|
||||
_ranges[4 * i + 3] = range.end.character + 1;
|
||||
}
|
||||
return this._proxy.$trySetDecorationsFast(
|
||||
this._id,
|
||||
this.id,
|
||||
decorationType.key,
|
||||
_ranges
|
||||
);
|
||||
@@ -541,7 +532,7 @@ export class ExtHostTextEditor implements vscode.TextEditor {
|
||||
revealRange(range: Range, revealType: vscode.TextEditorRevealType): void {
|
||||
this._runOnProxy(
|
||||
() => this._proxy.$tryRevealRange(
|
||||
this._id,
|
||||
this.id,
|
||||
TypeConverters.Range.from(range),
|
||||
(revealType || TextEditorRevealType.Default)
|
||||
)
|
||||
@@ -550,7 +541,7 @@ export class ExtHostTextEditor implements vscode.TextEditor {
|
||||
|
||||
private _trySetSelection(): Promise<vscode.TextEditor | null | undefined> {
|
||||
const selection = this._selections.map(TypeConverters.Selection.from);
|
||||
return this._runOnProxy(() => this._proxy.$trySetSelections(this._id, selection));
|
||||
return this._runOnProxy(() => this._proxy.$trySetSelections(this.id, selection));
|
||||
}
|
||||
|
||||
_acceptSelections(selections: Selection[]): void {
|
||||
@@ -616,7 +607,7 @@ export class ExtHostTextEditor implements vscode.TextEditor {
|
||||
};
|
||||
});
|
||||
|
||||
return this._proxy.$tryApplyEdits(this._id, editData.documentVersionId, edits, {
|
||||
return this._proxy.$tryApplyEdits(this.id, editData.documentVersionId, edits, {
|
||||
setEndOfLine: typeof editData.setEndOfLine === 'number' ? TypeConverters.EndOfLine.from(editData.setEndOfLine) : undefined,
|
||||
undoStopBefore: editData.undoStopBefore,
|
||||
undoStopAfter: editData.undoStopAfter
|
||||
@@ -650,27 +641,22 @@ export class ExtHostTextEditor implements vscode.TextEditor {
|
||||
}
|
||||
}
|
||||
|
||||
return this._proxy.$tryInsertSnippet(this._id, snippet.value, ranges, options);
|
||||
return this._proxy.$tryInsertSnippet(this.id, snippet.value, ranges, options);
|
||||
}
|
||||
|
||||
// ---- util
|
||||
|
||||
private _runOnProxy(callback: () => Promise<any>): Promise<ExtHostTextEditor | undefined | null> {
|
||||
if (this._disposed) {
|
||||
console.warn('TextEditor is closed/disposed');
|
||||
this._logService.warn('TextEditor is closed/disposed');
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
return callback().then(() => this, err => {
|
||||
if (!(err instanceof Error && err.name === 'DISPOSED')) {
|
||||
console.warn(err);
|
||||
this._logService.warn(err);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function warnOnError(promise: Promise<any>): void {
|
||||
promise.then(undefined, (err) => {
|
||||
console.warn(err);
|
||||
});
|
||||
}
|
||||
|
||||
51
src/vs/workbench/api/common/extHostTunnelService.ts
Normal file
51
src/vs/workbench/api/common/extHostTunnelService.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ExtHostTunnelServiceShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import * as vscode from 'vscode';
|
||||
import { RemoteTunnel, TunnelOptions } from 'vs/platform/remote/common/tunnel';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
export interface TunnelDto {
|
||||
remoteAddress: { port: number, host: string };
|
||||
localAddress: string;
|
||||
}
|
||||
|
||||
export namespace TunnelDto {
|
||||
export function fromApiTunnel(tunnel: vscode.Tunnel): TunnelDto {
|
||||
return { remoteAddress: tunnel.remoteAddress, localAddress: tunnel.localAddress };
|
||||
}
|
||||
export function fromServiceTunnel(tunnel: RemoteTunnel): TunnelDto {
|
||||
return { remoteAddress: { host: tunnel.tunnelRemoteHost, port: tunnel.tunnelRemotePort }, localAddress: tunnel.localAddress };
|
||||
}
|
||||
}
|
||||
|
||||
export interface Tunnel extends vscode.Disposable {
|
||||
remote: { port: number, host: string };
|
||||
localAddress: string;
|
||||
}
|
||||
|
||||
export interface IExtHostTunnelService extends ExtHostTunnelServiceShape {
|
||||
readonly _serviceBrand: undefined;
|
||||
openTunnel(forward: TunnelOptions): Promise<vscode.Tunnel | undefined>;
|
||||
setForwardPortProvider(provider: vscode.RemoteAuthorityResolver | undefined): Promise<IDisposable>;
|
||||
}
|
||||
|
||||
export const IExtHostTunnelService = createDecorator<IExtHostTunnelService>('IExtHostTunnelService');
|
||||
|
||||
export class ExtHostTunnelService implements IExtHostTunnelService {
|
||||
_serviceBrand: undefined;
|
||||
async openTunnel(forward: TunnelOptions): Promise<vscode.Tunnel | undefined> {
|
||||
return undefined;
|
||||
}
|
||||
async $findCandidatePorts(): Promise<{ host: string, port: number; detail: string; }[]> {
|
||||
return [];
|
||||
}
|
||||
async setForwardPortProvider(provider: vscode.RemoteAuthorityResolver | undefined): Promise<IDisposable> { return { dispose: () => { } }; }
|
||||
$forwardPort(tunnelOptions: TunnelOptions): Promise<TunnelDto> | undefined { return undefined; }
|
||||
async $closeTunnel(remote: { host: string, port: number }): Promise<void> { }
|
||||
|
||||
}
|
||||
@@ -309,7 +309,7 @@ export namespace MarkdownString {
|
||||
}
|
||||
|
||||
export function to(value: htmlContent.IMarkdownString): vscode.MarkdownString {
|
||||
return new htmlContent.MarkdownString(value.value, value.isTrusted);
|
||||
return new htmlContent.MarkdownString(value.value, { isTrusted: value.isTrusted, supportThemeIcons: value.supportThemeIcons });
|
||||
}
|
||||
|
||||
export function fromStrict(value: string | types.MarkdownString): undefined | string | htmlContent.IMarkdownString {
|
||||
|
||||
@@ -14,6 +14,7 @@ import { generateUuid } from 'vs/base/common/uuid';
|
||||
import * as vscode from 'vscode';
|
||||
import { FileSystemProviderErrorCode, markAsFileSystemProviderError } from 'vs/platform/files/common/files';
|
||||
import { RemoteAuthorityResolverErrorCode } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { escapeCodicons } from 'vs/base/common/codicons';
|
||||
|
||||
function es5ClassCompat(target: Function): any {
|
||||
///@ts-ignore
|
||||
@@ -1231,21 +1232,25 @@ export class MarkdownString {
|
||||
|
||||
value: string;
|
||||
isTrusted?: boolean;
|
||||
readonly supportThemeIcons?: boolean;
|
||||
|
||||
constructor(value?: string) {
|
||||
this.value = value || '';
|
||||
constructor(value?: string, supportThemeIcons: boolean = false) {
|
||||
this.value = value ?? '';
|
||||
this.supportThemeIcons = supportThemeIcons;
|
||||
}
|
||||
|
||||
appendText(value: string): MarkdownString {
|
||||
// escape markdown syntax tokens: http://daringfireball.net/projects/markdown/syntax#backslash
|
||||
this.value += value
|
||||
this.value += (this.supportThemeIcons ? escapeCodicons(value) : value)
|
||||
.replace(/[\\`*_{}[\]()#+\-.!]/g, '\\$&')
|
||||
.replace('\n', '\n\n');
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
appendMarkdown(value: string): MarkdownString {
|
||||
this.value += value;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,8 +59,4 @@ export class ExtHostUrls implements ExtHostUrlsShape {
|
||||
async createAppUri(uri: URI): Promise<vscode.Uri> {
|
||||
return URI.revive(await this._proxy.$createAppUri(uri));
|
||||
}
|
||||
|
||||
async proposedCreateAppUri(extensionId: ExtensionIdentifier, options?: vscode.AppUriOptions): Promise<vscode.Uri> {
|
||||
return URI.revive(await this._proxy.$proposedCreateAppUri(extensionId, options));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { generateUuid } from 'vs/base/common/uuid';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
@@ -16,7 +15,7 @@ import { IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor';
|
||||
import { asWebviewUri, WebviewInitData } from 'vs/workbench/api/common/shared/webview';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtHostWebviewsShape, IMainContext, MainContext, MainThreadWebviewsShape, WebviewPanelHandle, WebviewPanelViewStateData } from './extHost.protocol';
|
||||
import { ExtHostWebviewsShape, IMainContext, MainContext, MainThreadWebviewsShape, WebviewEditorCapabilities, WebviewPanelHandle, WebviewPanelViewStateData } from './extHost.protocol';
|
||||
import { Disposable as VSCodeDisposable } from './extHostTypes';
|
||||
|
||||
type IconPath = URI | { light: URI, dark: URI };
|
||||
@@ -117,8 +116,6 @@ export class ExtHostWebviewEditor extends Disposable implements vscode.WebviewPa
|
||||
readonly _onDidChangeViewStateEmitter = this._register(new Emitter<vscode.WebviewPanelOnDidChangeViewStateEvent>());
|
||||
public readonly onDidChangeViewState: Event<vscode.WebviewPanelOnDidChangeViewStateEvent> = this._onDidChangeViewStateEmitter.event;
|
||||
|
||||
public _capabilities?: vscode.WebviewEditorCapabilities;
|
||||
|
||||
constructor(
|
||||
handle: WebviewPanelHandle,
|
||||
proxy: MainThreadWebviewsShape,
|
||||
@@ -239,32 +236,6 @@ export class ExtHostWebviewEditor extends Disposable implements vscode.WebviewPa
|
||||
});
|
||||
}
|
||||
|
||||
_setCapabilities(capabilities: vscode.WebviewEditorCapabilities) {
|
||||
this._capabilities = capabilities;
|
||||
if (capabilities.editingCapability) {
|
||||
this._register(capabilities.editingCapability.onEdit(edit => {
|
||||
this._proxy.$onEdit(this._handle, edit);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
_undoEdits(edits: readonly any[]): void {
|
||||
assertIsDefined(this._capabilities).editingCapability?.undoEdits(edits);
|
||||
}
|
||||
|
||||
_redoEdits(edits: readonly any[]): void {
|
||||
assertIsDefined(this._capabilities).editingCapability?.applyEdits(edits);
|
||||
}
|
||||
|
||||
async _onSave(): Promise<void> {
|
||||
await assertIsDefined(this._capabilities).editingCapability?.save();
|
||||
}
|
||||
|
||||
|
||||
async _onSaveAs(resource: vscode.Uri, targetResource: vscode.Uri): Promise<void> {
|
||||
await assertIsDefined(this._capabilities).editingCapability?.saveAs(resource, targetResource);
|
||||
}
|
||||
|
||||
private assertNotDisposed() {
|
||||
if (this._isDisposed) {
|
||||
throw new Error('Webview is disposed');
|
||||
@@ -281,7 +252,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
private readonly _proxy: MainThreadWebviewsShape;
|
||||
private readonly _webviewPanels = new Map<WebviewPanelHandle, ExtHostWebviewEditor>();
|
||||
private readonly _serializers = new Map<string, { readonly serializer: vscode.WebviewPanelSerializer, readonly extension: IExtensionDescription }>();
|
||||
private readonly _editorProviders = new Map<string, { readonly provider: vscode.WebviewEditorProvider, readonly extension: IExtensionDescription }>();
|
||||
private readonly _editorProviders = new Map<string, { readonly provider: vscode.WebviewCustomEditorProvider, readonly extension: IExtensionDescription }>();
|
||||
|
||||
constructor(
|
||||
mainContext: IMainContext,
|
||||
@@ -332,10 +303,10 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
});
|
||||
}
|
||||
|
||||
public registerWebviewEditorProvider(
|
||||
public registerWebviewCustomEditorProvider(
|
||||
extension: IExtensionDescription,
|
||||
viewType: string,
|
||||
provider: vscode.WebviewEditorProvider,
|
||||
provider: vscode.WebviewCustomEditorProvider,
|
||||
options?: vscode.WebviewPanelOptions,
|
||||
): vscode.Disposable {
|
||||
if (this._editorProviders.has(viewType)) {
|
||||
@@ -343,7 +314,10 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
}
|
||||
|
||||
this._editorProviders.set(viewType, { extension, provider, });
|
||||
this._proxy.$registerEditorProvider({ id: extension.identifier, location: extension.extensionLocation }, viewType, options || {});
|
||||
this._proxy.$registerEditorProvider({ id: extension.identifier, location: extension.extensionLocation }, viewType, options || {}, this.getCapabilites(provider));
|
||||
provider?.editingDelegate?.onEdit(({ edit, resource }) => {
|
||||
this._proxy.$onEdit(resource, viewType, edit);
|
||||
});
|
||||
|
||||
return new VSCodeDisposable(() => {
|
||||
this._editorProviders.delete(viewType);
|
||||
@@ -432,7 +406,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
}
|
||||
|
||||
async $resolveWebviewEditor(
|
||||
input: { resource: UriComponents, edits: readonly any[] },
|
||||
resource: UriComponents,
|
||||
handle: WebviewPanelHandle,
|
||||
viewType: string,
|
||||
title: string,
|
||||
@@ -448,38 +422,45 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
const webview = new ExtHostWebview(handle, this._proxy, options, this.initData, this.workspace, extension, this._logService);
|
||||
const revivedPanel = new ExtHostWebviewEditor(handle, this._proxy, viewType, title, typeof position === 'number' && position >= 0 ? typeConverters.ViewColumn.to(position) : undefined, options, webview);
|
||||
this._webviewPanels.set(handle, revivedPanel);
|
||||
const capabilities = await provider.resolveWebviewEditor({ resource: URI.revive(input.resource) }, revivedPanel);
|
||||
revivedPanel._setCapabilities(capabilities);
|
||||
|
||||
// TODO: the first set of edits should likely be passed when resolving
|
||||
if (input.edits.length) {
|
||||
revivedPanel._redoEdits(input.edits);
|
||||
}
|
||||
const revivedResource = URI.revive(resource);
|
||||
await provider.resolveWebviewEditor(revivedResource, revivedPanel);
|
||||
}
|
||||
|
||||
$undoEdits(handle: WebviewPanelHandle, edits: readonly any[]): void {
|
||||
const panel = this.getWebviewPanel(handle);
|
||||
panel?._undoEdits(edits);
|
||||
$undoEdits(resource: UriComponents, viewType: string, edits: readonly any[]): void {
|
||||
const provider = this.getEditorProvider(viewType);
|
||||
provider?.editingDelegate?.undoEdits(URI.revive(resource), edits);
|
||||
}
|
||||
|
||||
$applyEdits(handle: WebviewPanelHandle, edits: readonly any[]): void {
|
||||
const panel = this.getWebviewPanel(handle);
|
||||
panel?._redoEdits(edits);
|
||||
$applyEdits(resource: UriComponents, viewType: string, edits: readonly any[]): void {
|
||||
const provider = this.getEditorProvider(viewType);
|
||||
provider?.editingDelegate?.applyEdits(URI.revive(resource), edits);
|
||||
}
|
||||
|
||||
async $onSave(handle: WebviewPanelHandle): Promise<void> {
|
||||
const panel = this.getWebviewPanel(handle);
|
||||
return panel?._onSave();
|
||||
async $onSave(resource: UriComponents, viewType: string): Promise<void> {
|
||||
const provider = this.getEditorProvider(viewType);
|
||||
return provider?.editingDelegate?.save(URI.revive(resource));
|
||||
}
|
||||
|
||||
async $onSaveAs(handle: WebviewPanelHandle, resource: UriComponents, targetResource: UriComponents): Promise<void> {
|
||||
const panel = this.getWebviewPanel(handle);
|
||||
return panel?._onSaveAs(URI.revive(resource), URI.revive(targetResource));
|
||||
async $onSaveAs(resource: UriComponents, viewType: string, targetResource: UriComponents): Promise<void> {
|
||||
const provider = this.getEditorProvider(viewType);
|
||||
return provider?.editingDelegate?.saveAs(URI.revive(resource), URI.revive(targetResource));
|
||||
}
|
||||
|
||||
private getWebviewPanel(handle: WebviewPanelHandle): ExtHostWebviewEditor | undefined {
|
||||
return this._webviewPanels.get(handle);
|
||||
}
|
||||
|
||||
private getEditorProvider(viewType: string): vscode.WebviewCustomEditorProvider | undefined {
|
||||
return this._editorProviders.get(viewType)?.provider;
|
||||
}
|
||||
|
||||
private getCapabilites(capabilities: vscode.WebviewCustomEditorProvider) {
|
||||
const declaredCapabilites: WebviewEditorCapabilities[] = [];
|
||||
if (capabilities.editingDelegate) {
|
||||
declaredCapabilites.push(WebviewEditorCapabilities.Editable);
|
||||
}
|
||||
return declaredCapabilites;
|
||||
}
|
||||
}
|
||||
|
||||
function convertWebviewOptions(
|
||||
|
||||
@@ -351,11 +351,8 @@ commandsExtensionPoint.setHandler(extensions => {
|
||||
let absoluteIcon: { dark: URI; light?: URI; } | ThemeIcon | undefined;
|
||||
if (icon) {
|
||||
if (typeof icon === 'string') {
|
||||
if (extension.description.enableProposedApi) {
|
||||
absoluteIcon = ThemeIcon.fromString(icon) || { dark: resources.joinPath(extension.description.extensionLocation, icon) };
|
||||
} else {
|
||||
absoluteIcon = { dark: resources.joinPath(extension.description.extensionLocation, icon) };
|
||||
}
|
||||
absoluteIcon = ThemeIcon.fromString(icon) || { dark: resources.joinPath(extension.description.extensionLocation, icon) };
|
||||
|
||||
} else {
|
||||
absoluteIcon = {
|
||||
dark: resources.joinPath(extension.description.extensionLocation, icon.dark),
|
||||
|
||||
Reference in New Issue
Block a user