mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-04 07:15:54 +01:00
Merge branch 'master' into fix-70323
This commit is contained in:
@@ -48,6 +48,7 @@ import './mainThreadStatusBar';
|
||||
import './mainThreadStorage';
|
||||
import './mainThreadTelemetry';
|
||||
import './mainThreadTerminalService';
|
||||
import './mainThreadTheming';
|
||||
import './mainThreadTreeViews';
|
||||
import './mainThreadDownloadService';
|
||||
import './mainThreadUrls';
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope, getScopes } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { MainThreadConfigurationShape, MainContext, ExtHostContext, IExtHostContext, IConfigurationInitData } from '../common/extHost.protocol';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { ConfigurationTarget, IConfigurationService, IConfigurationOverrides } from 'vs/platform/configuration/common/configuration';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadConfiguration)
|
||||
@@ -45,23 +45,43 @@ export class MainThreadConfiguration implements MainThreadConfigurationShape {
|
||||
this._configurationListener.dispose();
|
||||
}
|
||||
|
||||
$updateConfigurationOption(target: ConfigurationTarget | null, key: string, value: any, resourceUriComponenets: UriComponents | undefined): Promise<void> {
|
||||
const resource = resourceUriComponenets ? URI.revive(resourceUriComponenets) : null;
|
||||
return this.writeConfiguration(target, key, value, resource);
|
||||
$updateConfigurationOption(target: ConfigurationTarget | null, key: string, value: any, overrides: IConfigurationOverrides | undefined, scopeToLanguage: boolean | undefined): Promise<void> {
|
||||
overrides = { resource: overrides?.resource ? URI.revive(overrides.resource) : undefined, overrideIdentifier: overrides?.overrideIdentifier };
|
||||
return this.writeConfiguration(target, key, value, overrides, scopeToLanguage);
|
||||
}
|
||||
|
||||
$removeConfigurationOption(target: ConfigurationTarget | null, key: string, resourceUriComponenets: UriComponents | undefined): Promise<void> {
|
||||
const resource = resourceUriComponenets ? URI.revive(resourceUriComponenets) : null;
|
||||
return this.writeConfiguration(target, key, undefined, resource);
|
||||
$removeConfigurationOption(target: ConfigurationTarget | null, key: string, overrides: IConfigurationOverrides | undefined, scopeToLanguage: boolean | undefined): Promise<void> {
|
||||
overrides = { resource: overrides?.resource ? URI.revive(overrides.resource) : undefined, overrideIdentifier: overrides?.overrideIdentifier };
|
||||
return this.writeConfiguration(target, key, undefined, overrides, scopeToLanguage);
|
||||
}
|
||||
|
||||
private writeConfiguration(target: ConfigurationTarget | null, key: string, value: any, resource: URI | null): Promise<void> {
|
||||
target = target !== null && target !== undefined ? target : this.deriveConfigurationTarget(key, resource);
|
||||
return this.configurationService.updateValue(key, value, { resource }, target, true);
|
||||
private writeConfiguration(target: ConfigurationTarget | null, key: string, value: any, overrides: IConfigurationOverrides, scopeToLanguage: boolean | undefined): Promise<void> {
|
||||
target = target !== null && target !== undefined ? target : this.deriveConfigurationTarget(key, overrides);
|
||||
const configurationValue = this.configurationService.inspect(key, overrides);
|
||||
switch (target) {
|
||||
case ConfigurationTarget.MEMORY:
|
||||
return this._updateValue(key, value, target, configurationValue?.memory?.override, overrides, scopeToLanguage);
|
||||
case ConfigurationTarget.WORKSPACE_FOLDER:
|
||||
return this._updateValue(key, value, target, configurationValue?.workspaceFolder?.override, overrides, scopeToLanguage);
|
||||
case ConfigurationTarget.WORKSPACE:
|
||||
return this._updateValue(key, value, target, configurationValue?.workspace?.override, overrides, scopeToLanguage);
|
||||
case ConfigurationTarget.USER_REMOTE:
|
||||
return this._updateValue(key, value, target, configurationValue?.userRemote?.override, overrides, scopeToLanguage);
|
||||
default:
|
||||
return this._updateValue(key, value, target, configurationValue?.userLocal?.override, overrides, scopeToLanguage);
|
||||
}
|
||||
}
|
||||
|
||||
private deriveConfigurationTarget(key: string, resource: URI | null): ConfigurationTarget {
|
||||
if (resource && this._workspaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE) {
|
||||
private _updateValue(key: string, value: any, configurationTarget: ConfigurationTarget, overriddenValue: any | undefined, overrides: IConfigurationOverrides, scopeToLanguage: boolean | undefined): Promise<void> {
|
||||
overrides = scopeToLanguage === true ? overrides
|
||||
: scopeToLanguage === false ? { resource: overrides.resource }
|
||||
: overrides.overrideIdentifier && overriddenValue !== undefined ? overrides
|
||||
: { resource: overrides.resource };
|
||||
return this.configurationService.updateValue(key, value, overrides, configurationTarget);
|
||||
}
|
||||
|
||||
private deriveConfigurationTarget(key: string, overrides: IConfigurationOverrides): ConfigurationTarget {
|
||||
if (overrides.resource && this._workspaceContextService.getWorkbenchState() === WorkbenchState.WORKSPACE) {
|
||||
const configurationProperties = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration).getConfigurationProperties();
|
||||
if (configurationProperties[key] && (configurationProperties[key].scope === ConfigurationScope.RESOURCE || configurationProperties[key].scope === ConfigurationScope.RESOURCE_LANGUAGE)) {
|
||||
return ConfigurationTarget.WORKSPACE_FOLDER;
|
||||
|
||||
@@ -154,7 +154,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
public $registerDebugConfigurationProvider(debugType: string, hasProvide: boolean, hasResolve: boolean, hasProvideDebugAdapter: boolean, handle: number): Promise<void> {
|
||||
public $registerDebugConfigurationProvider(debugType: string, hasProvide: boolean, hasResolve: boolean, hasResolve2: boolean, hasProvideDebugAdapter: boolean, handle: number): Promise<void> {
|
||||
|
||||
const provider = <IDebugConfigurationProvider>{
|
||||
type: debugType
|
||||
@@ -169,6 +169,11 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
|
||||
return this._proxy.$resolveDebugConfiguration(handle, folder, config, token);
|
||||
};
|
||||
}
|
||||
if (hasResolve2) {
|
||||
provider.resolveDebugConfigurationWithSubstitutedVariables = (folder, config, token) => {
|
||||
return this._proxy.$resolveDebugConfigurationWithSubstitutedVariables(handle, folder, config, token);
|
||||
};
|
||||
}
|
||||
if (hasProvideDebugAdapter) {
|
||||
console.info('DebugConfigurationProvider.debugAdapterExecutable is deprecated and will be removed soon; please use DebugAdapterDescriptorFactory.createDebugAdapterDescriptor instead.');
|
||||
provider.debugAdapterExecutable = (folder) => {
|
||||
|
||||
@@ -505,13 +505,17 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
|
||||
this._registrations.set(handle, callh.CallHierarchyProviderRegistry.register(selector, {
|
||||
|
||||
prepareCallHierarchy: async (document, position, token) => {
|
||||
const item = await this._proxy.$prepareCallHierarchy(handle, document.uri, position, token);
|
||||
if (!item) {
|
||||
const items = await this._proxy.$prepareCallHierarchy(handle, document.uri, position, token);
|
||||
if (!items) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
dispose: () => this._proxy.$releaseCallHierarchy(handle, item._sessionId),
|
||||
root: MainThreadLanguageFeatures._reviveCallHierarchyItemDto(item)
|
||||
dispose: () => {
|
||||
for (const item of items) {
|
||||
this._proxy.$releaseCallHierarchy(handle, item._sessionId);
|
||||
}
|
||||
},
|
||||
roots: items.map(MainThreadLanguageFeatures._reviveCallHierarchyItemDto)
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
@@ -514,15 +514,19 @@ export class MainThreadTask implements MainThreadTaskShape {
|
||||
if (TaskHandleDTO.is(value)) {
|
||||
const workspaceFolder = this._workspaceContextServer.getWorkspaceFolder(URI.revive(value.workspaceFolder));
|
||||
if (workspaceFolder) {
|
||||
this._taskService.getTask(workspaceFolder, value.id, true).then((task: Task) => {
|
||||
this._taskService.run(task).then(undefined, reason => {
|
||||
// eat the error, it has already been surfaced to the user and we don't care about it here
|
||||
});
|
||||
const result: TaskExecutionDTO = {
|
||||
id: value.id,
|
||||
task: TaskDTO.from(task)
|
||||
};
|
||||
resolve(result);
|
||||
this._taskService.getTask(workspaceFolder, value.id, true).then((task: Task | undefined) => {
|
||||
if (!task) {
|
||||
reject(new Error('Task not found'));
|
||||
} else {
|
||||
this._taskService.run(task).then(undefined, reason => {
|
||||
// eat the error, it has already been surfaced to the user and we don't care about it here
|
||||
});
|
||||
const result: TaskExecutionDTO = {
|
||||
id: value.id,
|
||||
task: TaskDTO.from(task)
|
||||
};
|
||||
resolve(result);
|
||||
}
|
||||
}, (_error) => {
|
||||
reject(new Error('Task not found'));
|
||||
});
|
||||
|
||||
33
src/vs/workbench/api/browser/mainThreadTheming.ts
Normal file
33
src/vs/workbench/api/browser/mainThreadTheming.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { MainContext, IExtHostContext, ExtHostThemingShape, ExtHostContext, MainThreadThemingShape } from '../common/extHost.protocol';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadTheming)
|
||||
export class MainThreadTheming implements MainThreadThemingShape {
|
||||
|
||||
private readonly _themeService: IThemeService;
|
||||
private readonly _proxy: ExtHostThemingShape;
|
||||
private readonly _themeChangeListener: IDisposable;
|
||||
|
||||
constructor(
|
||||
extHostContext: IExtHostContext,
|
||||
@IThemeService themeService: IThemeService
|
||||
) {
|
||||
this._themeService = themeService;
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostTheming);
|
||||
|
||||
this._themeChangeListener = this._themeService.onThemeChange(e => {
|
||||
this._proxy.$onColorThemeChange(this._themeService.getTheme().type);
|
||||
});
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._themeChangeListener.dispose();
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,10 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { MainThreadTunnelServiceShape, IExtHostContext, MainContext, ExtHostContext, ExtHostTunnelServiceShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { TunnelOptions, TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
|
||||
import { IRemoteExplorerService } from 'vs/workbench/services/remote/common/remoteExplorerService';
|
||||
import { ITunnelProvider, ITunnelService } from 'vs/platform/remote/common/tunnel';
|
||||
import { ITunnelProvider, ITunnelService, TunnelOptions } from 'vs/platform/remote/common/tunnel';
|
||||
|
||||
@extHostNamedCustomer(MainContext.MainThreadTunnelService)
|
||||
export class MainThreadTunnelService implements MainThreadTunnelServiceShape {
|
||||
@@ -22,15 +22,15 @@ export class MainThreadTunnelService implements MainThreadTunnelServiceShape {
|
||||
}
|
||||
|
||||
async $openTunnel(tunnelOptions: TunnelOptions): Promise<TunnelDto | undefined> {
|
||||
const tunnel = await this.remoteExplorerService.forward(tunnelOptions.remote.port, tunnelOptions.localPort, tunnelOptions.name);
|
||||
const tunnel = await this.remoteExplorerService.forward(tunnelOptions.remoteAddress, tunnelOptions.localPort, tunnelOptions.label);
|
||||
if (tunnel) {
|
||||
return TunnelDto.fromServiceTunnel(tunnel);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async $closeTunnel(remotePort: number): Promise<void> {
|
||||
return this.remoteExplorerService.close(remotePort);
|
||||
async $closeTunnel(remote: { host: string, port: number }): Promise<void> {
|
||||
return this.remoteExplorerService.close(remote);
|
||||
}
|
||||
|
||||
async $registerCandidateFinder(): Promise<void> {
|
||||
@@ -44,11 +44,11 @@ export class MainThreadTunnelService implements MainThreadTunnelServiceShape {
|
||||
if (forward) {
|
||||
return forward.then(tunnel => {
|
||||
return {
|
||||
tunnelRemotePort: tunnel.remote.port,
|
||||
tunnelRemoteHost: tunnel.remote.host,
|
||||
tunnelRemotePort: tunnel.remoteAddress.port,
|
||||
tunnelRemoteHost: tunnel.remoteAddress.host,
|
||||
localAddress: tunnel.localAddress,
|
||||
dispose: () => {
|
||||
this._proxy.$closeTunnel({ host: tunnel.remote.host, port: tunnel.remote.port });
|
||||
this._proxy.$closeTunnel({ host: tunnel.remoteAddress.host, port: tunnel.remoteAddress.port });
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Disposable, IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { isWeb } from 'vs/base/common/platform';
|
||||
import { startsWith } from 'vs/base/common/strings';
|
||||
@@ -20,7 +20,7 @@ import { editorGroupToViewColumn, EditorViewColumn, viewColumnToEditorGroup } fr
|
||||
import { IEditorInput } from 'vs/workbench/common/editor';
|
||||
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
|
||||
import { CustomFileEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput';
|
||||
import { ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor';
|
||||
import { ICustomEditorModel, ICustomEditorService } from 'vs/workbench/contrib/customEditor/common/customEditor';
|
||||
import { WebviewExtensionDescription } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { WebviewInput } from 'vs/workbench/contrib/webview/browser/webviewEditorInput';
|
||||
import { ICreateWebViewShowOptions, IWebviewWorkbenchService, WebviewInputOptions } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService';
|
||||
@@ -95,6 +95,7 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
||||
private readonly _webviewInputs = new WebviewInputStore();
|
||||
private readonly _revivers = new Map<string, IDisposable>();
|
||||
private readonly _editorProviders = new Map<string, IDisposable>();
|
||||
private readonly _customEditorModels = new Map<ICustomEditorModel, { referenceCount: number }>();
|
||||
|
||||
constructor(
|
||||
context: extHostProtocol.IExtHostContext,
|
||||
@@ -272,10 +273,9 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
||||
webviewInput.webview.extension = extension;
|
||||
const resource = webviewInput.getResource();
|
||||
|
||||
const model = await this.loadOrCreateModel(webviewInput, resource, viewType, capabilities);
|
||||
const model = await this.retainCustomEditorModel(webviewInput, resource, viewType, capabilities);
|
||||
webviewInput.onDisposeWebview(() => {
|
||||
// TODO: This should be reference counted
|
||||
this._customEditorService.models.disposeModel(model);
|
||||
this.releaseCustomEditorModel(model);
|
||||
});
|
||||
|
||||
try {
|
||||
@@ -306,36 +306,53 @@ export class MainThreadWebviews extends Disposable implements extHostProtocol.Ma
|
||||
this._editorProviders.delete(viewType);
|
||||
}
|
||||
|
||||
private async loadOrCreateModel(webviewInput: WebviewInput, resource: URI, viewType: string, capabilities: readonly extHostProtocol.WebviewEditorCapabilities[]) {
|
||||
const existingModel = this._customEditorService.models.get(webviewInput.getResource(), webviewInput.viewType);
|
||||
if (existingModel) {
|
||||
return existingModel;
|
||||
private async retainCustomEditorModel(webviewInput: WebviewInput, resource: URI, viewType: string, capabilities: readonly extHostProtocol.WebviewEditorCapabilities[]) {
|
||||
const model = await this._customEditorService.models.loadOrCreate(webviewInput.getResource(), webviewInput.viewType);
|
||||
|
||||
const existingEntry = this._customEditorModels.get(model);
|
||||
if (existingEntry) {
|
||||
++existingEntry.referenceCount;
|
||||
// no need to hook up listeners again
|
||||
return model;
|
||||
}
|
||||
|
||||
const newModel = await this._customEditorService.models.loadOrCreate(webviewInput.getResource(), webviewInput.viewType);
|
||||
this._customEditorModels.set(model, { referenceCount: 1 });
|
||||
|
||||
const capabilitiesSet = new Set(capabilities);
|
||||
if (capabilitiesSet.has(extHostProtocol.WebviewEditorCapabilities.Editable)) {
|
||||
newModel.onUndo(edits => {
|
||||
model.onUndo(edits => {
|
||||
this._proxy.$undoEdits(resource, viewType, edits.map(x => x.data));
|
||||
});
|
||||
|
||||
newModel.onApplyEdit(edits => {
|
||||
const editsToApply = edits.filter(x => x.source !== newModel).map(x => x.data);
|
||||
model.onApplyEdit(edits => {
|
||||
const editsToApply = edits.filter(x => x.source !== model).map(x => x.data);
|
||||
if (editsToApply.length) {
|
||||
this._proxy.$applyEdits(resource, viewType, editsToApply);
|
||||
}
|
||||
});
|
||||
|
||||
newModel.onWillSave(e => {
|
||||
model.onWillSave(e => {
|
||||
e.waitUntil(this._proxy.$onSave(resource.toJSON(), viewType));
|
||||
});
|
||||
|
||||
newModel.onWillSaveAs(e => {
|
||||
model.onWillSaveAs(e => {
|
||||
e.waitUntil(this._proxy.$onSaveAs(e.resource.toJSON(), viewType, e.targetResource.toJSON()));
|
||||
});
|
||||
}
|
||||
return newModel;
|
||||
return model;
|
||||
}
|
||||
|
||||
private async releaseCustomEditorModel(model: ICustomEditorModel) {
|
||||
const entry = this._customEditorModels.get(model);
|
||||
if (!entry) {
|
||||
return;
|
||||
}
|
||||
|
||||
--entry.referenceCount;
|
||||
if (entry.referenceCount <= 0) {
|
||||
this._customEditorService.models.disposeModel(model);
|
||||
this._customEditorModels.delete(model);
|
||||
}
|
||||
}
|
||||
|
||||
public $onEdit(resource: UriComponents, viewType: string, editData: any): void {
|
||||
|
||||
@@ -8,7 +8,7 @@ import { forEach } from 'vs/base/common/collections';
|
||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
import * as resources from 'vs/base/common/resources';
|
||||
import { ExtensionMessageCollector, ExtensionsRegistry, IExtensionPoint, IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry';
|
||||
import { ViewContainer, IViewsRegistry, ITreeViewDescriptor, IViewContainersRegistry, Extensions as ViewContainerExtensions, TEST_VIEW_CONTAINER_ID, IViewDescriptor } from 'vs/workbench/common/views';
|
||||
import { ViewContainer, IViewsRegistry, ITreeViewDescriptor, IViewContainersRegistry, Extensions as ViewContainerExtensions, TEST_VIEW_CONTAINER_ID, IViewDescriptor, ViewContainerLocation } from 'vs/workbench/common/views';
|
||||
import { CustomTreeViewPane, CustomTreeView } from 'vs/workbench/browser/parts/views/customView';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { coalesce, } from 'vs/base/common/arrays';
|
||||
@@ -22,14 +22,13 @@ import { VIEWLET_ID as DEBUG } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { VIEWLET_ID as REMOTE } from 'vs/workbench/contrib/remote/common/remote.contribution';
|
||||
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor, ShowViewletAction, Viewlet } from 'vs/workbench/browser/viewlet';
|
||||
import { ViewletRegistry, Extensions as ViewletExtensions, ShowViewletAction } from 'vs/workbench/browser/viewlet';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
@@ -313,7 +312,6 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
|
||||
|
||||
if (!viewContainer) {
|
||||
|
||||
viewContainer = this.viewContainersRegistry.registerViewContainer(id, true, extensionId);
|
||||
|
||||
class CustomViewPaneContainer extends ViewPaneContainer {
|
||||
constructor(
|
||||
@@ -327,38 +325,17 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@IExtensionService extensionService: IExtensionService,
|
||||
) {
|
||||
super(id, `${id}.state`, { showHeaderInTitleWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService);
|
||||
super(id, `${id}.state`, { mergeViewWithContainerWhenSingleView: true }, instantiationService, configurationService, layoutService, contextMenuService, telemetryService, extensionService, themeService, storageService, contextService);
|
||||
}
|
||||
}
|
||||
|
||||
// Register a viewlet
|
||||
class CustomViewlet extends Viewlet {
|
||||
constructor(
|
||||
@IConfigurationService configurationService: IConfigurationService,
|
||||
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
|
||||
@ITelemetryService telemetryService: ITelemetryService,
|
||||
@IWorkspaceContextService contextService: IWorkspaceContextService,
|
||||
@IStorageService storageService: IStorageService,
|
||||
@IEditorService editorService: IEditorService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IContextMenuService contextMenuService: IContextMenuService,
|
||||
@IExtensionService extensionService: IExtensionService
|
||||
) {
|
||||
super(id, instantiationService.createInstance(CustomViewPaneContainer), telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService, layoutService, configurationService);
|
||||
}
|
||||
}
|
||||
|
||||
const viewletDescriptor = ViewletDescriptor.create(
|
||||
CustomViewlet,
|
||||
viewContainer = this.viewContainersRegistry.registerViewContainer({
|
||||
id,
|
||||
title,
|
||||
undefined,
|
||||
order,
|
||||
icon
|
||||
);
|
||||
|
||||
Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets).registerViewlet(viewletDescriptor);
|
||||
name: title, extensionId,
|
||||
ctorDescriptor: { ctor: CustomViewPaneContainer },
|
||||
hideIfEmpty: true,
|
||||
icon,
|
||||
}, ViewContainerLocation.Sidebar);
|
||||
|
||||
// Register Action to Open Viewlet
|
||||
class OpenCustomViewletAction extends ShowViewletAction {
|
||||
@@ -432,8 +409,8 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
|
||||
|
||||
const order = ExtensionIdentifier.equals(extension.description.identifier, container.extensionId)
|
||||
? index + 1
|
||||
: container.orderDelegate
|
||||
? container.orderDelegate.getOrder(item.group)
|
||||
: container.viewOrderDelegate
|
||||
? container.viewOrderDelegate.getOrder(item.group)
|
||||
: undefined;
|
||||
|
||||
const viewDescriptor = <ICustomViewDescriptor>{
|
||||
|
||||
@@ -39,17 +39,16 @@ const configurationEntrySchema: IJSONSchema = {
|
||||
},
|
||||
scope: {
|
||||
type: 'string',
|
||||
enum: ['application', 'machine', 'window', 'resource', 'resource-language', 'machine-overridable'],
|
||||
enum: ['application', 'machine', 'window', 'resource', 'machine-overridable'],
|
||||
default: 'window',
|
||||
enumDescriptions: [
|
||||
nls.localize('scope.application.description', "Configuration that can be configured only in the user settings."),
|
||||
nls.localize('scope.machine.description', "Configuration that can be configured only in the user settings when the extension is running locally, or only in the remote settings when the extension is running remotely."),
|
||||
nls.localize('scope.window.description', "Configuration that can be configured in the user, remote or workspace settings."),
|
||||
nls.localize('scope.resource.description', "Configuration that can be configured in the user, remote, workspace or folder settings."),
|
||||
nls.localize('scope.resource-language.description', "Resource configuration that can be configured also in language specific 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`, `resource-language` 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',
|
||||
@@ -58,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',
|
||||
|
||||
@@ -67,6 +67,7 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IURITransformerService } from 'vs/workbench/api/common/extHostUriTransformerService';
|
||||
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 {
|
||||
@@ -125,7 +126,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
const extHostComment = rpcProtocol.set(ExtHostContext.ExtHostComments, new ExtHostComments(rpcProtocol, extHostCommands, extHostDocuments));
|
||||
const extHostWindow = rpcProtocol.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(rpcProtocol));
|
||||
const extHostProgress = rpcProtocol.set(ExtHostContext.ExtHostProgress, new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress)));
|
||||
const extHostLabelService = rpcProtocol.set(ExtHostContext.ExtHosLabelService, new ExtHostLabelService(rpcProtocol));
|
||||
const extHostLabelService = rpcProtocol.set(ExtHostContext.ExtHostLabelService, new ExtHostLabelService(rpcProtocol));
|
||||
const extHostTheming = rpcProtocol.set(ExtHostContext.ExtHostTheming, new ExtHostTheming(rpcProtocol));
|
||||
|
||||
// Check that no named customers are missing
|
||||
const expected: ProxyIdentifier<any>[] = values(ExtHostContext);
|
||||
@@ -548,6 +550,14 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
},
|
||||
createInputBox(): vscode.InputBox {
|
||||
return extHostQuickOpen.createInputBox(extension.identifier);
|
||||
},
|
||||
get activeColorTheme(): vscode.ColorTheme {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostTheming.activeColorTheme;
|
||||
},
|
||||
onDidChangeActiveColorTheme(listener, thisArg?, disposables?) {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostTheming.onDidChangeActiveColorTheme(listener, thisArg, disposables);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -664,9 +674,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);
|
||||
@@ -714,9 +724,9 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
onWillRenameFiles: (listener: (e: vscode.FileWillRenameEvent) => any, thisArg?: any, disposables?: vscode.Disposable[]) => {
|
||||
return extHostFileSystemEvent.getOnWillRenameFileEvent(extension)(listener, thisArg, disposables);
|
||||
},
|
||||
makeTunnel: (forward: vscode.TunnelOptions) => {
|
||||
openTunnel: (forward: vscode.TunnelOptions) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostTunnelService.makeTunnel(forward);
|
||||
return extHostTunnelService.openTunnel(forward);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -935,7 +945,8 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
DebugConsoleMode: extHostTypes.DebugConsoleMode,
|
||||
Decoration: extHostTypes.Decoration,
|
||||
WebviewContentState: extHostTypes.WebviewContentState,
|
||||
UIKind: UIKind
|
||||
UIKind: UIKind,
|
||||
ColorThemeKind: extHostTypes.ColorThemeKind
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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, IConfigurationChange } 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,7 +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 { TunnelOptions, TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { TunnelOptions } from 'vs/platform/remote/common/tunnel';
|
||||
|
||||
export interface IEnvironment {
|
||||
isExtensionDevelopmentDebug: boolean;
|
||||
@@ -147,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 {
|
||||
@@ -749,7 +750,7 @@ export interface MainThreadDebugServiceShape extends IDisposable {
|
||||
$acceptDAMessage(handle: number, message: DebugProtocol.ProtocolMessage): void;
|
||||
$acceptDAError(handle: number, name: string, message: string, stack: string | undefined): void;
|
||||
$acceptDAExit(handle: number, code: number | undefined, signal: string | undefined): void;
|
||||
$registerDebugConfigurationProvider(type: string, hasProvideMethod: boolean, hasResolveMethod: boolean, hasProvideDaMethod: boolean, handle: number): Promise<void>;
|
||||
$registerDebugConfigurationProvider(type: string, hasProvideMethod: boolean, hasResolveMethod: boolean, hasResolve2Method: boolean, hasProvideDaMethod: boolean, handle: number): Promise<void>;
|
||||
$registerDebugAdapterDescriptorFactory(type: string, handle: number): Promise<void>;
|
||||
$unregisterDebugConfigurationProvider(handle: number): void;
|
||||
$unregisterDebugAdapterDescriptorFactory(handle: number): void;
|
||||
@@ -774,7 +775,7 @@ export interface MainThreadWindowShape extends IDisposable {
|
||||
|
||||
export interface MainThreadTunnelServiceShape extends IDisposable {
|
||||
$openTunnel(tunnelOptions: TunnelOptions): Promise<TunnelDto | undefined>;
|
||||
$closeTunnel(remotePort: number): Promise<void>;
|
||||
$closeTunnel(remote: { host: string, port: number }): Promise<void>;
|
||||
$registerCandidateFinder(): Promise<void>;
|
||||
$setTunnelProvider(): Promise<void>;
|
||||
}
|
||||
@@ -1188,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;
|
||||
@@ -1336,6 +1337,7 @@ export interface ExtHostDebugServiceShape {
|
||||
$stopDASession(handle: number): Promise<void>;
|
||||
$sendDAMessage(handle: number, message: DebugProtocol.ProtocolMessage): void;
|
||||
$resolveDebugConfiguration(handle: number, folder: UriComponents | undefined, debugConfiguration: IConfig, token: CancellationToken): Promise<IConfig | null | undefined>;
|
||||
$resolveDebugConfigurationWithSubstitutedVariables(handle: number, folder: UriComponents | undefined, debugConfiguration: IConfig, token: CancellationToken): Promise<IConfig | null | undefined>;
|
||||
$provideDebugConfigurations(handle: number, folder: UriComponents | undefined, token: CancellationToken): Promise<IConfig[]>;
|
||||
$legacyDebugAdapterExecutable(handle: number, folderUri: UriComponents | undefined): Promise<IAdapterDescriptor>; // TODO@AW legacy
|
||||
$provideDebugAdapter(handle: number, session: IDebugSessionDto): Promise<IAdapterDescriptor>;
|
||||
@@ -1393,9 +1395,15 @@ export interface ExtHostStorageShape {
|
||||
$acceptValue(shared: boolean, key: string, value: object | undefined): void;
|
||||
}
|
||||
|
||||
export interface ExtHostThemingShape {
|
||||
$onColorThemeChange(themeType: string): void;
|
||||
}
|
||||
|
||||
export interface MainThreadThemingShape extends IDisposable {
|
||||
}
|
||||
|
||||
export interface ExtHostTunnelServiceShape {
|
||||
$findCandidatePorts(): Promise<{ port: number, detail: string }[]>;
|
||||
$findCandidatePorts(): Promise<{ host: string, port: number, detail: string }[]>;
|
||||
$forwardPort(tunnelOptions: TunnelOptions): Promise<TunnelDto> | undefined;
|
||||
$closeTunnel(remote: { host: string, port: number }): Promise<void>;
|
||||
}
|
||||
@@ -1441,6 +1449,7 @@ export const MainContext = {
|
||||
MainThreadTask: createMainId<MainThreadTaskShape>('MainThreadTask'),
|
||||
MainThreadWindow: createMainId<MainThreadWindowShape>('MainThreadWindow'),
|
||||
MainThreadLabelService: createMainId<MainThreadLabelServiceShape>('MainThreadLabelService'),
|
||||
MainThreadTheming: createMainId<MainThreadThemingShape>('MainThreadTheming'),
|
||||
MainThreadTunnelService: createMainId<MainThreadTunnelServiceShape>('MainThreadTunnelService')
|
||||
};
|
||||
|
||||
@@ -1475,6 +1484,7 @@ export const ExtHostContext = {
|
||||
ExtHostStorage: createMainId<ExtHostStorageShape>('ExtHostStorage'),
|
||||
ExtHostUrls: createExtId<ExtHostUrlsShape>('ExtHostUrls'),
|
||||
ExtHostOutputService: createMainId<ExtHostOutputServiceShape>('ExtHostOutputService'),
|
||||
ExtHosLabelService: createMainId<ExtHostLabelServiceShape>('ExtHostLabelService'),
|
||||
ExtHostLabelService: createMainId<ExtHostLabelServiceShape>('ExtHostLabelService'),
|
||||
ExtHostTheming: createMainId<ExtHostThemingShape>('ExtHostTheming'),
|
||||
ExtHostTunnelService: createMainId<ExtHostTunnelServiceShape>('ExtHostTunnelService')
|
||||
};
|
||||
|
||||
@@ -4,22 +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, IConfigurationInitData, MainContext } from './extHost.protocol';
|
||||
import { ConfigurationTarget as ExtHostConfigurationTarget } from './extHostTypes';
|
||||
import { ConfigurationTarget, IConfigurationChange, IConfigurationData } from 'vs/platform/configuration/common/configuration';
|
||||
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) {
|
||||
@@ -34,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;
|
||||
@@ -104,13 +150,17 @@ export class ExtHostConfigProvider {
|
||||
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.defaultValue,
|
||||
globalValue: config.userValue,
|
||||
workspaceValue: config.workspaceValue,
|
||||
workspaceFolderValue: config.workspaceFolderValue
|
||||
workspaceFolderValue: config.workspaceFolderValue,
|
||||
|
||||
defaultLanguageValue: config.default?.override,
|
||||
userLanguageValue: config.user?.override,
|
||||
workspaceLanguageValue: config.workspace?.override,
|
||||
workspaceFolderLanguageValue: config.workspaceFolder?.override,
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
@@ -237,17 +293,17 @@ 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;
|
||||
@@ -257,7 +313,7 @@ export class ExtHostConfigProvider {
|
||||
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 ? { resource } : undefined)
|
||||
affectsConfiguration: (section: string, scope?: vscode.ConfigurationScope) => event.affectsConfiguration(section, scopeToOverrides(scope))
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -315,6 +315,7 @@ export class ExtHostDebugServiceBase implements IExtHostDebugService, ExtHostDeb
|
||||
this._debugServiceProxy.$registerDebugConfigurationProvider(type,
|
||||
!!provider.provideDebugConfigurations,
|
||||
!!provider.resolveDebugConfiguration,
|
||||
!!provider.resolveDebugConfigurationWithSubstitutedVariables,
|
||||
!!provider.debugAdapterExecutable, // TODO@AW: deprecated
|
||||
handle);
|
||||
|
||||
@@ -628,6 +629,20 @@ export class ExtHostDebugServiceBase implements IExtHostDebugService, ExtHostDeb
|
||||
});
|
||||
}
|
||||
|
||||
public $resolveDebugConfigurationWithSubstitutedVariables(configProviderHandle: number, folderUri: UriComponents | undefined, debugConfiguration: vscode.DebugConfiguration, token: CancellationToken): Promise<vscode.DebugConfiguration | null | undefined> {
|
||||
return asPromise(async () => {
|
||||
const provider = this.getConfigProviderByHandle(configProviderHandle);
|
||||
if (!provider) {
|
||||
throw new Error('no DebugConfigurationProvider found');
|
||||
}
|
||||
if (!provider.resolveDebugConfigurationWithSubstitutedVariables) {
|
||||
throw new Error('DebugConfigurationProvider has no method resolveDebugConfigurationWithSubstitutedVariables');
|
||||
}
|
||||
const folder = await this.getFolder(folderUri);
|
||||
return provider.resolveDebugConfigurationWithSubstitutedVariables(folder, debugConfiguration, token);
|
||||
});
|
||||
}
|
||||
|
||||
// TODO@AW deprecated and legacy
|
||||
public $legacyDebugAdapterExecutable(configProviderHandle: number, folderUri: UriComponents | undefined): Promise<IAdapterDescriptor> {
|
||||
return asPromise(async () => {
|
||||
|
||||
@@ -662,7 +662,7 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
|
||||
value: {
|
||||
authority,
|
||||
options,
|
||||
tunnelInformation: { detectedTunnels: result.detectedTunnels }
|
||||
tunnelInformation: { environmentTunnels: result.environmentTunnels }
|
||||
}
|
||||
};
|
||||
} catch (err) {
|
||||
|
||||
@@ -1200,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> {
|
||||
@@ -1727,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);
|
||||
}
|
||||
|
||||
|
||||
38
src/vs/workbench/api/common/extHostTheming.ts
Normal file
38
src/vs/workbench/api/common/extHostTheming.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ColorTheme, ColorThemeKind } from './extHostTypes';
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { ExtHostThemingShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
|
||||
export class ExtHostTheming implements ExtHostThemingShape {
|
||||
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
private _actual: ColorTheme;
|
||||
private _onDidChangeActiveColorTheme: Emitter<ColorTheme>;
|
||||
|
||||
constructor(
|
||||
@IExtHostRpcService _extHostRpc: IExtHostRpcService
|
||||
) {
|
||||
this._actual = new ColorTheme(ColorThemeKind.Dark);
|
||||
this._onDidChangeActiveColorTheme = new Emitter<ColorTheme>();
|
||||
}
|
||||
|
||||
public get activeColorTheme(): ColorTheme {
|
||||
return this._actual;
|
||||
}
|
||||
|
||||
$onColorThemeChange(type: string): void {
|
||||
let kind = type === 'light' ? ColorThemeKind.Light : type === 'dark' ? ColorThemeKind.Dark : ColorThemeKind.HighContrast;
|
||||
this._actual = new ColorTheme(kind);
|
||||
this._onDidChangeActiveColorTheme.fire(this._actual);
|
||||
}
|
||||
|
||||
public get onDidChangeActiveColorTheme(): Event<ColorTheme> {
|
||||
return this._onDidChangeActiveColorTheme.event;
|
||||
}
|
||||
}
|
||||
@@ -6,27 +6,20 @@
|
||||
import { ExtHostTunnelServiceShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import * as vscode from 'vscode';
|
||||
import { RemoteTunnel } from 'vs/platform/remote/common/tunnel';
|
||||
import { RemoteTunnel, TunnelOptions } from 'vs/platform/remote/common/tunnel';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
export interface TunnelOptions {
|
||||
remote: { port: number, host: string };
|
||||
localPort?: number;
|
||||
name?: string;
|
||||
closeable?: boolean;
|
||||
}
|
||||
|
||||
export interface TunnelDto {
|
||||
remote: { port: number, host: string };
|
||||
remoteAddress: { port: number, host: string };
|
||||
localAddress: string;
|
||||
}
|
||||
|
||||
export namespace TunnelDto {
|
||||
export function fromApiTunnel(tunnel: vscode.Tunnel): TunnelDto {
|
||||
return { remote: tunnel.remote, localAddress: tunnel.localAddress };
|
||||
return { remoteAddress: tunnel.remoteAddress, localAddress: tunnel.localAddress };
|
||||
}
|
||||
export function fromServiceTunnel(tunnel: RemoteTunnel): TunnelDto {
|
||||
return { remote: { host: tunnel.tunnelRemoteHost, port: tunnel.tunnelRemotePort }, localAddress: tunnel.localAddress };
|
||||
return { remoteAddress: { host: tunnel.tunnelRemoteHost, port: tunnel.tunnelRemotePort }, localAddress: tunnel.localAddress };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +30,7 @@ export interface Tunnel extends vscode.Disposable {
|
||||
|
||||
export interface IExtHostTunnelService extends ExtHostTunnelServiceShape {
|
||||
readonly _serviceBrand: undefined;
|
||||
makeTunnel(forward: TunnelOptions): Promise<vscode.Tunnel | undefined>;
|
||||
openTunnel(forward: TunnelOptions): Promise<vscode.Tunnel | undefined>;
|
||||
setForwardPortProvider(provider: vscode.RemoteAuthorityResolver | undefined): Promise<IDisposable>;
|
||||
}
|
||||
|
||||
@@ -45,10 +38,10 @@ export const IExtHostTunnelService = createDecorator<IExtHostTunnelService>('IEx
|
||||
|
||||
export class ExtHostTunnelService implements IExtHostTunnelService {
|
||||
_serviceBrand: undefined;
|
||||
async makeTunnel(forward: TunnelOptions): Promise<vscode.Tunnel | undefined> {
|
||||
async openTunnel(forward: TunnelOptions): Promise<vscode.Tunnel | undefined> {
|
||||
return undefined;
|
||||
}
|
||||
async $findCandidatePorts(): Promise<{ port: number; detail: string; }[]> {
|
||||
async $findCandidatePorts(): Promise<{ host: string, port: number; detail: string; }[]> {
|
||||
return [];
|
||||
}
|
||||
async setForwardPortProvider(provider: vscode.RemoteAuthorityResolver | undefined): Promise<IDisposable> { return { dispose: () => { } }; }
|
||||
|
||||
@@ -2508,3 +2508,20 @@ export enum WebviewContentState {
|
||||
Unchanged = 2,
|
||||
Dirty = 3,
|
||||
}
|
||||
|
||||
|
||||
//#region Theming
|
||||
|
||||
@es5ClassCompat
|
||||
export class ColorTheme implements vscode.ColorTheme {
|
||||
constructor(public readonly kind: ColorThemeKind) {
|
||||
}
|
||||
}
|
||||
|
||||
export enum ColorThemeKind {
|
||||
Light = 1,
|
||||
Dark = 2,
|
||||
HighContrast = 3
|
||||
}
|
||||
|
||||
//#endregion Theming
|
||||
|
||||
@@ -51,6 +51,7 @@ namespace schema {
|
||||
case 'comments/commentThread/context': return MenuId.CommentThreadActions;
|
||||
case 'comments/comment/title': return MenuId.CommentTitle;
|
||||
case 'comments/comment/context': return MenuId.CommentActions;
|
||||
case 'extension/context': return MenuId.ExtensionContext;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
@@ -209,6 +210,11 @@ namespace schema {
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
'extension/context': {
|
||||
description: localize('menus.extensionContext', "The extension context menu"),
|
||||
type: 'array',
|
||||
items: menuItem
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
@@ -351,11 +357,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),
|
||||
|
||||
@@ -13,16 +13,17 @@ import { exec } from 'child_process';
|
||||
import * as resources from 'vs/base/common/resources';
|
||||
import * as fs from 'fs';
|
||||
import { isLinux } from 'vs/base/common/platform';
|
||||
import { IExtHostTunnelService, TunnelOptions, TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { IExtHostTunnelService, TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { asPromise } from 'vs/base/common/async';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { TunnelOptions } from 'vs/platform/remote/common/tunnel';
|
||||
|
||||
class ExtensionTunnel implements vscode.Tunnel {
|
||||
private _onDispose: Emitter<void> = new Emitter();
|
||||
onDispose: Event<void> = this._onDispose.event;
|
||||
onDidDispose: Event<void> = this._onDispose.event;
|
||||
|
||||
constructor(
|
||||
public readonly remote: { port: number; host: string; },
|
||||
public readonly remoteAddress: { port: number; host: string; },
|
||||
public readonly localAddress: string,
|
||||
private readonly _dispose: () => void) { }
|
||||
|
||||
@@ -48,11 +49,11 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe
|
||||
this.registerCandidateFinder();
|
||||
}
|
||||
}
|
||||
async makeTunnel(forward: TunnelOptions): Promise<vscode.Tunnel | undefined> {
|
||||
async openTunnel(forward: TunnelOptions): Promise<vscode.Tunnel | undefined> {
|
||||
const tunnel = await this._proxy.$openTunnel(forward);
|
||||
if (tunnel) {
|
||||
const disposableTunnel: vscode.Tunnel = new ExtensionTunnel(tunnel.remote, tunnel.localAddress, () => {
|
||||
return this._proxy.$closeTunnel(tunnel.remote.port);
|
||||
const disposableTunnel: vscode.Tunnel = new ExtensionTunnel(tunnel.remoteAddress, tunnel.localAddress, () => {
|
||||
return this._proxy.$closeTunnel(tunnel.remoteAddress);
|
||||
});
|
||||
this._register(disposableTunnel);
|
||||
return disposableTunnel;
|
||||
@@ -65,8 +66,8 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe
|
||||
}
|
||||
|
||||
async setForwardPortProvider(provider: vscode.RemoteAuthorityResolver | undefined): Promise<IDisposable> {
|
||||
if (provider && provider.forwardPort) {
|
||||
this._forwardPortProvider = provider.forwardPort;
|
||||
if (provider && provider.tunnelFactory) {
|
||||
this._forwardPortProvider = provider.tunnelFactory;
|
||||
await this._proxy.$setTunnelProvider();
|
||||
} else {
|
||||
this._forwardPortProvider = undefined;
|
||||
@@ -91,11 +92,11 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe
|
||||
const providedPort = this._forwardPortProvider!(tunnelOptions);
|
||||
if (providedPort !== undefined) {
|
||||
return asPromise(() => providedPort).then(tunnel => {
|
||||
if (!this._extensionTunnels.has(tunnelOptions.remote.host)) {
|
||||
this._extensionTunnels.set(tunnelOptions.remote.host, new Map());
|
||||
if (!this._extensionTunnels.has(tunnelOptions.remoteAddress.host)) {
|
||||
this._extensionTunnels.set(tunnelOptions.remoteAddress.host, new Map());
|
||||
}
|
||||
this._extensionTunnels.get(tunnelOptions.remote.host)!.set(tunnelOptions.remote.port, tunnel);
|
||||
this._register(tunnel.onDispose(() => this._proxy.$closeTunnel(tunnel.remote.port)));
|
||||
this._extensionTunnels.get(tunnelOptions.remoteAddress.host)!.set(tunnelOptions.remoteAddress.port, tunnel);
|
||||
this._register(tunnel.onDidDispose(() => this._proxy.$closeTunnel(tunnel.remoteAddress)));
|
||||
return Promise.resolve(TunnelDto.fromApiTunnel(tunnel));
|
||||
});
|
||||
}
|
||||
@@ -104,12 +105,12 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe
|
||||
}
|
||||
|
||||
|
||||
async $findCandidatePorts(): Promise<{ port: number, detail: string }[]> {
|
||||
async $findCandidatePorts(): Promise<{ host: string, port: number, detail: string }[]> {
|
||||
if (!isLinux) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const ports: { port: number, detail: string }[] = [];
|
||||
const ports: { host: string, port: number, detail: string }[] = [];
|
||||
const tcp: string = fs.readFileSync('/proc/net/tcp', 'utf8');
|
||||
const tcp6: string = fs.readFileSync('/proc/net/tcp6', 'utf8');
|
||||
const procSockets: string = await (new Promise(resolve => {
|
||||
@@ -150,7 +151,7 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe
|
||||
connections.filter((connection => socketMap[connection.socket])).forEach(({ socket, ip, port }) => {
|
||||
const command = processMap[socketMap[socket].pid].cmd;
|
||||
if (!command.match('.*\.vscode\-server\-[a-zA-Z]+\/bin.*') && (command.indexOf('out/vs/server/main.js') === -1)) {
|
||||
ports.push({ port, detail: processMap[socketMap[socket].pid].cmd });
|
||||
ports.push({ host: ip, port, detail: processMap[socketMap[socket].pid].cmd });
|
||||
}
|
||||
});
|
||||
|
||||
@@ -177,7 +178,7 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe
|
||||
const address = row.local_address.split(':');
|
||||
return {
|
||||
socket: parseInt(row.inode, 10),
|
||||
ip: address[0],
|
||||
ip: this.parseIpAddress(address[0]),
|
||||
port: parseInt(address[1], 16)
|
||||
};
|
||||
}).map(port => [port.port, port])
|
||||
@@ -185,6 +186,17 @@ export class ExtHostTunnelService extends Disposable implements IExtHostTunnelSe
|
||||
];
|
||||
}
|
||||
|
||||
private parseIpAddress(hex: string): string {
|
||||
let result = '';
|
||||
for (let i = hex.length - 2; (i >= 0); i -= 2) {
|
||||
result += parseInt(hex.substr(i, 2), 16);
|
||||
if (i !== 0) {
|
||||
result += '.';
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private loadConnectionTable(stdout: string): Record<string, string>[] {
|
||||
const lines = stdout.trim().split('\n');
|
||||
const names = lines.shift()!.trim().split(/\s+/)
|
||||
|
||||
Reference in New Issue
Block a user