Merge VS Code 1.31.1 (#4283)

This commit is contained in:
Matt Irvine
2019-03-15 13:09:45 -07:00
committed by GitHub
parent 7d31575149
commit 86bac90001
1716 changed files with 53308 additions and 48375 deletions

View File

@@ -1,216 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
import { IJSONSchema } from 'vs/base/common/jsonSchema';
import { ExtensionMessageCollector, ExtensionsRegistry, IExtensionPoint } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import * as resources from 'vs/base/common/resources';
import { createCSSRule } from 'vs/base/browser/dom';
import { Registry } from 'vs/platform/registry/common/platform';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { ViewletDescriptor, ViewletRegistry, Extensions as ViewletExtensions, ShowViewletAction } from 'vs/workbench/browser/viewlet';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IPartService } from 'vs/workbench/services/part/common/partService';
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 { IThemeService } from 'vs/platform/theme/common/themeService';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IExtensionService, IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { Extensions as ViewContainerExtensions, IViewContainersRegistry, TEST_VIEW_CONTAINER_ID } from 'vs/workbench/common/views';
import { ViewContainerViewlet } from 'vs/workbench/browser/parts/views/viewsViewlet';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { forEach } from 'vs/base/common/collections';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
import { URI } from 'vs/base/common/uri';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
export interface IUserFriendlyViewsContainerDescriptor {
id: string;
title: string;
icon: string;
}
export interface IUserFriendlyViewsContainerDescriptor2 {
id: string;
title: string;
icon: URI;
}
const viewsContainerSchema: IJSONSchema = {
type: 'object',
properties: {
id: {
description: localize({ key: 'vscode.extension.contributes.views.containers.id', comment: ['Contribution refers to those that an extension contributes to VS Code through an extension/contribution point. '] }, "Unique id used to identify the container in which views can be contributed using 'views' contribution point"),
type: 'string',
pattern: '^[a-zA-Z0-9_-]+$'
},
title: {
description: localize('vscode.extension.contributes.views.containers.title', 'Human readable string used to render the container'),
type: 'string'
},
icon: {
description: localize('vscode.extension.contributes.views.containers.icon', "Path to the container icon. Icons are 24x24 centered on a 50x40 block and have a fill color of 'rgb(215, 218, 224)' or '#d7dae0'. It is recommended that icons be in SVG, though any image file type is accepted."),
type: 'string'
}
}
};
export const viewsContainersContribution: IJSONSchema = {
description: localize('vscode.extension.contributes.viewsContainers', 'Contributes views containers to the editor'),
type: 'object',
properties: {
'activitybar': {
description: localize('views.container.activitybar', "Contribute views containers to Activity Bar"),
type: 'array',
items: viewsContainerSchema
}
}
};
export const viewsContainersExtensionPoint: IExtensionPoint<{ [loc: string]: IUserFriendlyViewsContainerDescriptor[] }> = ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: IUserFriendlyViewsContainerDescriptor[] }>('viewsContainers', [], viewsContainersContribution);
const TEST_VIEW_CONTAINER_ORDER = 6;
class ViewsContainersExtensionHandler implements IWorkbenchContribution {
constructor() {
this.registerTestViewContainer();
this.handleAndRegisterCustomViewContainers();
}
private registerTestViewContainer(): void {
const title = localize('test', "Test");
const cssClass = `extensionViewlet-test`;
const icon = URI.parse(require.toUrl('./media/test.svg'));
this.registerCustomViewlet({ id: TEST_VIEW_CONTAINER_ID, title, icon }, TEST_VIEW_CONTAINER_ORDER, cssClass, void 0);
}
private handleAndRegisterCustomViewContainers() {
let order = TEST_VIEW_CONTAINER_ORDER + 1;
viewsContainersExtensionPoint.setHandler((extensions) => {
for (let extension of extensions) {
const { value, collector } = extension;
forEach(value, entry => {
if (!this.isValidViewsContainer(entry.value, collector)) {
return;
}
switch (entry.key) {
case 'activitybar':
order = this.registerCustomViewContainers(entry.value, extension.description, order);
break;
}
});
}
});
}
private isValidViewsContainer(viewsContainersDescriptors: IUserFriendlyViewsContainerDescriptor[], collector: ExtensionMessageCollector): boolean {
if (!Array.isArray(viewsContainersDescriptors)) {
collector.error(localize('requirearray', "views containers must be an array"));
return false;
}
for (let descriptor of viewsContainersDescriptors) {
if (typeof descriptor.id !== 'string') {
collector.error(localize('requireidstring', "property `{0}` is mandatory and must be of type `string`. Only alphanumeric characters, '_', and '-' are allowed.", 'id'));
return false;
}
if (!(/^[a-z0-9_-]+$/i.test(descriptor.id))) {
collector.error(localize('requireidstring', "property `{0}` is mandatory and must be of type `string`. Only alphanumeric characters, '_', and '-' are allowed.", 'id'));
return false;
}
if (typeof descriptor.title !== 'string') {
collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'title'));
return false;
}
if (typeof descriptor.icon !== 'string') {
collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'icon'));
return false;
}
}
return true;
}
private registerCustomViewContainers(containers: IUserFriendlyViewsContainerDescriptor[], extension: IExtensionDescription, order: number): number {
containers.forEach(descriptor => {
const cssClass = `extensionViewlet-${descriptor.id}`;
const icon = resources.joinPath(extension.extensionLocation, descriptor.icon);
this.registerCustomViewlet({ id: `workbench.view.extension.${descriptor.id}`, title: descriptor.title, icon }, order++, cssClass, extension.id);
});
return order;
}
private registerCustomViewlet(descriptor: IUserFriendlyViewsContainerDescriptor2, order: number, cssClass: string, extensionId: string): void {
const viewContainersRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
const viewletRegistry = Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets);
const id = descriptor.id;
if (!viewletRegistry.getViewlet(id)) {
viewContainersRegistry.registerViewContainer(id, extensionId);
// Register as viewlet
class CustomViewlet extends ViewContainerViewlet {
constructor(
@IConfigurationService configurationService: IConfigurationService,
@IPartService partService: IPartService,
@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, `${id}.state`, true, configurationService, partService, telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService);
}
}
const viewletDescriptor = new ViewletDescriptor(
CustomViewlet,
id,
descriptor.title,
cssClass,
order,
descriptor.icon
);
viewletRegistry.registerViewlet(viewletDescriptor);
// Register Action to Open Viewlet
class OpenCustomViewletAction extends ShowViewletAction {
constructor(
id: string, label: string,
@IViewletService viewletService: IViewletService,
@IEditorGroupsService editorGroupService: IEditorGroupsService,
@IPartService partService: IPartService
) {
super(id, label, id, viewletService, editorGroupService, partService);
}
}
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
registry.registerWorkbenchAction(
new SyncActionDescriptor(OpenCustomViewletAction, id, localize('showViewlet', "Show {0}", descriptor.title)),
'View: Show {0}',
localize('view', "View")
);
// Generate CSS to show the icon in the activity bar
const iconClass = `.monaco-workbench > .activitybar .monaco-action-bar .action-label.${cssClass}`;
createCSSRule(iconClass, `-webkit-mask: url('${descriptor.icon}') no-repeat 50% 50%`);
}
}
}
const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
workbenchRegistry.registerWorkbenchContribution(ViewsContainersExtensionHandler, LifecyclePhase.Starting);

View File

@@ -6,12 +6,12 @@
import { localize } from 'vs/nls';
import { forEach } from 'vs/base/common/collections';
import { IJSONSchema } from 'vs/base/common/jsonSchema';
import { ExtensionMessageCollector, ExtensionsRegistry, IExtensionPoint } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { ViewContainer, ViewsRegistry, ICustomViewDescriptor, IViewContainersRegistry, Extensions as ViewContainerExtensions } from 'vs/workbench/common/views';
import * as resources from 'vs/base/common/resources';
import { ExtensionMessageCollector, ExtensionsRegistry, IExtensionPoint, IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { ViewContainer, ViewsRegistry, ITreeViewDescriptor, IViewContainersRegistry, Extensions as ViewContainerExtensions, TEST_VIEW_CONTAINER_ID, IViewDescriptor } from 'vs/workbench/common/views';
import { CustomTreeViewPanel, CustomTreeView } from 'vs/workbench/browser/parts/views/customView';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { coalesce, } from 'vs/base/common/arrays';
import { viewsContainersExtensionPoint } from 'vs/workbench/api/browser/viewsContainersExtensionPoint';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { Registry } from 'vs/platform/registry/common/platform';
@@ -19,6 +19,61 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import { VIEWLET_ID as EXPLORER } from 'vs/workbench/parts/files/common/files';
import { VIEWLET_ID as SCM } from 'vs/workbench/parts/scm/common/scm';
import { VIEWLET_ID as DEBUG } from 'vs/workbench/parts/debug/common/debug';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { URI } from 'vs/base/common/uri';
import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor, ShowViewletAction } from 'vs/workbench/browser/viewlet';
import { IExtensionDescription, IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { ViewContainerViewlet } from 'vs/workbench/browser/parts/views/viewsViewlet';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IPartService } from 'vs/workbench/services/part/common/partService';
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';
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { createCSSRule } from 'vs/base/browser/dom';
export interface IUserFriendlyViewsContainerDescriptor {
id: string;
title: string;
icon: string;
}
const viewsContainerSchema: IJSONSchema = {
type: 'object',
properties: {
id: {
description: localize({ key: 'vscode.extension.contributes.views.containers.id', comment: ['Contribution refers to those that an extension contributes to VS Code through an extension/contribution point. '] }, "Unique id used to identify the container in which views can be contributed using 'views' contribution point"),
type: 'string',
pattern: '^[a-zA-Z0-9_-]+$'
},
title: {
description: localize('vscode.extension.contributes.views.containers.title', 'Human readable string used to render the container'),
type: 'string'
},
icon: {
description: localize('vscode.extension.contributes.views.containers.icon', "Path to the container icon. Icons are 24x24 centered on a 50x40 block and have a fill color of 'rgb(215, 218, 224)' or '#d7dae0'. It is recommended that icons be in SVG, though any image file type is accepted."),
type: 'string'
}
}
};
export const viewsContainersContribution: IJSONSchema = {
description: localize('vscode.extension.contributes.viewsContainers', 'Contributes views containers to the editor'),
type: 'object',
properties: {
'activitybar': {
description: localize('views.container.activitybar', "Contribute views containers to Activity Bar"),
type: 'array',
items: viewsContainerSchema
}
}
};
interface IUserFriendlyViewDescriptor {
id: string;
@@ -81,69 +136,282 @@ const viewsContribution: IJSONSchema = {
}
};
export interface ICustomViewDescriptor extends ITreeViewDescriptor {
readonly extensionId: ExtensionIdentifier;
readonly originalContainerId: string;
}
const viewsExtensionPoint: IExtensionPoint<{ [loc: string]: IUserFriendlyViewDescriptor[] }> = ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: IUserFriendlyViewDescriptor[] }>('views', [viewsContainersExtensionPoint], viewsContribution);
type ViewContainerExtensionPointType = { [loc: string]: IUserFriendlyViewsContainerDescriptor[] };
// {{SQL CARBON EDIT}} - Export viewsContainersExtensionPoint
export const viewsContainersExtensionPoint: IExtensionPoint<ViewContainerExtensionPointType> = ExtensionsRegistry.registerExtensionPoint<ViewContainerExtensionPointType>({
extensionPoint: 'viewsContainers',
jsonSchema: viewsContainersContribution,
isDynamic: true
});
class ViewsContainersExtensionHandler implements IWorkbenchContribution {
type ViewExtensionPointType = { [loc: string]: IUserFriendlyViewDescriptor[] };
const viewsExtensionPoint: IExtensionPoint<ViewExtensionPointType> = ExtensionsRegistry.registerExtensionPoint<ViewExtensionPointType>({
extensionPoint: 'views',
deps: [viewsContainersExtensionPoint],
jsonSchema: viewsContribution,
isDynamic: true
});
const TEST_VIEW_CONTAINER_ORDER = 6;
class ViewsExtensionHandler implements IWorkbenchContribution {
private viewContainersRegistry: IViewContainersRegistry;
constructor(
@IInstantiationService private instantiationService: IInstantiationService
@IInstantiationService private readonly instantiationService: IInstantiationService
) {
this.viewContainersRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
this.handleAndRegisterCustomViewContainers();
this.handleAndRegisterCustomViews();
}
private handleAndRegisterCustomViews() {
viewsExtensionPoint.setHandler(extensions => {
for (let extension of extensions) {
const { value, collector } = extension;
forEach(value, entry => {
if (!this.isValidViewDescriptors(entry.value, collector)) {
return;
}
let container = this.getViewContainer(entry.key);
if (!container) {
collector.warn(localize('ViewContainerDoesnotExist', "View container '{0}' does not exist and all views registered to it will be added to 'Data Explorer'.", entry.key));
container = this.viewContainersRegistry.get(EXPLORER);
}
const registeredViews = ViewsRegistry.getViews(container);
const viewIds: string[] = [];
const viewDescriptors = coalesce(entry.value.map((item, index) => {
// validate
if (viewIds.indexOf(item.id) !== -1) {
collector.error(localize('duplicateView1', "Cannot register multiple views with same id `{0}` in the view container `{1}`", item.id, container.id));
return null;
}
if (registeredViews.some(v => v.id === item.id)) {
collector.error(localize('duplicateView2', "A view with id `{0}` is already registered in the view container `{1}`", item.id, container.id));
return null;
}
const viewDescriptor = <ICustomViewDescriptor>{
id: item.id,
name: item.name,
ctor: CustomTreeViewPanel,
container,
when: ContextKeyExpr.deserialize(item.when),
canToggleVisibility: true,
collapsed: this.showCollapsed(container),
treeView: this.instantiationService.createInstance(CustomTreeView, item.id, container),
order: extension.description.id === container.extensionId ? index + 1 : void 0
};
viewIds.push(viewDescriptor.id);
return viewDescriptor;
}));
ViewsRegistry.registerViews(viewDescriptors);
});
private handleAndRegisterCustomViewContainers() {
this.registerTestViewContainer();
viewsContainersExtensionPoint.setHandler((extensions, { added, removed }) => {
if (removed.length) {
this.removeCustomViewContainers(removed);
}
if (added.length) {
this.addCustomViewContainers(added, this.viewContainersRegistry.all);
}
});
}
private addCustomViewContainers(extensionPoints: IExtensionPointUser<ViewContainerExtensionPointType>[], existingViewContainers: ViewContainer[]): void {
const viewContainersRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
let order = TEST_VIEW_CONTAINER_ORDER + viewContainersRegistry.all.filter(v => !!v.extensionId).length + 1;
for (let { value, collector, description } of extensionPoints) {
forEach(value, entry => {
if (!this.isValidViewsContainer(entry.value, collector)) {
return;
}
switch (entry.key) {
case 'activitybar':
order = this.registerCustomViewContainers(entry.value, description, order, existingViewContainers);
break;
}
});
}
}
private removeCustomViewContainers(extensionPoints: IExtensionPointUser<ViewContainerExtensionPointType>[]): void {
const viewContainersRegistry = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry);
const removedExtensions: Set<string> = extensionPoints.reduce((result, e) => { result.add(ExtensionIdentifier.toKey(e.description.identifier)); return result; }, new Set<string>());
for (const viewContainer of viewContainersRegistry.all) {
if (viewContainer.extensionId && removedExtensions.has(ExtensionIdentifier.toKey(viewContainer.extensionId))) {
// move only those views that do not belong to the removed extension
const views = ViewsRegistry.getViews(viewContainer).filter((view: ICustomViewDescriptor) => !removedExtensions.has(ExtensionIdentifier.toKey(view.extensionId)));
if (views.length) {
ViewsRegistry.moveViews(views, this.getDefaultViewContainer());
}
this.deregisterCustomViewContainer(viewContainer);
}
}
}
private registerTestViewContainer(): void {
const title = localize('test', "Test");
const cssClass = `extensionViewlet-test`;
const icon = URI.parse(require.toUrl('./media/test.svg'));
this.registerCustomViewContainer(TEST_VIEW_CONTAINER_ID, title, icon, TEST_VIEW_CONTAINER_ORDER, cssClass, undefined);
}
private isValidViewsContainer(viewsContainersDescriptors: IUserFriendlyViewsContainerDescriptor[], collector: ExtensionMessageCollector): boolean {
if (!Array.isArray(viewsContainersDescriptors)) {
collector.error(localize('viewcontainer requirearray', "views containers must be an array"));
return false;
}
for (let descriptor of viewsContainersDescriptors) {
if (typeof descriptor.id !== 'string') {
collector.error(localize('requireidstring', "property `{0}` is mandatory and must be of type `string`. Only alphanumeric characters, '_', and '-' are allowed.", 'id'));
return false;
}
if (!(/^[a-z0-9_-]+$/i.test(descriptor.id))) {
collector.error(localize('requireidstring', "property `{0}` is mandatory and must be of type `string`. Only alphanumeric characters, '_', and '-' are allowed.", 'id'));
return false;
}
if (typeof descriptor.title !== 'string') {
collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'title'));
return false;
}
if (typeof descriptor.icon !== 'string') {
collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'icon'));
return false;
}
}
return true;
}
private registerCustomViewContainers(containers: IUserFriendlyViewsContainerDescriptor[], extension: IExtensionDescription, order: number, existingViewContainers: ViewContainer[]): number {
containers.forEach(descriptor => {
const cssClass = `extensionViewlet-${descriptor.id}`;
const icon = resources.joinPath(extension.extensionLocation, descriptor.icon);
const id = `workbench.view.extension.${descriptor.id}`;
const viewContainer = this.registerCustomViewContainer(id, descriptor.title, icon, order++, cssClass, extension.identifier);
// Move those views that belongs to this container
if (existingViewContainers.length) {
const viewsToMove: IViewDescriptor[] = [];
for (const existingViewContainer of existingViewContainers) {
if (viewContainer !== existingViewContainer) {
viewsToMove.push(...ViewsRegistry.getViews(existingViewContainer).filter((view: ICustomViewDescriptor) => view.originalContainerId === descriptor.id));
}
}
if (viewsToMove.length) {
ViewsRegistry.moveViews(viewsToMove, viewContainer);
}
}
});
return order;
}
private registerCustomViewContainer(id: string, title: string, icon: URI, order: number, cssClass: string, extensionId: ExtensionIdentifier | undefined): ViewContainer {
let viewContainer = this.viewContainersRegistry.get(id);
if (!viewContainer) {
viewContainer = this.viewContainersRegistry.registerViewContainer(id, extensionId);
// Register as viewlet
class CustomViewlet extends ViewContainerViewlet {
constructor(
@IConfigurationService configurationService: IConfigurationService,
@IPartService partService: IPartService,
@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, `${id}.state`, true, configurationService, partService, telemetryService, storageService, instantiationService, themeService, contextMenuService, extensionService, contextService);
}
}
const viewletDescriptor = new ViewletDescriptor(
CustomViewlet,
id,
title,
cssClass,
order,
icon
);
Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets).registerViewlet(viewletDescriptor);
// Register Action to Open Viewlet
class OpenCustomViewletAction extends ShowViewletAction {
constructor(
id: string, label: string,
@IViewletService viewletService: IViewletService,
@IEditorGroupsService editorGroupService: IEditorGroupsService,
@IPartService partService: IPartService
) {
super(id, label, id, viewletService, editorGroupService, partService);
}
}
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
registry.registerWorkbenchAction(
new SyncActionDescriptor(OpenCustomViewletAction, id, localize('showViewlet', "Show {0}", title)),
'View: Show {0}',
localize('view', "View")
);
// Generate CSS to show the icon in the activity bar
const iconClass = `.monaco-workbench .activitybar .monaco-action-bar .action-label.${cssClass}`;
createCSSRule(iconClass, `-webkit-mask: url('${icon}') no-repeat 50% 50%`);
}
return viewContainer;
}
private deregisterCustomViewContainer(viewContainer: ViewContainer): void {
this.viewContainersRegistry.deregisterViewContainer(viewContainer);
Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets).deregisterViewlet(viewContainer.id);
}
private handleAndRegisterCustomViews() {
viewsExtensionPoint.setHandler((extensions, { added, removed }) => {
if (removed.length) {
this.removeViews(removed);
}
if (added.length) {
this.addViews(added);
}
});
}
private addViews(extensions: IExtensionPointUser<ViewExtensionPointType>[]): void {
for (const extension of extensions) {
const { value, collector } = extension;
forEach(value, entry => {
if (!this.isValidViewDescriptors(entry.value, collector)) {
return;
}
let container = this.getViewContainer(entry.key);
if (!container) {
collector.warn(localize('ViewContainerDoesnotExist', "View container '{0}' does not exist and all views registered to it will be added to 'Explorer'.", entry.key));
container = this.getDefaultViewContainer();
}
const registeredViews = ViewsRegistry.getViews(container);
const viewIds: string[] = [];
const viewDescriptors = coalesce(entry.value.map((item, index) => {
// validate
if (viewIds.indexOf(item.id) !== -1) {
collector.error(localize('duplicateView1', "Cannot register multiple views with same id `{0}` in the view container `{1}`", item.id, container.id));
return null;
}
if (registeredViews.some(v => v.id === item.id)) {
collector.error(localize('duplicateView2', "A view with id `{0}` is already registered in the view container `{1}`", item.id, container.id));
return null;
}
const viewDescriptor = <ICustomViewDescriptor>{
id: item.id,
name: item.name,
ctor: CustomTreeViewPanel,
when: ContextKeyExpr.deserialize(item.when),
canToggleVisibility: true,
collapsed: this.showCollapsed(container),
treeView: this.instantiationService.createInstance(CustomTreeView, item.id, container),
order: ExtensionIdentifier.equals(extension.description.identifier, container.extensionId) ? index + 1 : undefined,
extensionId: extension.description.identifier,
originalContainerId: entry.key
};
viewIds.push(viewDescriptor.id);
return viewDescriptor;
}));
ViewsRegistry.registerViews(viewDescriptors, container);
});
}
}
private getDefaultViewContainer(): ViewContainer {
return this.viewContainersRegistry.get(EXPLORER);
}
private removeViews(extensions: IExtensionPointUser<ViewExtensionPointType>[]): void {
const removedExtensions: Set<string> = extensions.reduce((result, e) => { result.add(ExtensionIdentifier.toKey(e.description.identifier)); return result; }, new Set<string>());
for (const viewContainer of this.viewContainersRegistry.all) {
const removedViews = ViewsRegistry.getViews(viewContainer).filter((v: ICustomViewDescriptor) => v.extensionId && removedExtensions.has(ExtensionIdentifier.toKey(v.extensionId)));
if (removedViews.length) {
ViewsRegistry.deregisterViews(removedViews, viewContainer);
}
}
}
private isValidViewDescriptors(viewDescriptors: IUserFriendlyViewDescriptor[], collector: ExtensionMessageCollector): boolean {
if (!Array.isArray(viewDescriptors)) {
collector.error(localize('requirearray', "views must be an array"));
@@ -168,7 +436,6 @@ class ViewsContainersExtensionHandler implements IWorkbenchContribution {
return true;
}
private getViewContainer(value: string): ViewContainer {
switch (value) {
case 'explorer': return this.viewContainersRegistry.get(EXPLORER);
@@ -190,4 +457,4 @@ class ViewsContainersExtensionHandler implements IWorkbenchContribution {
}
const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
workbenchRegistry.registerWorkbenchContribution(ViewsContainersExtensionHandler, LifecyclePhase.Starting);
workbenchRegistry.registerWorkbenchContribution(ViewsExtensionHandler, LifecyclePhase.Starting);

View File

@@ -0,0 +1,303 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
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 { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
import { workspaceSettingsSchemaId, launchSchemaId } from 'vs/workbench/services/configuration/common/configuration';
import { isObject } from 'vs/base/common/types';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
const configurationRegistry = Registry.as<IConfigurationRegistry>(Extensions.Configuration);
const configurationEntrySchema: IJSONSchema = {
type: 'object',
defaultSnippets: [{ body: { title: '', properties: {} } }],
properties: {
title: {
description: nls.localize('vscode.extension.contributes.configuration.title', 'A summary of the settings. This label will be used in the settings file as separating comment.'),
type: 'string'
},
properties: {
description: nls.localize('vscode.extension.contributes.configuration.properties', 'Description of the configuration properties.'),
type: 'object',
additionalProperties: {
anyOf: [
{ $ref: 'http://json-schema.org/draft-07/schema#' },
{
type: 'object',
properties: {
isExecutable: {
type: 'boolean',
deprecationMessage: 'This property is deprecated. Instead use `scope` property and set it to `application` value.'
},
scope: {
type: 'string',
enum: ['application', 'window', 'resource'],
default: 'window',
enumDescriptions: [
nls.localize('scope.application.description', "Application specific configuration, which can be configured only in User settings."),
nls.localize('scope.window.description', "Window specific configuration, which can be configured in the User or Workspace settings."),
nls.localize('scope.resource.description', "Resource specific configuration, which can be configured in the User, Workspace or Folder settings.")
],
description: nls.localize('scope.description', "Scope in which the configuration is applicable. Available scopes are `window` and `resource`.")
},
enumDescriptions: {
type: 'array',
items: {
type: 'string',
},
description: nls.localize('scope.enumDescriptions', 'Descriptions for enum values')
},
markdownEnumDescription: {
type: 'array',
items: {
type: 'string',
},
description: nls.localize('scope.markdownEnumDescription', 'Descriptions for enum values in the markdown format.')
},
markdownDescription: {
type: 'string',
description: nls.localize('scope.markdownDescription', 'The description in the markdown format.')
},
deprecationMessage: {
type: 'string',
description: nls.localize('scope.deprecationMessage', 'If set, the property is marked as deprecated and the given message is shown as an explanation.')
}
}
}
]
}
}
}
};
// BEGIN VSCode extension point `configurationDefaults`
const defaultConfigurationExtPoint = ExtensionsRegistry.registerExtensionPoint<IConfigurationNode>({
extensionPoint: 'configurationDefaults',
jsonSchema: {
description: nls.localize('vscode.extension.contributes.defaultConfiguration', 'Contributes default editor configuration settings by language.'),
type: 'object',
patternProperties: {
'\\[.*\\]$': {
type: 'object',
default: {},
$ref: editorConfigurationSchemaId,
}
}
},
isDynamic: true
});
defaultConfigurationExtPoint.setHandler((extensions, { added, removed }) => {
if (removed.length) {
const removedDefaultConfigurations: IDefaultConfigurationExtension[] = removed.map(extension => {
const id = extension.description.identifier;
const name = extension.description.name;
const defaults = objects.deepClone(extension.value);
return <IDefaultConfigurationExtension>{
id, name, defaults
};
});
configurationRegistry.deregisterDefaultConfigurations(removedDefaultConfigurations);
}
if (added.length) {
const addedDefaultConfigurations = added.map(extension => {
const id = extension.description.identifier;
const name = extension.description.name;
const defaults = objects.deepClone(extension.value);
return <IDefaultConfigurationExtension>{
id, name, defaults
};
});
configurationRegistry.registerDefaultConfigurations(addedDefaultConfigurations);
}
});
// END VSCode extension point `configurationDefaults`
// BEGIN VSCode extension point `configuration`
const configurationExtPoint = ExtensionsRegistry.registerExtensionPoint<IConfigurationNode>({
extensionPoint: 'configuration',
deps: [defaultConfigurationExtPoint],
jsonSchema: {
description: nls.localize('vscode.extension.contributes.configuration', 'Contributes configuration settings.'),
oneOf: [
configurationEntrySchema,
{
type: 'array',
items: configurationEntrySchema
}
]
},
isDynamic: true
});
const extensionConfigurations: Map<string, IConfigurationNode[]> = new Map<string, IConfigurationNode[]>();
configurationExtPoint.setHandler((extensions, { added, removed }) => {
if (removed.length) {
const removedConfigurations: IConfigurationNode[] = [];
for (const extension of removed) {
const key = ExtensionIdentifier.toKey(extension.description.identifier);
removedConfigurations.push(...(extensionConfigurations.get(key) || []));
extensionConfigurations.delete(key);
}
configurationRegistry.deregisterConfigurations(removedConfigurations);
}
function handleConfiguration(node: IConfigurationNode, extension: IExtensionPointUser<any>): IConfigurationNode[] {
const configurations: IConfigurationNode[] = [];
let configuration = objects.deepClone(node);
if (configuration.title && (typeof configuration.title !== 'string')) {
extension.collector.error(nls.localize('invalid.title', "'configuration.title' must be a string"));
}
validateProperties(configuration, extension);
configuration.id = node.id || extension.description.identifier.value;
configuration.contributedByExtension = true;
configuration.title = configuration.title || extension.description.displayName || extension.description.identifier.value;
configurations.push(configuration);
return configurations;
}
if (added.length) {
const addedConfigurations: IConfigurationNode[] = [];
for (let extension of added) {
const configurations: IConfigurationNode[] = [];
const value = <IConfigurationNode | IConfigurationNode[]>extension.value;
if (!Array.isArray(value)) {
configurations.push(...handleConfiguration(value, extension));
} else {
value.forEach(v => configurations.push(...handleConfiguration(v, extension)));
}
extensionConfigurations.set(ExtensionIdentifier.toKey(extension.description.identifier), configurations);
addedConfigurations.push(...configurations);
}
configurationRegistry.registerConfigurations(addedConfigurations, false);
}
});
// END VSCode extension point `configuration`
function validateProperties(configuration: IConfigurationNode, extension: IExtensionPointUser<any>): void {
let properties = configuration.properties;
if (properties) {
if (typeof properties !== 'object') {
extension.collector.error(nls.localize('invalid.properties', "'configuration.properties' must be an object"));
configuration.properties = {};
}
for (let key in properties) {
const message = validateProperty(key);
if (message) {
delete properties[key];
extension.collector.warn(message);
continue;
}
const propertyConfiguration = properties[key];
if (!isObject(propertyConfiguration)) {
delete properties[key];
extension.collector.error(nls.localize('invalid.property', "'configuration.property' must be an object"));
continue;
}
if (propertyConfiguration.scope) {
if (propertyConfiguration.scope.toString() === 'application') {
propertyConfiguration.scope = ConfigurationScope.APPLICATION;
} else if (propertyConfiguration.scope.toString() === 'resource') {
propertyConfiguration.scope = ConfigurationScope.RESOURCE;
} else {
propertyConfiguration.scope = ConfigurationScope.WINDOW;
}
} else {
propertyConfiguration.scope = ConfigurationScope.WINDOW;
}
}
}
let subNodes = configuration.allOf;
if (subNodes) {
extension.collector.error(nls.localize('invalid.allOf', "'configuration.allOf' is deprecated and should no longer be used. Instead, pass multiple configuration sections as an array to the 'configuration' contribution point."));
for (let node of subNodes) {
validateProperties(node, extension);
}
}
}
const jsonRegistry = Registry.as<IJSONContributionRegistry>(JSONExtensions.JSONContribution);
jsonRegistry.registerSchema('vscode://schemas/workspaceConfig', {
allowComments: true,
default: {
folders: [
{
path: ''
}
],
settings: {
}
},
required: ['folders'],
properties: {
'folders': {
minItems: 0,
uniqueItems: true,
description: nls.localize('workspaceConfig.folders.description', "List of folders to be loaded in the workspace."),
items: {
type: 'object',
default: { path: '' },
oneOf: [{
properties: {
path: {
type: 'string',
description: nls.localize('workspaceConfig.path.description', "A file path. e.g. `/root/folderA` or `./folderA` for a relative path that will be resolved against the location of the workspace file.")
},
name: {
type: 'string',
description: nls.localize('workspaceConfig.name.description', "An optional name for the folder. ")
}
},
required: ['path']
}, {
properties: {
uri: {
type: 'string',
description: nls.localize('workspaceConfig.uri.description', "URI of the folder")
},
name: {
type: 'string',
description: nls.localize('workspaceConfig.name.description', "An optional name for the folder. ")
}
},
required: ['uri']
}]
}
},
'settings': {
type: 'object',
default: {},
description: nls.localize('workspaceConfig.settings.description', "Workspace settings"),
$ref: workspaceSettingsSchemaId
},
'launch': {
type: 'object',
default: { configurations: [], compounds: [] },
description: nls.localize('workspaceConfig.launch.description', "Workspace launch configurations"),
$ref: launchSchemaId
},
'extensions': {
type: 'object',
default: {},
description: nls.localize('workspaceConfig.extensions.description', "Workspace extensions"),
$ref: 'vscode://schemas/extensions'
}
},
additionalProperties: false,
errorMessage: nls.localize('unknownWorkspaceProperty', "Unknown workspace configuration property")
});

View File

@@ -0,0 +1,398 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
import { isFalsyOrWhitespace } from 'vs/base/common/strings';
import * as resources from 'vs/base/common/resources';
import { IJSONSchema } from 'vs/base/common/jsonSchema';
import { forEach } from 'vs/base/common/collections';
import { IExtensionPointUser, ExtensionMessageCollector, ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { MenuId, MenuRegistry, ILocalizedString, IMenuItem } from 'vs/platform/actions/common/actions';
import { URI } from 'vs/base/common/uri';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
namespace schema {
// --- menus contribution point
export interface IUserFriendlyMenuItem {
command: string;
alt?: string;
when?: string;
group?: string;
}
export function parseMenuId(value: string): MenuId | undefined {
switch (value) {
case 'commandPalette': return MenuId.CommandPalette;
case 'touchBar': return MenuId.TouchBarContext;
case 'editor/title': return MenuId.EditorTitle;
case 'editor/context': return MenuId.EditorContext;
case 'explorer/context': return MenuId.ExplorerContext;
case 'editor/title/context': return MenuId.EditorTitleContext;
case 'debug/callstack/context': return MenuId.DebugCallStackContext;
case 'scm/title': return MenuId.SCMTitle;
case 'scm/sourceControl': return MenuId.SCMSourceControl;
case 'scm/resourceGroup/context': return MenuId.SCMResourceGroupContext;
case 'scm/resourceState/context': return MenuId.SCMResourceContext;
case 'scm/change/title': return MenuId.SCMChangeContext;
case 'view/title': return MenuId.ViewTitle;
case 'view/item/context': return MenuId.ViewItemContext;
// {{SQL CARBON EDIT}}
case 'objectExplorer/item/context': return MenuId.ObjectExplorerItemContext;
case 'notebook/toolbar': return MenuId.NotebookToolbar;
case 'dataExplorer/context': return MenuId.DataExplorerContext;
}
return undefined;
}
export function isValidMenuItems(menu: IUserFriendlyMenuItem[], collector: ExtensionMessageCollector): boolean {
if (!Array.isArray(menu)) {
collector.error(localize('requirearray', "menu items must be an array"));
return false;
}
for (let item of menu) {
if (typeof item.command !== 'string') {
collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'command'));
return false;
}
if (item.alt && typeof item.alt !== 'string') {
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'alt'));
return false;
}
if (item.when && typeof item.when !== 'string') {
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'when'));
return false;
}
if (item.group && typeof item.group !== 'string') {
collector.error(localize('optstring', "property `{0}` can be omitted or must be of type `string`", 'group'));
return false;
}
}
return true;
}
const menuItem: IJSONSchema = {
type: 'object',
properties: {
command: {
description: localize('vscode.extension.contributes.menuItem.command', 'Identifier of the command to execute. The command must be declared in the \'commands\'-section'),
type: 'string'
},
alt: {
description: localize('vscode.extension.contributes.menuItem.alt', 'Identifier of an alternative command to execute. The command must be declared in the \'commands\'-section'),
type: 'string'
},
when: {
description: localize('vscode.extension.contributes.menuItem.when', 'Condition which must be true to show this item'),
type: 'string'
},
group: {
description: localize('vscode.extension.contributes.menuItem.group', 'Group into which this command belongs'),
type: 'string'
}
}
};
export const menusContribtion: IJSONSchema = {
description: localize('vscode.extension.contributes.menus', "Contributes menu items to the editor"),
type: 'object',
properties: {
'commandPalette': {
description: localize('menus.commandPalette', "The Command Palette"),
type: 'array',
items: menuItem
},
'touchBar': {
description: localize('menus.touchBar', "The touch bar (macOS only)"),
type: 'array',
items: menuItem
},
'editor/title': {
description: localize('menus.editorTitle', "The editor title menu"),
type: 'array',
items: menuItem
},
'editor/context': {
description: localize('menus.editorContext', "The editor context menu"),
type: 'array',
items: menuItem
},
'explorer/context': {
description: localize('menus.explorerContext', "The file explorer context menu"),
type: 'array',
items: menuItem
},
'editor/title/context': {
description: localize('menus.editorTabContext', "The editor tabs context menu"),
type: 'array',
items: menuItem
},
'debug/callstack/context': {
description: localize('menus.debugCallstackContext', "The debug callstack context menu"),
type: 'array',
items: menuItem
},
'scm/title': {
description: localize('menus.scmTitle', "The Source Control title menu"),
type: 'array',
items: menuItem
},
'scm/sourceControl': {
description: localize('menus.scmSourceControl', "The Source Control menu"),
type: 'array',
items: menuItem
},
'scm/resourceGroup/context': {
description: localize('menus.resourceGroupContext', "The Source Control resource group context menu"),
type: 'array',
items: menuItem
},
'scm/resourceState/context': {
description: localize('menus.resourceStateContext', "The Source Control resource state context menu"),
type: 'array',
items: menuItem
},
'view/title': {
description: localize('view.viewTitle', "The contributed view title menu"),
type: 'array',
items: menuItem
},
'view/item/context': {
description: localize('view.itemContext', "The contributed view item context menu"),
type: 'array',
items: menuItem
}
}
};
// --- commands contribution point
export interface IUserFriendlyCommand {
command: string;
title: string | ILocalizedString;
category?: string | ILocalizedString;
icon?: IUserFriendlyIcon;
}
export type IUserFriendlyIcon = string | { light: string; dark: string; };
export function isValidCommand(command: IUserFriendlyCommand, collector: ExtensionMessageCollector): boolean {
if (!command) {
collector.error(localize('nonempty', "expected non-empty value."));
return false;
}
if (isFalsyOrWhitespace(command.command)) {
collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", 'command'));
return false;
}
if (!isValidLocalizedString(command.title, collector, 'title')) {
return false;
}
if (command.category && !isValidLocalizedString(command.category, collector, 'category')) {
return false;
}
if (!isValidIcon(command.icon, collector)) {
return false;
}
return true;
}
function isValidIcon(icon: IUserFriendlyIcon | undefined, collector: ExtensionMessageCollector): boolean {
if (typeof icon === 'undefined') {
return true;
}
if (typeof icon === 'string') {
return true;
} else if (typeof icon.dark === 'string' && typeof icon.light === 'string') {
return true;
}
collector.error(localize('opticon', "property `icon` can be omitted or must be either a string or a literal like `{dark, light}`"));
return false;
}
function isValidLocalizedString(localized: string | ILocalizedString, collector: ExtensionMessageCollector, propertyName: string): boolean {
if (typeof localized === 'undefined') {
collector.error(localize('requireStringOrObject', "property `{0}` is mandatory and must be of type `string` or `object`", propertyName));
return false;
} else if (typeof localized === 'string' && isFalsyOrWhitespace(localized)) {
collector.error(localize('requirestring', "property `{0}` is mandatory and must be of type `string`", propertyName));
return false;
} else if (typeof localized !== 'string' && (isFalsyOrWhitespace(localized.original) || isFalsyOrWhitespace(localized.value))) {
collector.error(localize('requirestrings', "properties `{0}` and `{1}` are mandatory and must be of type `string`", `${propertyName}.value`, `${propertyName}.original`));
return false;
}
return true;
}
const commandType: IJSONSchema = {
type: 'object',
required: ['command', 'title'],
properties: {
command: {
description: localize('vscode.extension.contributes.commandType.command', 'Identifier of the command to execute'),
type: 'string'
},
title: {
description: localize('vscode.extension.contributes.commandType.title', 'Title by which the command is represented in the UI'),
type: 'string'
},
category: {
description: localize('vscode.extension.contributes.commandType.category', '(Optional) Category string by the command is grouped in the UI'),
type: 'string'
},
icon: {
description: localize('vscode.extension.contributes.commandType.icon', '(Optional) Icon which is used to represent the command in the UI. Either a file path or a themable configuration'),
anyOf: [{
type: 'string'
},
{
type: 'object',
properties: {
light: {
description: localize('vscode.extension.contributes.commandType.icon.light', 'Icon path when a light theme is used'),
type: 'string'
},
dark: {
description: localize('vscode.extension.contributes.commandType.icon.dark', 'Icon path when a dark theme is used'),
type: 'string'
}
}
}]
}
}
};
export const commandsContribution: IJSONSchema = {
description: localize('vscode.extension.contributes.commands', "Contributes commands to the command palette."),
oneOf: [
commandType,
{
type: 'array',
items: commandType
}
]
};
}
let _commandRegistrations: IDisposable[] = [];
ExtensionsRegistry.registerExtensionPoint<schema.IUserFriendlyCommand | schema.IUserFriendlyCommand[]>({
extensionPoint: 'commands',
jsonSchema: schema.commandsContribution,
isDynamic: true
}).setHandler(extensions => {
function handleCommand(userFriendlyCommand: schema.IUserFriendlyCommand, extension: IExtensionPointUser<any>, disposables: IDisposable[]) {
if (!schema.isValidCommand(userFriendlyCommand, extension.collector)) {
return;
}
const { icon, category, title, command } = userFriendlyCommand;
let absoluteIcon: { dark: URI; light?: URI; } | undefined;
if (icon) {
if (typeof icon === 'string') {
absoluteIcon = { dark: resources.joinPath(extension.description.extensionLocation, icon) };
} else {
absoluteIcon = {
dark: resources.joinPath(extension.description.extensionLocation, icon.dark),
light: resources.joinPath(extension.description.extensionLocation, icon.light)
};
}
}
if (MenuRegistry.getCommand(command)) {
extension.collector.info(localize('dup', "Command `{0}` appears multiple times in the `commands` section.", userFriendlyCommand.command));
}
const registration = MenuRegistry.addCommand({ id: command, title, category, iconLocation: absoluteIcon });
disposables.push(registration);
}
// remove all previous command registrations
_commandRegistrations = dispose(_commandRegistrations);
for (let extension of extensions) {
const { value } = extension;
if (Array.isArray<schema.IUserFriendlyCommand>(value)) {
for (let command of value) {
handleCommand(command, extension, _commandRegistrations);
}
} else {
handleCommand(value, extension, _commandRegistrations);
}
}
});
let _menuRegistrations: IDisposable[] = [];
ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: schema.IUserFriendlyMenuItem[] }>({
extensionPoint: 'menus',
jsonSchema: schema.menusContribtion,
isDynamic: true
}).setHandler(extensions => {
// remove all previous menu registrations
_menuRegistrations = dispose(_menuRegistrations);
for (let extension of extensions) {
const { value, collector } = extension;
forEach(value, entry => {
if (!schema.isValidMenuItems(entry.value, collector)) {
return;
}
const menu = schema.parseMenuId(entry.key);
if (typeof menu !== 'number') {
collector.warn(localize('menuId.invalid', "`{0}` is not a valid menu identifier", entry.key));
return;
}
for (let item of entry.value) {
let command = MenuRegistry.getCommand(item.command);
let alt = item.alt && MenuRegistry.getCommand(item.alt);
if (!command) {
collector.error(localize('missing.command', "Menu item references a command `{0}` which is not defined in the 'commands' section.", item.command));
continue;
}
if (item.alt && !alt) {
collector.warn(localize('missing.altCommand', "Menu item references an alt-command `{0}` which is not defined in the 'commands' section.", item.alt));
}
if (item.command === item.alt) {
collector.info(localize('dupe.command', "Menu item references the same command as default and alt-command"));
}
let group: string | undefined;
let order: number | undefined;
if (item.group) {
const idx = item.group.lastIndexOf('@');
if (idx > 0) {
group = item.group.substr(0, idx);
order = Number(item.group.substr(idx + 1)) || undefined;
} else {
group = item.group;
}
}
const registration = MenuRegistry.appendMenuItem(menu, {
command,
alt,
group,
order,
when: ContextKeyExpr.deserialize(item.when)
} as IMenuItem);
_menuRegistrations.push(registration);
}
});
}
});

View File

@@ -18,10 +18,10 @@ import 'vs/workbench/api/node/apiCommands';
import './mainThreadClipboard';
import './mainThreadCommands';
import './mainThreadConfiguration';
import './mainThreadConsole';
// {{SQL CARBON EDIT}}
// disable the debug service
// import './mainThreadDebugService';
import './mainThreadDecorations';
import './mainThreadDiagnostics';
import './mainThreadDialogs';
@@ -60,7 +60,7 @@ import './mainThreadWorkspace';
export class ExtensionPoints implements IWorkbenchContribution {
constructor(
@IInstantiationService private instantiationService: IInstantiationService
@IInstantiationService private readonly instantiationService: IInstantiationService
) {
// Classes that handle extension points...
this.instantiationService.createInstance(JSONValidationExtensionPoint);

View File

@@ -32,7 +32,7 @@ export class MainThreadCommands implements MainThreadCommandsShape {
this._generateCommandsDocumentationRegistration.dispose();
}
private _generateCommandsDocumentation(): Thenable<void> {
private _generateCommandsDocumentation(): Promise<void> {
return this._proxy.$getContributedCommandHandlerDescriptions().then(result => {
// add local commands
const commands = CommandsRegistry.getCommands();
@@ -70,14 +70,14 @@ export class MainThreadCommands implements MainThreadCommandsShape {
}
}
$executeCommand<T>(id: string, args: any[]): Thenable<T> {
$executeCommand<T>(id: string, args: any[]): Promise<T> {
for (let i = 0; i < args.length; i++) {
args[i] = revive(args[i], 0);
}
return this._commandService.executeCommand<T>(id, ...args);
}
$getCommands(): Thenable<string[]> {
$getCommands(): Promise<string[]> {
return Promise.resolve(Object.keys(CommandsRegistry.getCommands()));
}
}

View File

@@ -12,11 +12,16 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import { ExtHostCommentsShape, ExtHostContext, IExtHostContext, MainContext, MainThreadCommentsShape, CommentProviderFeatures } from '../node/extHost.protocol';
import { ICommentService } from 'vs/workbench/parts/comments/electron-browser/commentService';
import { COMMENTS_PANEL_ID } from 'vs/workbench/parts/comments/electron-browser/commentsPanel';
import { COMMENTS_PANEL_ID, CommentsPanel, COMMENTS_PANEL_TITLE } from 'vs/workbench/parts/comments/electron-browser/commentsPanel';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
import { URI } from 'vs/base/common/uri';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { generateUuid } from 'vs/base/common/uuid';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ICommentsConfiguration } from 'vs/workbench/parts/comments/electron-browser/comments.contribution';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { Registry } from 'vs/platform/registry/common/platform';
import { PanelRegistry, Extensions as PanelExtensions, PanelDescriptor } from 'vs/workbench/browser/panel';
export class MainThreadDocumentCommentProvider implements modes.DocumentCommentProvider {
private _proxy: ExtHostCommentsShape;
@@ -25,6 +30,7 @@ export class MainThreadDocumentCommentProvider implements modes.DocumentCommentP
get startDraftLabel(): string { return this._features.startDraftLabel; }
get deleteDraftLabel(): string { return this._features.deleteDraftLabel; }
get finishDraftLabel(): string { return this._features.finishDraftLabel; }
get reactionGroup(): modes.CommentReaction[] { return this._features.reactionGroup; }
constructor(proxy: ExtHostCommentsShape, handle: number, features: CommentProviderFeatures) {
this._proxy = proxy;
@@ -52,15 +58,22 @@ export class MainThreadDocumentCommentProvider implements modes.DocumentCommentP
return this._proxy.$deleteComment(this._handle, uri, comment);
}
async startDraft(token): Promise<void> {
return this._proxy.$startDraft(this._handle);
async startDraft(uri, token): Promise<void> {
return this._proxy.$startDraft(this._handle, uri);
}
async deleteDraft(token): Promise<void> {
return this._proxy.$deleteDraft(this._handle);
async deleteDraft(uri, token): Promise<void> {
return this._proxy.$deleteDraft(this._handle, uri);
}
async finishDraft(token): Promise<void> {
return this._proxy.$finishDraft(this._handle);
async finishDraft(uri, token): Promise<void> {
return this._proxy.$finishDraft(this._handle, uri);
}
async addReaction(uri, comment: modes.Comment, reaction: modes.CommentReaction, token): Promise<void> {
return this._proxy.$addReaction(this._handle, uri, comment, reaction);
}
async deleteReaction(uri, comment: modes.Comment, reaction: modes.CommentReaction, token): Promise<void> {
return this._proxy.$deleteReaction(this._handle, uri, comment, reaction);
}
onDidChangeCommentThreads = null;
}
@@ -72,18 +85,18 @@ export class MainThreadComments extends Disposable implements MainThreadComments
private _documentProviders = new Map<number, IDisposable>();
private _workspaceProviders = new Map<number, IDisposable>();
private _handlers = new Map<number, string>();
private _firstSessionStart: boolean;
private _openPanelListener: IDisposable | null;
constructor(
extHostContext: IExtHostContext,
@IEditorService private _editorService: IEditorService,
@ICommentService private _commentService: ICommentService,
@IPanelService private _panelService: IPanelService,
@ITelemetryService private _telemetryService: ITelemetryService
@IEditorService private readonly _editorService: IEditorService,
@ICommentService private readonly _commentService: ICommentService,
@IPanelService private readonly _panelService: IPanelService,
@ITelemetryService private readonly _telemetryService: ITelemetryService,
@IConfigurationService private readonly _configurationService: IConfigurationService
) {
super();
this._disposables = [];
this._firstSessionStart = true;
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostComments);
}
@@ -97,19 +110,67 @@ export class MainThreadComments extends Disposable implements MainThreadComments
this._commentService.registerDataProvider(providerId, handler);
}
$registerWorkspaceCommentProvider(handle: number, extensionId: string): void {
/**
* If the comments panel has never been opened, the constructor for it has not yet run so it has
* no listeners for comment threads being set or updated. Listen for the panel opening for the
* first time and send it comments then.
*/
private registerOpenPanelListener(commentsPanelAlreadyConstructed: boolean) {
if (!commentsPanelAlreadyConstructed && !this._openPanelListener) {
this._openPanelListener = this._panelService.onDidPanelOpen(e => {
if (e.panel.getId() === COMMENTS_PANEL_ID) {
keys(this._workspaceProviders).forEach(handle => {
this._proxy.$provideWorkspaceComments(handle).then(commentThreads => {
if (commentThreads) {
const providerId = this._handlers.get(handle);
this._commentService.setWorkspaceComments(providerId, commentThreads);
}
});
});
this._openPanelListener.dispose();
this._openPanelListener = null;
}
});
}
}
$registerWorkspaceCommentProvider(handle: number, extensionId: ExtensionIdentifier): void {
this._workspaceProviders.set(handle, undefined);
const providerId = generateUuid();
this._handlers.set(handle, providerId);
this._panelService.setPanelEnablement(COMMENTS_PANEL_ID, true);
if (this._firstSessionStart) {
this._panelService.openPanel(COMMENTS_PANEL_ID);
this._firstSessionStart = false;
const commentsPanelAlreadyConstructed = this._panelService.getPanels().some(panel => panel.id === COMMENTS_PANEL_ID);
Registry.as<PanelRegistry>(PanelExtensions.Panels).registerPanel(new PanelDescriptor(
CommentsPanel,
COMMENTS_PANEL_ID,
COMMENTS_PANEL_TITLE,
'commentsPanel',
10
));
const openPanel = this._configurationService.getValue<ICommentsConfiguration>('comments').openPanel;
if (openPanel === 'neverOpen') {
this.registerOpenPanelListener(commentsPanelAlreadyConstructed);
}
if (openPanel === 'openOnSessionStart') {
this._panelService.openPanel(COMMENTS_PANEL_ID);
}
this._proxy.$provideWorkspaceComments(handle).then(commentThreads => {
if (commentThreads) {
if (openPanel === 'openOnSessionStartWithComments' && commentThreads.length) {
if (commentThreads.length) {
this._panelService.openPanel(COMMENTS_PANEL_ID);
} else {
this.registerOpenPanelListener(commentsPanelAlreadyConstructed);
}
}
this._commentService.setWorkspaceComments(providerId, commentThreads);
}
});
@@ -120,7 +181,7 @@ export class MainThreadComments extends Disposable implements MainThreadComments
}
*/
this._telemetryService.publicLog('comments:registerWorkspaceCommentProvider', {
extensionId: extensionId
extensionId: extensionId.value
});
}
@@ -134,8 +195,14 @@ export class MainThreadComments extends Disposable implements MainThreadComments
$unregisterWorkspaceCommentProvider(handle: number): void {
this._workspaceProviders.delete(handle);
if (this._workspaceProviders.size === 0) {
this._panelService.setPanelEnablement(COMMENTS_PANEL_ID, false);
Registry.as<PanelRegistry>(PanelExtensions.Panels).deregisterPanel(COMMENTS_PANEL_ID);
if (this._openPanelListener) {
this._openPanelListener.dispose();
this._openPanelListener = null;
}
}
const handlerId = this._handlers.get(handle);
this._commentService.removeWorkspaceComments(handlerId);
this._handlers.delete(handle);

View File

@@ -6,12 +6,13 @@
import { URI, UriComponents } 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 } from 'vs/platform/configuration/common/configurationRegistry';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope, getScopes } from 'vs/platform/configuration/common/configurationRegistry';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
import { MainThreadConfigurationShape, MainContext, ExtHostContext, IExtHostContext, IWorkspaceConfigurationChangeEventData } from '../node/extHost.protocol';
import { MainThreadConfigurationShape, MainContext, ExtHostContext, IExtHostContext, IWorkspaceConfigurationChangeEventData, IConfigurationInitData } from '../node/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import { ConfigurationTarget, IConfigurationChangeEvent, IConfigurationModel } from 'vs/platform/configuration/common/configuration';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
@extHostNamedCustomer(MainContext.MainThreadConfiguration)
export class MainThreadConfiguration implements MainThreadConfigurationShape {
@@ -21,25 +22,36 @@ export class MainThreadConfiguration implements MainThreadConfigurationShape {
constructor(
extHostContext: IExtHostContext,
@IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService,
@IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService
@IWorkspaceConfigurationService private readonly configurationService: IWorkspaceConfigurationService,
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
) {
const proxy = extHostContext.getProxy(ExtHostContext.ExtHostConfiguration);
proxy.$initializeConfiguration(this._getConfigurationData());
this._configurationListener = configurationService.onDidChangeConfiguration(e => {
proxy.$acceptConfigurationChanged(configurationService.getConfigurationData(), this.toConfigurationChangeEventData(e));
proxy.$acceptConfigurationChanged(this._getConfigurationData(), this.toConfigurationChangeEventData(e));
});
}
private _getConfigurationData(): IConfigurationInitData {
const configurationData: IConfigurationInitData = { ...this.configurationService.getConfigurationData(), configurationScopes: {} };
// Send configurations scopes only in development mode.
if (!this._environmentService.isBuilt || this._environmentService.isExtensionDevelopment) {
configurationData.configurationScopes = getScopes();
}
return configurationData;
}
public dispose(): void {
this._configurationListener.dispose();
}
$updateConfigurationOption(target: ConfigurationTarget, key: string, value: any, resourceUriComponenets: UriComponents): Thenable<void> {
$updateConfigurationOption(target: ConfigurationTarget, key: string, value: any, resourceUriComponenets: UriComponents): Promise<void> {
const resource = resourceUriComponenets ? URI.revive(resourceUriComponenets) : null;
return this.writeConfiguration(target, key, value, resource);
}
$removeConfigurationOption(target: ConfigurationTarget, key: string, resourceUriComponenets: UriComponents): Thenable<void> {
$removeConfigurationOption(target: ConfigurationTarget, key: string, resourceUriComponenets: UriComponents): Promise<void> {
const resource = resourceUriComponenets ? URI.revive(resourceUriComponenets) : null;
return this.writeConfiguration(target, key, undefined, resource);
}

View File

@@ -0,0 +1,58 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import { MainContext, MainThreadConsoleShape, IExtHostContext } from 'vs/workbench/api/node/extHost.protocol';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IRemoteConsoleLog, log, parse } from 'vs/base/node/console';
import { parseExtensionDevOptions } from 'vs/workbench/services/extensions/electron-browser/extensionHost';
import { IWindowsService } from 'vs/platform/windows/common/windows';
import { IBroadcastService } from 'vs/platform/broadcast/electron-browser/broadcastService';
import { EXTENSION_LOG_BROADCAST_CHANNEL } from 'vs/platform/extensions/common/extensionHost';
@extHostNamedCustomer(MainContext.MainThreadConsole)
export class MainThreadConsole implements MainThreadConsoleShape {
private readonly _isExtensionDevHost: boolean;
private readonly _isExtensionDevTestFromCli: boolean;
constructor(
extHostContext: IExtHostContext,
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
@IWindowsService private readonly _windowsService: IWindowsService,
@IBroadcastService private readonly _broadcastService: IBroadcastService,
) {
const devOpts = parseExtensionDevOptions(this._environmentService);
this._isExtensionDevHost = devOpts.isExtensionDevHost;
this._isExtensionDevTestFromCli = devOpts.isExtensionDevTestFromCli;
}
dispose(): void {
//
}
$logExtensionHostMessage(entry: IRemoteConsoleLog): void {
// Send to local console unless we run tests from cli
if (!this._isExtensionDevTestFromCli) {
log(entry, 'Extension Host');
}
// Log on main side if running tests from cli
if (this._isExtensionDevTestFromCli) {
this._windowsService.log(entry.severity, ...parse(entry).args);
}
// Broadcast to other windows if we are in development mode
else if (!this._environmentService.isBuilt || this._isExtensionDevHost) {
this._broadcastService.broadcast({
channel: EXTENSION_LOG_BROADCAST_CHANNEL,
payload: {
logEntry: entry,
debugId: this._environmentService.debugExtensionHost.debugId
}
});
}
}
}

View File

@@ -17,7 +17,7 @@ import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostC
import severity from 'vs/base/common/severity';
import { AbstractDebugAdapter } from 'vs/workbench/parts/debug/node/debugAdapter';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { convertToVSCPaths, convertToDAPaths, stringToUri, uriToString } from 'vs/workbench/parts/debug/common/debugUtils';
import { convertToVSCPaths, convertToDAPaths } from 'vs/workbench/parts/debug/common/debugUtils';
@extHostNamedCustomer(MainContext.MainThreadDebugService)
export class MainThreadDebugService implements MainThreadDebugServiceShape, IDebugAdapterFactory {
@@ -34,7 +34,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
constructor(
extHostContext: IExtHostContext,
@IDebugService private debugService: IDebugService
@IDebugService private readonly debugService: IDebugService
) {
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostDebugService);
this._toDispose = [];
@@ -124,7 +124,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
}
}
public $registerBreakpoints(DTOs: (ISourceMultiBreakpointDto | IFunctionBreakpointDto)[]): Thenable<void> {
public $registerBreakpoints(DTOs: Array<ISourceMultiBreakpointDto | IFunctionBreakpointDto>): Promise<void> {
for (let dto of DTOs) {
if (dto.type === 'sourceMulti') {
@@ -144,21 +144,20 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
this.debugService.addFunctionBreakpoint(dto.functionName, dto.id);
}
}
return void 0;
return undefined;
}
public $unregisterBreakpoints(breakpointIds: string[], functionBreakpointIds: string[]): Thenable<void> {
public $unregisterBreakpoints(breakpointIds: string[], functionBreakpointIds: string[]): Promise<void> {
breakpointIds.forEach(id => this.debugService.removeBreakpoints(id));
functionBreakpointIds.forEach(id => this.debugService.removeFunctionBreakpoints(id));
return void 0;
return undefined;
}
public $registerDebugConfigurationProvider(debugType: string, hasProvide: boolean, hasResolve: boolean, hasProvideDebugAdapter: boolean, hasTracker: boolean, handle: number): Thenable<void> {
public $registerDebugConfigurationProvider(debugType: string, hasProvide: boolean, hasResolve: boolean, hasProvideDebugAdapter: boolean, handle: number): Promise<void> {
const provider = <IDebugConfigurationProvider>{
type: debugType,
hasTracker: hasTracker
type: debugType
};
if (hasProvide) {
provider.provideDebugConfigurations = (folder) => {
@@ -171,6 +170,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
};
}
if (hasProvideDebugAdapter) {
console.info('DebugConfigurationProvider.debugAdapterExecutable is deprecated and will be removed soon; please use DebugAdapterDescriptorFactory.createDebugAdapterDescriptor instead.');
provider.debugAdapterExecutable = (folder) => {
return Promise.resolve(this._proxy.$legacyDebugAdapterExecutable(handle, folder));
};
@@ -189,7 +189,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
}
}
public $registerDebugAdapterDescriptorFactory(debugType: string, handle: number): Thenable<void> {
public $registerDebugAdapterDescriptorFactory(debugType: string, handle: number): Promise<void> {
const provider = <IDebugAdapterDescriptorFactory>{
type: debugType,
@@ -229,7 +229,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
}
}
public $startDebugging(_folderUri: uri | undefined, nameOrConfiguration: string | IConfig): Thenable<boolean> {
public $startDebugging(_folderUri: uri | undefined, nameOrConfiguration: string | IConfig): Promise<boolean> {
const folderUri = _folderUri ? uri.revive(_folderUri) : undefined;
const launch = this.debugService.getConfigurationManager().getLaunch(folderUri);
return this.debugService.startDebugging(launch, nameOrConfiguration).then(success => {
@@ -239,7 +239,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
});
}
public $customDebugAdapterRequest(sessionId: DebugSessionUUID, request: string, args: any): Thenable<any> {
public $customDebugAdapterRequest(sessionId: DebugSessionUUID, request: string, args: any): Promise<any> {
const session = this.debugService.getModel().getSessions(true).filter(s => s.getId() === sessionId).pop();
if (session) {
return session.customRequest(request, args).then(response => {
@@ -262,8 +262,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
}
public $acceptDAMessage(handle: number, message: DebugProtocol.ProtocolMessage) {
this._debugAdapters.get(handle).acceptMessage(convertToVSCPaths(message, source => uriToString(source)));
this._debugAdapters.get(handle).acceptMessage(convertToVSCPaths(message, false));
}
public $acceptDAError(handle: number, name: string, message: string, stack: string) {
@@ -295,7 +294,7 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
return undefined;
}
private convertToDto(bps: (ReadonlyArray<IBreakpoint | IFunctionBreakpoint>)): (ISourceBreakpointDto | IFunctionBreakpointDto)[] {
private convertToDto(bps: (ReadonlyArray<IBreakpoint | IFunctionBreakpoint>)): Array<ISourceBreakpointDto | IFunctionBreakpointDto> {
return bps.map(bp => {
if ('name' in bp) {
const fbp = <IFunctionBreakpoint>bp;
@@ -351,8 +350,7 @@ class ExtensionHostDebugAdapter extends AbstractDebugAdapter {
}
public sendMessage(message: DebugProtocol.ProtocolMessage): void {
this._proxy.$sendDAMessage(this._handle, convertToDAPaths(message, source => stringToUri(source)));
this._proxy.$sendDAMessage(this._handle, convertToDAPaths(message, true));
}
public stopSession(): Promise<void> {

View File

@@ -58,7 +58,7 @@ class DecorationRequestsQueue {
// reset
this._requests = [];
this._resolver = [];
this._timer = void 0;
this._timer = undefined;
}, 0);
}
}

View File

@@ -41,7 +41,7 @@ export class MainThreadDocumentContentProviders implements MainThreadDocumentCon
$registerTextContentProvider(handle: number, scheme: string): void {
const registration = this._textModelResolverService.registerTextModelContentProvider(scheme, {
provideTextContent: (uri: URI): Thenable<ITextModel> => {
provideTextContent: (uri: URI): Promise<ITextModel> => {
return this._proxy.$provideTextDocumentContent(handle, uri).then(value => {
if (typeof value === 'string') {
const firstLineText = value.substr(0, 1 + value.search(/\r?\n/));

View File

@@ -167,20 +167,20 @@ export class MainThreadDocuments implements MainThreadDocumentsShape {
// --- from extension host process
$trySaveDocument(uri: UriComponents): Thenable<boolean> {
$trySaveDocument(uri: UriComponents): Promise<boolean> {
return this._textFileService.save(URI.revive(uri));
}
$tryOpenDocument(_uri: UriComponents): Thenable<any> {
$tryOpenDocument(_uri: UriComponents): Promise<any> {
const uri = URI.revive(_uri);
if (!uri.scheme || !(uri.fsPath || uri.authority)) {
return Promise.reject(new Error(`Invalid uri. Scheme and authority or path must be set.`));
}
let promise: Thenable<boolean>;
let promise: Promise<boolean>;
switch (uri.scheme) {
case Schemas.untitled:
promise = this._handleUnititledScheme(uri);
promise = this._handleUntitledScheme(uri);
break;
case Schemas.file:
default:
@@ -201,11 +201,11 @@ export class MainThreadDocuments implements MainThreadDocumentsShape {
});
}
$tryCreateDocument(options?: { language?: string, content?: string }): Thenable<URI> {
return this._doCreateUntitled(void 0, options ? options.language : void 0, options ? options.content : void 0);
$tryCreateDocument(options?: { language?: string, content?: string }): Promise<URI> {
return this._doCreateUntitled(undefined, options ? options.language : undefined, options ? options.content : undefined);
}
private _handleAsResourceInput(uri: URI): Thenable<boolean> {
private _handleAsResourceInput(uri: URI): Promise<boolean> {
return this._textModelResolverService.createModelReference(uri).then(ref => {
this._modelReferenceCollection.add(ref);
const result = !!ref.object;
@@ -213,7 +213,7 @@ export class MainThreadDocuments implements MainThreadDocumentsShape {
});
}
private _handleUnititledScheme(uri: URI): Thenable<boolean> {
private _handleUntitledScheme(uri: URI): Promise<boolean> {
let asFileUri = uri.with({ scheme: Schemas.file });
return this._fileService.resolveFile(asFileUri).then(stats => {
// don't create a new file ontop of an existing file
@@ -223,7 +223,7 @@ export class MainThreadDocuments implements MainThreadDocumentsShape {
});
}
private _doCreateUntitled(resource?: URI, modeId?: string, initialValue?: string): Thenable<URI> {
private _doCreateUntitled(resource?: URI, modeId?: string, initialValue?: string): Promise<URI> {
return this._untitledEditorService.loadOrCreate({
resource,
modeId,

View File

@@ -114,7 +114,7 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
// --- from extension host process
$tryShowTextDocument(resource: UriComponents, options: ITextDocumentShowOptions): Thenable<string> {
$tryShowTextDocument(resource: UriComponents, options: ITextDocumentShowOptions): Promise<string> {
const uri = URI.revive(resource);
const editorOptions: ITextEditorOptions = {
@@ -136,7 +136,7 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
});
}
$tryShowEditor(id: string, position?: EditorViewColumn): Thenable<void> {
$tryShowEditor(id: string, position?: EditorViewColumn): Promise<void> {
let mainThreadEditor = this._documentsAndEditors.getEditor(id);
if (mainThreadEditor) {
let model = mainThreadEditor.getModel();
@@ -148,7 +148,7 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
return undefined;
}
$tryHideEditor(id: string): Thenable<void> {
$tryHideEditor(id: string): Promise<void> {
let mainThreadEditor = this._documentsAndEditors.getEditor(id);
if (mainThreadEditor) {
let editors = this._editorService.visibleControls;
@@ -161,33 +161,33 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
return undefined;
}
$trySetSelections(id: string, selections: ISelection[]): Thenable<void> {
$trySetSelections(id: string, selections: ISelection[]): Promise<void> {
if (!this._documentsAndEditors.getEditor(id)) {
return Promise.reject(disposed(`TextEditor(${id})`));
}
this._documentsAndEditors.getEditor(id).setSelections(selections);
return Promise.resolve(null);
return Promise.resolve(undefined);
}
$trySetDecorations(id: string, key: string, ranges: IDecorationOptions[]): Thenable<void> {
$trySetDecorations(id: string, key: string, ranges: IDecorationOptions[]): Promise<void> {
key = `${this._instanceId}-${key}`;
if (!this._documentsAndEditors.getEditor(id)) {
return Promise.reject(disposed(`TextEditor(${id})`));
}
this._documentsAndEditors.getEditor(id).setDecorations(key, ranges);
return Promise.resolve(null);
return Promise.resolve(undefined);
}
$trySetDecorationsFast(id: string, key: string, ranges: number[]): Thenable<void> {
$trySetDecorationsFast(id: string, key: string, ranges: number[]): Promise<void> {
key = `${this._instanceId}-${key}`;
if (!this._documentsAndEditors.getEditor(id)) {
return Promise.reject(disposed(`TextEditor(${id})`));
}
this._documentsAndEditors.getEditor(id).setDecorationsFast(key, ranges);
return Promise.resolve(null);
return Promise.resolve(undefined);
}
$tryRevealRange(id: string, range: IRange, revealType: TextEditorRevealType): Thenable<void> {
$tryRevealRange(id: string, range: IRange, revealType: TextEditorRevealType): Promise<void> {
if (!this._documentsAndEditors.getEditor(id)) {
return Promise.reject(disposed(`TextEditor(${id})`));
}
@@ -195,27 +195,27 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
return undefined;
}
$trySetOptions(id: string, options: ITextEditorConfigurationUpdate): Thenable<void> {
$trySetOptions(id: string, options: ITextEditorConfigurationUpdate): Promise<void> {
if (!this._documentsAndEditors.getEditor(id)) {
return Promise.reject(disposed(`TextEditor(${id})`));
}
this._documentsAndEditors.getEditor(id).setConfiguration(options);
return Promise.resolve(null);
return Promise.resolve(undefined);
}
$tryApplyEdits(id: string, modelVersionId: number, edits: ISingleEditOperation[], opts: IApplyEditsOptions): Thenable<boolean> {
$tryApplyEdits(id: string, modelVersionId: number, edits: ISingleEditOperation[], opts: IApplyEditsOptions): Promise<boolean> {
if (!this._documentsAndEditors.getEditor(id)) {
return Promise.reject(disposed(`TextEditor(${id})`));
}
return Promise.resolve(this._documentsAndEditors.getEditor(id).applyEdits(modelVersionId, edits, opts));
}
$tryApplyWorkspaceEdit(dto: WorkspaceEditDto): Thenable<boolean> {
$tryApplyWorkspaceEdit(dto: WorkspaceEditDto): Promise<boolean> {
const { edits } = reviveWorkspaceEditDto(dto);
return this._bulkEditService.apply({ edits }, undefined).then(() => true, err => false);
}
$tryInsertSnippet(id: string, template: string, ranges: IRange[], opts: IUndoStopOptions): Thenable<boolean> {
$tryInsertSnippet(id: string, template: string, ranges: IRange[], opts: IUndoStopOptions): Promise<boolean> {
if (!this._documentsAndEditors.getEditor(id)) {
return Promise.reject(disposed(`TextEditor(${id})`));
}
@@ -234,7 +234,7 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
this._codeEditorService.removeDecorationType(key);
}
$getDiffInformation(id: string): Thenable<ILineChange[]> {
$getDiffInformation(id: string): Promise<ILineChange[]> {
const editor = this._documentsAndEditors.getEditor(id);
if (!editor) {
@@ -272,20 +272,20 @@ CommandsRegistry.registerCommand('_workbench.open', function (accessor: Services
if (options || typeof position === 'number') {
// use editor options or editor view column as a hint to use the editor service for opening
return editorService.openEditor({ resource, options, label }, viewColumnToEditorGroup(editorGroupService, position)).then(_ => void 0);
return editorService.openEditor({ resource, options, label }, viewColumnToEditorGroup(editorGroupService, position)).then(_ => undefined);
}
if (resource && resource.scheme === 'command') {
// do not allow to execute commands from here
return Promise.resolve(void 0);
return Promise.resolve(undefined);
}
if (resource && (resource.scheme === product.urlProtocol || /^vscode/.test(resource.scheme))) {
return urlService.open(resource).then(_ => void 0);
return urlService.open(resource).then(_ => undefined);
}
// finally, delegate to opener service
return openerService.open(resource).then(_ => void 0);
return openerService.open(resource).then(_ => undefined);
});
@@ -305,5 +305,5 @@ CommandsRegistry.registerCommand('_workbench.diff', function (accessor: Services
label = localize('diffLeftRightLabel', "{0} ⟷ {1}", leftResource.toString(true), rightResource.toString(true));
}
return editorService.openEditor({ leftResource, rightResource, label, description, options }, viewColumnToEditorGroup(editorGroupService, position)).then(() => void 0);
return editorService.openEditor({ leftResource, rightResource, label, description, options }, viewColumnToEditorGroup(editorGroupService, position)).then(() => undefined);
});

View File

@@ -9,6 +9,7 @@ import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostC
import { IExtHostContext, MainContext, MainThreadExtensionServiceShape } from 'vs/workbench/api/node/extHost.protocol';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { ExtensionService } from 'vs/workbench/services/extensions/electron-browser/extensionService';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
@extHostNamedCustomer(MainContext.MainThreadExtensionService)
export class MainThreadExtensionService implements MainThreadExtensionServiceShape {
@@ -30,10 +31,13 @@ export class MainThreadExtensionService implements MainThreadExtensionServiceSha
$localShowMessage(severity: Severity, msg: string): void {
this._extensionService._logOrShowMessage(severity, msg);
}
$onExtensionActivated(extensionId: string, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationEvent: string): void {
this._extensionService._onExtensionActivated(extensionId, startup, codeLoadingTime, activateCallTime, activateResolvedTime, activationEvent);
$onWillActivateExtension(extensionId: ExtensionIdentifier): void {
this._extensionService._onWillActivateExtension(extensionId);
}
$onExtensionRuntimeError(extensionId: string, data: SerializedError): void {
$onDidActivateExtension(extensionId: ExtensionIdentifier, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationEvent: string): void {
this._extensionService._onDidActivateExtension(extensionId, startup, codeLoadingTime, activateCallTime, activateResolvedTime, activationEvent);
}
$onExtensionRuntimeError(extensionId: ExtensionIdentifier, data: SerializedError): void {
const error = new Error();
error.name = data.name;
error.message = data.message;
@@ -42,9 +46,9 @@ export class MainThreadExtensionService implements MainThreadExtensionServiceSha
console.error(`[${extensionId}]${error.message}`);
console.error(error.stack);
}
$onExtensionActivationFailed(extensionId: string): void {
$onExtensionActivationFailed(extensionId: ExtensionIdentifier): void {
}
$addMessage(extensionId: string, severity: Severity, message: string): void {
$addMessage(extensionId: ExtensionIdentifier, severity: Severity, message: string): void {
this._extensionService._addMessage(extensionId, severity, message);
}
}

View File

@@ -6,10 +6,10 @@
import { Emitter, Event } from 'vs/base/common/event';
import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { FileWriteOptions, FileSystemProviderCapabilities, IFileChange, IFileService, IFileSystemProvider, IStat, IWatchOptions, FileType, FileOverwriteOptions, FileDeleteOptions } from 'vs/platform/files/common/files';
import { FileWriteOptions, FileSystemProviderCapabilities, IFileChange, IFileService, IFileSystemProvider, IStat, IWatchOptions, FileType, FileOverwriteOptions, FileDeleteOptions, FileOpenOptions } from 'vs/platform/files/common/files';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import { ExtHostContext, ExtHostFileSystemShape, IExtHostContext, IFileChangeDto, MainContext, MainThreadFileSystemShape } from '../node/extHost.protocol';
import { LabelRules, ILabelService } from 'vs/platform/label/common/label';
import { ResourceLabelFormatter, ILabelService } from 'vs/platform/label/common/label';
@extHostNamedCustomer(MainContext.MainThreadFileSystem)
export class MainThreadFileSystem implements MainThreadFileSystemShape {
@@ -39,8 +39,8 @@ export class MainThreadFileSystem implements MainThreadFileSystemShape {
this._fileProvider.delete(handle);
}
$setUriFormatter(selector: string, formatter: LabelRules): void {
this._labelService.registerFormatter(selector, formatter);
$setUriFormatter(formatter: ResourceLabelFormatter): void {
this._labelService.registerFormatter(formatter);
}
$onFileSystemChange(handle: number, changes: IFileChangeDto[]): void {
@@ -96,53 +96,56 @@ class RemoteFileSystemProvider implements IFileSystemProvider {
return Buffer.isBuffer(data) ? data : Buffer.from(data.buffer, data.byteOffset, data.byteLength);
}
stat(resource: URI): Thenable<IStat> {
stat(resource: URI): Promise<IStat> {
return this._proxy.$stat(this._handle, resource).then(undefined, err => {
throw err;
});
}
readFile(resource: URI): Thenable<Uint8Array> {
readFile(resource: URI): Promise<Uint8Array> {
return this._proxy.$readFile(this._handle, resource);
}
writeFile(resource: URI, content: Uint8Array, opts: FileWriteOptions): Thenable<void> {
writeFile(resource: URI, content: Uint8Array, opts: FileWriteOptions): Promise<void> {
return this._proxy.$writeFile(this._handle, resource, RemoteFileSystemProvider._asBuffer(content), opts);
}
delete(resource: URI, opts: FileDeleteOptions): Thenable<void> {
delete(resource: URI, opts: FileDeleteOptions): Promise<void> {
return this._proxy.$delete(this._handle, resource, opts);
}
mkdir(resource: URI): Thenable<void> {
mkdir(resource: URI): Promise<void> {
return this._proxy.$mkdir(this._handle, resource);
}
readdir(resource: URI): Thenable<[string, FileType][]> {
readdir(resource: URI): Promise<[string, FileType][]> {
return this._proxy.$readdir(this._handle, resource);
}
rename(resource: URI, target: URI, opts: FileOverwriteOptions): Thenable<void> {
rename(resource: URI, target: URI, opts: FileOverwriteOptions): Promise<void> {
return this._proxy.$rename(this._handle, resource, target, opts);
}
copy(resource: URI, target: URI, opts: FileOverwriteOptions): Thenable<void> {
copy(resource: URI, target: URI, opts: FileOverwriteOptions): Promise<void> {
return this._proxy.$copy(this._handle, resource, target, opts);
}
open(resource: URI): Thenable<number> {
return this._proxy.$open(this._handle, resource);
open(resource: URI, opts: FileOpenOptions): Promise<number> {
return this._proxy.$open(this._handle, resource, opts);
}
close(fd: number): Thenable<void> {
close(fd: number): Promise<void> {
return this._proxy.$close(this._handle, fd);
}
read(fd: number, pos: number, data: Uint8Array, offset: number, length: number): Thenable<number> {
return this._proxy.$read(this._handle, fd, pos, RemoteFileSystemProvider._asBuffer(data), offset, length);
read(fd: number, pos: number, data: Uint8Array, offset: number, length: number): Promise<number> {
return this._proxy.$read(this._handle, fd, pos, length).then(readData => {
data.set(readData, offset);
return readData.byteLength;
});
}
write(fd: number, pos: number, data: Uint8Array, offset: number, length: number): Thenable<number> {
return this._proxy.$write(this._handle, fd, pos, RemoteFileSystemProvider._asBuffer(data), offset, length);
write(fd: number, pos: number, data: Uint8Array, offset: number, length: number): Promise<number> {
return this._proxy.$write(this._handle, fd, pos, Buffer.from(data, offset, length));
}
}

View File

@@ -23,7 +23,7 @@ export interface IHeapService {
* Track gc-collection for all new objects that
* have the $ident-value set.
*/
trackRecursive<T>(obj: T | Thenable<T>): Thenable<T>;
trackRecursive<T>(obj: T | Promise<T>): Promise<T>;
}
export class HeapService implements IHeapService {
@@ -45,7 +45,7 @@ export class HeapService implements IHeapService {
clearInterval(this._consumeHandle);
}
trackRecursive<T>(obj: T | Thenable<T>): Thenable<T> {
trackRecursive<T>(obj: T | Promise<T>): Promise<T> {
if (isThenable(obj)) {
return obj.then(result => this.trackRecursive(result));
} else {
@@ -61,7 +61,7 @@ export class HeapService implements IHeapService {
return import('gc-signals').then(({ GCSignal, consumeSignals }) => {
if (this._consumeHandle === void 0) {
if (this._consumeHandle === undefined) {
// ensure that there is one consumer of signals
this._consumeHandle = setInterval(() => {
const ids = consumeSignals();

View File

@@ -69,17 +69,17 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
}
}
private static _reviveDefinitionLinkDto(data: DefinitionLinkDto): modes.DefinitionLink;
private static _reviveDefinitionLinkDto(data: DefinitionLinkDto[]): modes.DefinitionLink[];
private static _reviveDefinitionLinkDto(data: DefinitionLinkDto | DefinitionLinkDto[]): modes.DefinitionLink | modes.DefinitionLink[] {
private static _reviveLocationLinkDto(data: DefinitionLinkDto): modes.LocationLink;
private static _reviveLocationLinkDto(data: DefinitionLinkDto[]): modes.LocationLink[];
private static _reviveLocationLinkDto(data: DefinitionLinkDto | DefinitionLinkDto[]): modes.LocationLink | modes.LocationLink[] {
if (!data) {
return <modes.DefinitionLink>data;
return <modes.LocationLink>data;
} else if (Array.isArray(data)) {
data.forEach(l => MainThreadLanguageFeatures._reviveDefinitionLinkDto(l));
return <modes.DefinitionLink[]>data;
data.forEach(l => MainThreadLanguageFeatures._reviveLocationLinkDto(l));
return <modes.LocationLink[]>data;
} else {
data.uri = URI.revive(data.uri);
return <modes.DefinitionLink>data;
return <modes.LocationLink>data;
}
}
@@ -108,10 +108,10 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
// --- outline
$registerOutlineSupport(handle: number, selector: ISerializedDocumentFilter[], displayName: string): void {
$registerDocumentSymbolProvider(handle: number, selector: ISerializedDocumentFilter[], displayName: string): void {
this._registrations[handle] = modes.DocumentSymbolProviderRegistry.register(typeConverters.LanguageSelector.from(selector), <modes.DocumentSymbolProvider>{
displayName,
provideDocumentSymbols: (model: ITextModel, token: CancellationToken): Thenable<modes.DocumentSymbol[]> => {
provideDocumentSymbols: (model: ITextModel, token: CancellationToken): Promise<modes.DocumentSymbol[]> => {
return this._proxy.$provideDocumentSymbols(handle, model.uri, token);
}
});
@@ -122,10 +122,10 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
$registerCodeLensSupport(handle: number, selector: ISerializedDocumentFilter[], eventHandle: number): void {
const provider = <modes.CodeLensProvider>{
provideCodeLenses: (model: ITextModel, token: CancellationToken): modes.ICodeLensSymbol[] | Thenable<modes.ICodeLensSymbol[]> => {
provideCodeLenses: (model: ITextModel, token: CancellationToken): modes.ICodeLensSymbol[] | Promise<modes.ICodeLensSymbol[]> => {
return this._heapService.trackRecursive(this._proxy.$provideCodeLenses(handle, model.uri, token));
},
resolveCodeLens: (model: ITextModel, codeLens: modes.ICodeLensSymbol, token: CancellationToken): modes.ICodeLensSymbol | Thenable<modes.ICodeLensSymbol> => {
resolveCodeLens: (model: ITextModel, codeLens: modes.ICodeLensSymbol, token: CancellationToken): modes.ICodeLensSymbol | Promise<modes.ICodeLensSymbol> => {
return this._heapService.trackRecursive(this._proxy.$resolveCodeLens(handle, model.uri, codeLens, token));
}
};
@@ -150,8 +150,8 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
$registerDefinitionSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
this._registrations[handle] = modes.DefinitionProviderRegistry.register(typeConverters.LanguageSelector.from(selector), <modes.DefinitionProvider>{
provideDefinition: (model, position, token): Thenable<modes.DefinitionLink[]> => {
return this._proxy.$provideDefinition(handle, model.uri, position, token).then(MainThreadLanguageFeatures._reviveDefinitionLinkDto);
provideDefinition: (model, position, token): Promise<modes.LocationLink[]> => {
return this._proxy.$provideDefinition(handle, model.uri, position, token).then(MainThreadLanguageFeatures._reviveLocationLinkDto);
}
});
}
@@ -159,23 +159,23 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
$registerDeclarationSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
this._registrations[handle] = modes.DeclarationProviderRegistry.register(typeConverters.LanguageSelector.from(selector), <modes.DeclarationProvider>{
provideDeclaration: (model, position, token) => {
return this._proxy.$provideDeclaration(handle, model.uri, position, token).then(MainThreadLanguageFeatures._reviveDefinitionLinkDto);
return this._proxy.$provideDeclaration(handle, model.uri, position, token).then(MainThreadLanguageFeatures._reviveLocationLinkDto);
}
});
}
$registerImplementationSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
this._registrations[handle] = modes.ImplementationProviderRegistry.register(typeConverters.LanguageSelector.from(selector), <modes.ImplementationProvider>{
provideImplementation: (model, position, token): Thenable<modes.Definition> => {
return this._proxy.$provideImplementation(handle, model.uri, position, token).then(MainThreadLanguageFeatures._reviveDefinitionLinkDto);
provideImplementation: (model, position, token): Promise<modes.LocationLink[]> => {
return this._proxy.$provideImplementation(handle, model.uri, position, token).then(MainThreadLanguageFeatures._reviveLocationLinkDto);
}
});
}
$registerTypeDefinitionSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
this._registrations[handle] = modes.TypeDefinitionProviderRegistry.register(typeConverters.LanguageSelector.from(selector), <modes.TypeDefinitionProvider>{
provideTypeDefinition: (model, position, token): Thenable<modes.Definition> => {
return this._proxy.$provideTypeDefinition(handle, model.uri, position, token).then(MainThreadLanguageFeatures._reviveDefinitionLinkDto);
provideTypeDefinition: (model, position, token): Promise<modes.LocationLink[]> => {
return this._proxy.$provideTypeDefinition(handle, model.uri, position, token).then(MainThreadLanguageFeatures._reviveLocationLinkDto);
}
});
}
@@ -184,7 +184,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
$registerHoverProvider(handle: number, selector: ISerializedDocumentFilter[]): void {
this._registrations[handle] = modes.HoverProviderRegistry.register(typeConverters.LanguageSelector.from(selector), <modes.HoverProvider>{
provideHover: (model: ITextModel, position: EditorPosition, token: CancellationToken): Thenable<modes.Hover> => {
provideHover: (model: ITextModel, position: EditorPosition, token: CancellationToken): Promise<modes.Hover> => {
return this._proxy.$provideHover(handle, model.uri, position, token);
}
});
@@ -194,7 +194,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
$registerDocumentHighlightProvider(handle: number, selector: ISerializedDocumentFilter[]): void {
this._registrations[handle] = modes.DocumentHighlightProviderRegistry.register(typeConverters.LanguageSelector.from(selector), <modes.DocumentHighlightProvider>{
provideDocumentHighlights: (model: ITextModel, position: EditorPosition, token: CancellationToken): Thenable<modes.DocumentHighlight[]> => {
provideDocumentHighlights: (model: ITextModel, position: EditorPosition, token: CancellationToken): Promise<modes.DocumentHighlight[]> => {
return this._proxy.$provideDocumentHighlights(handle, model.uri, position, token);
}
});
@@ -204,7 +204,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
$registerReferenceSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
this._registrations[handle] = modes.ReferenceProviderRegistry.register(typeConverters.LanguageSelector.from(selector), <modes.ReferenceProvider>{
provideReferences: (model: ITextModel, position: EditorPosition, context: modes.ReferenceContext, token: CancellationToken): Thenable<modes.Location[]> => {
provideReferences: (model: ITextModel, position: EditorPosition, context: modes.ReferenceContext, token: CancellationToken): Promise<modes.Location[]> => {
return this._proxy.$provideReferences(handle, model.uri, position, context, token).then(MainThreadLanguageFeatures._reviveLocationDto);
}
});
@@ -214,7 +214,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
$registerQuickFixSupport(handle: number, selector: ISerializedDocumentFilter[], providedCodeActionKinds?: string[]): void {
this._registrations[handle] = modes.CodeActionProviderRegistry.register(typeConverters.LanguageSelector.from(selector), <modes.CodeActionProvider>{
provideCodeActions: (model: ITextModel, rangeOrSelection: EditorRange | Selection, context: modes.CodeActionContext, token: CancellationToken): Thenable<modes.CodeAction[]> => {
provideCodeActions: (model: ITextModel, rangeOrSelection: EditorRange | Selection, context: modes.CodeActionContext, token: CancellationToken): Promise<modes.CodeAction[]> => {
return this._heapService.trackRecursive(this._proxy.$provideCodeActions(handle, model.uri, rangeOrSelection, context, token)).then(MainThreadLanguageFeatures._reviveCodeActionDto);
},
providedCodeActionKinds
@@ -223,17 +223,19 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
// --- formatting
$registerDocumentFormattingSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
$registerDocumentFormattingSupport(handle: number, selector: ISerializedDocumentFilter[], displayName: string): void {
this._registrations[handle] = modes.DocumentFormattingEditProviderRegistry.register(typeConverters.LanguageSelector.from(selector), <modes.DocumentFormattingEditProvider>{
provideDocumentFormattingEdits: (model: ITextModel, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> => {
displayName,
provideDocumentFormattingEdits: (model: ITextModel, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]> => {
return this._proxy.$provideDocumentFormattingEdits(handle, model.uri, options, token);
}
});
}
$registerRangeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
$registerRangeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[], displayName: string): void {
this._registrations[handle] = modes.DocumentRangeFormattingEditProviderRegistry.register(typeConverters.LanguageSelector.from(selector), <modes.DocumentRangeFormattingEditProvider>{
provideDocumentRangeFormattingEdits: (model: ITextModel, range: EditorRange, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> => {
displayName,
provideDocumentRangeFormattingEdits: (model: ITextModel, range: EditorRange, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]> => {
return this._proxy.$provideDocumentRangeFormattingEdits(handle, model.uri, range, options, token);
}
});
@@ -244,7 +246,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
autoFormatTriggerCharacters,
provideOnTypeFormattingEdits: (model: ITextModel, position: EditorPosition, ch: string, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> => {
provideOnTypeFormattingEdits: (model: ITextModel, position: EditorPosition, ch: string, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]> => {
return this._proxy.$provideOnTypeFormattingEdits(handle, model.uri, position, ch, options, token);
}
});
@@ -255,7 +257,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
$registerNavigateTypeSupport(handle: number): void {
let lastResultId: number;
this._registrations[handle] = search.WorkspaceSymbolProviderRegistry.register(<search.IWorkspaceSymbolProvider>{
provideWorkspaceSymbols: (search: string, token: CancellationToken): Thenable<search.IWorkspaceSymbol[]> => {
provideWorkspaceSymbols: (search: string, token: CancellationToken): Promise<search.IWorkspaceSymbol[]> => {
return this._proxy.$provideWorkspaceSymbols(handle, search, token).then(result => {
if (lastResultId !== undefined) {
this._proxy.$releaseWorkspaceSymbols(handle, lastResultId);
@@ -264,7 +266,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
return MainThreadLanguageFeatures._reviveWorkspaceSymbolDto(result.symbols);
});
},
resolveWorkspaceSymbol: (item: search.IWorkspaceSymbol, token: CancellationToken): Thenable<search.IWorkspaceSymbol> => {
resolveWorkspaceSymbol: (item: search.IWorkspaceSymbol, token: CancellationToken): Promise<search.IWorkspaceSymbol> => {
return this._proxy.$resolveWorkspaceSymbol(handle, item, token).then(i => MainThreadLanguageFeatures._reviveWorkspaceSymbolDto(i));
}
});
@@ -275,11 +277,11 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
$registerRenameSupport(handle: number, selector: ISerializedDocumentFilter[], supportResolveLocation: boolean): void {
this._registrations[handle] = modes.RenameProviderRegistry.register(typeConverters.LanguageSelector.from(selector), <modes.RenameProvider>{
provideRenameEdits: (model: ITextModel, position: EditorPosition, newName: string, token: CancellationToken): Thenable<modes.WorkspaceEdit> => {
provideRenameEdits: (model: ITextModel, position: EditorPosition, newName: string, token: CancellationToken): Promise<modes.WorkspaceEdit> => {
return this._proxy.$provideRenameEdits(handle, model.uri, position, newName, token).then(reviveWorkspaceEditDto);
},
resolveRenameLocation: supportResolveLocation
? (model: ITextModel, position: EditorPosition, token: CancellationToken): Thenable<modes.RenameLocation> => this._proxy.$resolveRenameLocation(handle, model.uri, position, token)
? (model: ITextModel, position: EditorPosition, token: CancellationToken): Promise<modes.RenameLocation> => this._proxy.$resolveRenameLocation(handle, model.uri, position, token)
: undefined
});
}
@@ -289,7 +291,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
$registerSuggestSupport(handle: number, selector: ISerializedDocumentFilter[], triggerCharacters: string[], supportsResolveDetails: boolean): void {
this._registrations[handle] = modes.CompletionProviderRegistry.register(typeConverters.LanguageSelector.from(selector), <modes.CompletionItemProvider>{
triggerCharacters,
provideCompletionItems: (model: ITextModel, position: EditorPosition, context: modes.CompletionContext, token: CancellationToken): Thenable<modes.CompletionList> => {
provideCompletionItems: (model: ITextModel, position: EditorPosition, context: modes.CompletionContext, token: CancellationToken): Promise<modes.CompletionList> => {
return this._proxy.$provideCompletionItems(handle, model.uri, position, context, token).then(result => {
if (!result) {
return result;
@@ -315,7 +317,7 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
signatureHelpTriggerCharacters: metadata.triggerCharacters,
signatureHelpRetriggerCharacters: metadata.retriggerCharacters,
provideSignatureHelp: (model: ITextModel, position: EditorPosition, token: CancellationToken, context: modes.SignatureHelpContext): Thenable<modes.SignatureHelp> => {
provideSignatureHelp: (model: ITextModel, position: EditorPosition, token: CancellationToken, context: modes.SignatureHelpContext): Promise<modes.SignatureHelp> => {
return this._proxy.$provideSignatureHelp(handle, model.uri, position, context, token);
}
});

View File

@@ -23,11 +23,11 @@ export class MainThreadLanguages implements MainThreadLanguagesShape {
// nothing
}
$getLanguages(): Thenable<string[]> {
$getLanguages(): Promise<string[]> {
return Promise.resolve(this._modeService.getRegisteredModes());
}
$changeLanguage(resource: UriComponents, languageId: string): Thenable<void> {
$changeLanguage(resource: UriComponents, languageId: string): Promise<void> {
const uri = URI.revive(resource);
let model = this._modelService.getModel(uri);
if (!model) {

View File

@@ -11,9 +11,10 @@ import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostC
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { once } from 'vs/base/common/event';
import { Event } from 'vs/base/common/event';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { dispose } from 'vs/base/common/lifecycle';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
@extHostNamedCustomer(MainContext.MainThreadMessageService)
export class MainThreadMessageService implements MainThreadMessageServiceShape {
@@ -31,7 +32,7 @@ export class MainThreadMessageService implements MainThreadMessageServiceShape {
//
}
$showMessage(severity: Severity, message: string, options: MainThreadMessageOptions, commands: { title: string; isCloseAffordance: boolean; handle: number; }[]): Thenable<number> {
$showMessage(severity: Severity, message: string, options: MainThreadMessageOptions, commands: { title: string; isCloseAffordance: boolean; handle: number; }[]): Promise<number> {
if (options.modal) {
return this._showModalMessage(severity, message, commands);
} else {
@@ -39,7 +40,7 @@ export class MainThreadMessageService implements MainThreadMessageServiceShape {
}
}
private _showMessage(severity: Severity, message: string, commands: { title: string; isCloseAffordance: boolean; handle: number; }[], extension: IExtensionDescription): Thenable<number> {
private _showMessage(severity: Severity, message: string, commands: { title: string; isCloseAffordance: boolean; handle: number; }[], extension: IExtensionDescription): Promise<number> {
return new Promise<number>(resolve => {
@@ -55,9 +56,9 @@ export class MainThreadMessageService implements MainThreadMessageServiceShape {
}
class ManageExtensionAction extends Action {
constructor(id: string, label: string, commandService: ICommandService) {
super(id, label, undefined, true, () => {
return commandService.executeCommand('_extensions.manage', id);
constructor(id: ExtensionIdentifier, label: string, commandService: ICommandService) {
super(id.value, label, undefined, true, () => {
return commandService.executeCommand('_extensions.manage', id.value);
});
}
}
@@ -77,7 +78,7 @@ export class MainThreadMessageService implements MainThreadMessageServiceShape {
const secondaryActions: IAction[] = [];
if (extension && !extension.isUnderDevelopment) {
secondaryActions.push(new ManageExtensionAction(extension.id, nls.localize('manageExtension', "Manage Extension"), this._commandService));
secondaryActions.push(new ManageExtensionAction(extension.identifier, nls.localize('manageExtension', "Manage Extension"), this._commandService));
}
const messageHandle = this._notificationService.notify({
@@ -89,15 +90,15 @@ export class MainThreadMessageService implements MainThreadMessageServiceShape {
// if promise has not been resolved yet, now is the time to ensure a return value
// otherwise if already resolved it means the user clicked one of the buttons
once(messageHandle.onDidClose)(() => {
Event.once(messageHandle.onDidClose)(() => {
dispose(...primaryActions, ...secondaryActions);
resolve(undefined);
});
});
}
private _showModalMessage(severity: Severity, message: string, commands: { title: string; isCloseAffordance: boolean; handle: number; }[]): Thenable<number> {
let cancelId: number | undefined = void 0;
private _showModalMessage(severity: Severity, message: string, commands: { title: string; isCloseAffordance: boolean; handle: number; }[]): Promise<number> {
let cancelId: number | undefined = undefined;
const buttons = commands.map((command, index) => {
if (command.isCloseAffordance === true) {
@@ -107,7 +108,7 @@ export class MainThreadMessageService implements MainThreadMessageServiceShape {
return command.title;
});
if (cancelId === void 0) {
if (cancelId === undefined) {
if (buttons.length > 0) {
buttons.push(nls.localize('cancel', "Cancel"));
} else {

View File

@@ -11,7 +11,7 @@ import { MainThreadOutputServiceShape, MainContext, IExtHostContext, ExtHostOutp
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import { UriComponents, URI } from 'vs/base/common/uri';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { anyEvent } from 'vs/base/common/event';
import { Event } from 'vs/base/common/event';
@extHostNamedCustomer(MainContext.MainThreadOutputService)
export class MainThreadOutputService extends Disposable implements MainThreadOutputServiceShape {
@@ -41,18 +41,18 @@ export class MainThreadOutputService extends Disposable implements MainThreadOut
const visibleChannel: IOutputChannel = panel && panel.getId() === OUTPUT_PANEL_ID ? this._outputService.getActiveChannel() : null;
this._proxy.$setVisibleChannel(visibleChannel ? visibleChannel.id : null);
};
this._register(anyEvent<any>(this._outputService.onActiveOutputChannel, this._panelService.onDidPanelOpen, this._panelService.onDidPanelClose)(() => setVisibleChannel()));
this._register(Event.any<any>(this._outputService.onActiveOutputChannel, this._panelService.onDidPanelOpen, this._panelService.onDidPanelClose)(() => setVisibleChannel()));
setVisibleChannel();
}
public $register(label: string, log: boolean, file?: UriComponents): Thenable<string> {
public $register(label: string, log: boolean, file?: UriComponents): Promise<string> {
const id = 'extension-output-#' + (MainThreadOutputService._idPool++);
Registry.as<IOutputChannelRegistry>(Extensions.OutputChannels).registerChannel({ id, label, file: file ? URI.revive(file) : null, log });
this._register(toDisposable(() => this.$dispose(id)));
return Promise.resolve(id);
}
public $append(channelId: string, value: string): Thenable<void> {
public $append(channelId: string, value: string): Promise<void> {
const channel = this._getChannel(channelId);
if (channel) {
channel.append(value);
@@ -60,7 +60,7 @@ export class MainThreadOutputService extends Disposable implements MainThreadOut
return undefined;
}
public $update(channelId: string): Thenable<void> {
public $update(channelId: string): Promise<void> {
const channel = this._getChannel(channelId);
if (channel) {
channel.update();
@@ -68,7 +68,7 @@ export class MainThreadOutputService extends Disposable implements MainThreadOut
return undefined;
}
public $clear(channelId: string, till: number): Thenable<void> {
public $clear(channelId: string, till: number): Promise<void> {
const channel = this._getChannel(channelId);
if (channel) {
channel.clear(till);
@@ -76,7 +76,7 @@ export class MainThreadOutputService extends Disposable implements MainThreadOut
return undefined;
}
public $reveal(channelId: string, preserveFocus: boolean): Thenable<void> {
public $reveal(channelId: string, preserveFocus: boolean): Promise<void> {
const channel = this._getChannel(channelId);
if (channel) {
this._outputService.showChannel(channel.id, preserveFocus);
@@ -84,7 +84,7 @@ export class MainThreadOutputService extends Disposable implements MainThreadOut
return undefined;
}
public $close(channelId: string): Thenable<void> {
public $close(channelId: string): Promise<void> {
const panel = this._panelService.getActivePanel();
if (panel && panel.getId() === OUTPUT_PANEL_ID && channelId === this._outputService.getActiveChannel().id) {
this._partService.setPanelHidden(true);
@@ -93,7 +93,7 @@ export class MainThreadOutputService extends Disposable implements MainThreadOut
return undefined;
}
public $dispose(channelId: string): Thenable<void> {
public $dispose(channelId: string): Promise<void> {
const channel = this._getChannel(channelId);
if (channel) {
channel.dispose();

View File

@@ -11,7 +11,7 @@ import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostC
export class MainThreadProgress implements MainThreadProgressShape {
private _progressService: IProgressService2;
private _progress = new Map<number, { resolve: Function, progress: IProgress<IProgressStep> }>();
private _progress = new Map<number, { resolve: () => void, progress: IProgress<IProgressStep> }>();
private _proxy: ExtHostProgressShape;
constructor(

View File

@@ -36,7 +36,7 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
public dispose(): void {
}
$show(instance: number, options: IPickOptions<TransferQuickPickItems>, token: CancellationToken): Thenable<number | number[]> {
$show(instance: number, options: IPickOptions<TransferQuickPickItems>, token: CancellationToken): Promise<number | number[]> {
const contents = new Promise<TransferQuickPickItems[]>((resolve, reject) => {
this._items[instance] = { resolve, reject };
});
@@ -67,7 +67,7 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
}
}
$setItems(instance: number, items: TransferQuickPickItems[]): Thenable<void> {
$setItems(instance: number, items: TransferQuickPickItems[]): Promise<void> {
if (this._items[instance]) {
this._items[instance].resolve(items);
delete this._items[instance];
@@ -75,7 +75,7 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
return undefined;
}
$setError(instance: number, error: Error): Thenable<void> {
$setError(instance: number, error: Error): Promise<void> {
if (this._items[instance]) {
this._items[instance].reject(error);
delete this._items[instance];
@@ -85,7 +85,7 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
// ---- input
$input(options: InputBoxOptions, validateInput: boolean, token: CancellationToken): Thenable<string> {
$input(options: InputBoxOptions, validateInput: boolean, token: CancellationToken): Promise<string> {
const inputOptions: IInputOptions = Object.create(null);
if (options) {
@@ -110,7 +110,7 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
private sessions = new Map<number, QuickInputSession>();
$createOrUpdate(params: TransferQuickInput): Thenable<void> {
$createOrUpdate(params: TransferQuickInput): Promise<void> {
const sessionId = params.id;
let session = this.sessions.get(sessionId);
if (!session) {
@@ -202,7 +202,7 @@ export class MainThreadQuickOpen implements MainThreadQuickOpenShape {
return Promise.resolve(undefined);
}
$dispose(sessionId: number): Thenable<void> {
$dispose(sessionId: number): Promise<void> {
const session = this.sessions.get(sessionId);
if (session) {
session.input.dispose();

View File

@@ -3,9 +3,8 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { TPromise } from 'vs/base/common/winjs.base';
import { URI, UriComponents } from 'vs/base/common/uri';
import { Event, Emitter, debounceEvent } from 'vs/base/common/event';
import { Event, Emitter } from 'vs/base/common/event';
import { assign } from 'vs/base/common/objects';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { ISCMService, ISCMRepository, ISCMProvider, ISCMResource, ISCMResourceGroup, ISCMResourceDecorations, IInputValidation } from 'vs/workbench/services/scm/common/scm';
@@ -72,7 +71,7 @@ class MainThreadSCMResource implements ISCMResource {
public decorations: ISCMResourceDecorations
) { }
open(): Thenable<void> {
open(): Promise<void> {
return this.proxy.$executeResourceCommand(this.sourceControlHandle, this.groupHandle, this.handle);
}
@@ -242,13 +241,13 @@ class MainThreadSCMProvider implements ISCMProvider {
this.groups.splice(this.groups.elements.indexOf(group), 1);
}
getOriginalResource(uri: URI): TPromise<URI> {
async getOriginalResource(uri: URI): Promise<URI> {
if (!this.features.hasQuickDiffProvider) {
return TPromise.as(null);
return null;
}
return TPromise.wrap(this.proxy.$provideOriginalResource(this.handle, uri, CancellationToken.None))
.then(result => result && URI.revive(result));
const result = await this.proxy.$provideOriginalResource(this.handle, uri, CancellationToken.None);
return result && URI.revive(result);
}
toJSON(): any {
@@ -273,11 +272,11 @@ export class MainThreadSCM implements MainThreadSCMShape {
constructor(
extHostContext: IExtHostContext,
@ISCMService private scmService: ISCMService
@ISCMService private readonly scmService: ISCMService
) {
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostSCM);
debounceEvent(scmService.onDidChangeSelectedRepositories, (_, e) => e, 100)
Event.debounce(scmService.onDidChangeSelectedRepositories, (_, e) => e, 100)
(this.onDidChangeSelectedRepositories, this, this._disposables);
}
@@ -420,20 +419,12 @@ export class MainThreadSCM implements MainThreadSCMShape {
}
if (enabled) {
repository.input.validateInput = (value, pos): TPromise<IInputValidation | undefined> => {
return TPromise.wrap(this._proxy.$validateInput(sourceControlHandle, value, pos).then(result => {
if (!result) {
return undefined;
}
return {
message: result[0],
type: result[1]
};
}));
repository.input.validateInput = async (value, pos): Promise<IInputValidation | undefined> => {
const result = await this._proxy.$validateInput(sourceControlHandle, value, pos);
return result && { message: result[0], type: result[1] };
};
} else {
repository.input.validateInput = () => TPromise.as(undefined);
repository.input.validateInput = async () => undefined;
}
}

View File

@@ -3,39 +3,39 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { sequence, IdleValue } from 'vs/base/common/async';
import { isNonEmptyArray } from 'vs/base/common/arrays';
import { IdleValue, sequence } from 'vs/base/common/async';
import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation';
import * as strings from 'vs/base/common/strings';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { ISaveParticipant, ITextFileEditorModel, SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ITextModel, ISingleEditOperation, IIdentifiedSingleEditOperation } from 'vs/editor/common/model';
import { trimTrailingWhitespace } from 'vs/editor/common/commands/trimTrailingWhitespaceCommand';
import { ICodeActionsOnSaveOptions } from 'vs/editor/common/config/editorOptions';
import { EditOperation } from 'vs/editor/common/core/editOperation';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import { Position } from 'vs/editor/common/core/position';
import { trimTrailingWhitespace } from 'vs/editor/common/commands/trimTrailingWhitespaceCommand';
import { IIdentifiedSingleEditOperation, ISingleEditOperation, ITextModel } from 'vs/editor/common/model';
import { CodeAction } from 'vs/editor/common/modes';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
import { shouldSynchronizeModel } from 'vs/editor/common/services/modelService';
import { getCodeActions } from 'vs/editor/contrib/codeAction/codeAction';
import { applyCodeAction } from 'vs/editor/contrib/codeAction/codeActionCommands';
import { CodeActionKind } from 'vs/editor/contrib/codeAction/codeActionTrigger';
import { getDocumentFormattingEdits, NoProviderError } from 'vs/editor/contrib/format/format';
import { FormattingEdit } from 'vs/editor/contrib/format/formattingEdit';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel';
import { ExtHostContext, ExtHostDocumentSaveParticipantShape, IExtHostContext } from '../node/extHost.protocol';
import { EditOperation } from 'vs/editor/common/core/editOperation';
import { extHostCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IProgressService2, ProgressLocation } from 'vs/platform/progress/common/progress';
import { localize } from 'vs/nls';
import { isNonEmptyArray } from 'vs/base/common/arrays';
import { ILogService } from 'vs/platform/log/common/log';
import { shouldSynchronizeModel } from 'vs/editor/common/services/modelService';
import { SnippetController2 } from 'vs/editor/contrib/snippet/snippetController2';
import { localize } from 'vs/nls';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { CodeActionKind } from 'vs/editor/contrib/codeAction/codeActionTrigger';
import { CodeAction } from 'vs/editor/common/modes';
import { applyCodeAction } from 'vs/editor/contrib/codeAction/codeActionCommands';
import { getCodeActions } from 'vs/editor/contrib/codeAction/codeAction';
import { ICodeActionsOnSaveOptions } from 'vs/editor/common/config/editorOptions';
import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ILogService } from 'vs/platform/log/common/log';
import { IProgressService2, ProgressLocation } from 'vs/platform/progress/common/progress';
import { extHostCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import { TextFileEditorModel } from 'vs/workbench/services/textfile/common/textFileEditorModel';
import { ISaveParticipant, ITextFileEditorModel, SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
import { ExtHostContext, ExtHostDocumentSaveParticipantShape, IExtHostContext } from '../node/extHost.protocol';
// {{SQL CARBON EDIT}}
import { INotebookService } from 'sql/workbench/services/notebook/common/notebookService';
@@ -55,12 +55,13 @@ class NotebookUpdateParticipant implements ISaveParticipantParticipant {
// Nothing
}
public participate(model: ITextFileEditorModel, env: { reason: SaveReason }): void {
public participate(model: ITextFileEditorModel, env: { reason: SaveReason }): Promise<void> {
let uriString = model.getResource().toString();
let notebookEditor = this.notebookService.listNotebookEditors().find((editor) => editor.id === uriString);
if (notebookEditor) {
notebookEditor.notebookParams.input.updateModel();
}
return Promise.resolve();
}
}
@@ -71,13 +72,13 @@ export interface ISaveParticipantParticipant extends ISaveParticipant {
class TrimWhitespaceParticipant implements ISaveParticipantParticipant {
constructor(
@IConfigurationService private configurationService: IConfigurationService,
@ICodeEditorService private codeEditorService: ICodeEditorService
@IConfigurationService private readonly configurationService: IConfigurationService,
@ICodeEditorService private readonly codeEditorService: ICodeEditorService
) {
// Nothing
}
public participate(model: ITextFileEditorModel, env: { reason: SaveReason }): void {
async participate(model: ITextFileEditorModel, env: { reason: SaveReason }): Promise<void> {
if (this.configurationService.getValue('files.trimTrailingWhitespace', { overrideIdentifier: model.textEditorModel.getLanguageIdentifier().language, resource: model.getResource() })) {
this.doTrimTrailingWhitespace(model.textEditorModel, env.reason === SaveReason.AUTO);
}
@@ -133,13 +134,13 @@ function findEditor(model: ITextModel, codeEditorService: ICodeEditorService): I
export class FinalNewLineParticipant implements ISaveParticipantParticipant {
constructor(
@IConfigurationService private configurationService: IConfigurationService,
@ICodeEditorService private codeEditorService: ICodeEditorService
@IConfigurationService private readonly configurationService: IConfigurationService,
@ICodeEditorService private readonly codeEditorService: ICodeEditorService
) {
// Nothing
}
public participate(model: ITextFileEditorModel, env: { reason: SaveReason }): void {
async participate(model: ITextFileEditorModel, env: { reason: SaveReason }): Promise<void> {
if (this.configurationService.getValue('files.insertFinalNewline', { overrideIdentifier: model.textEditorModel.getLanguageIdentifier().language, resource: model.getResource() })) {
this.doInsertFinalNewLine(model.textEditorModel);
}
@@ -171,13 +172,13 @@ export class FinalNewLineParticipant implements ISaveParticipantParticipant {
export class TrimFinalNewLinesParticipant implements ISaveParticipantParticipant {
constructor(
@IConfigurationService private configurationService: IConfigurationService,
@ICodeEditorService private codeEditorService: ICodeEditorService
@IConfigurationService private readonly configurationService: IConfigurationService,
@ICodeEditorService private readonly codeEditorService: ICodeEditorService
) {
// Nothing
}
public participate(model: ITextFileEditorModel, env: { reason: SaveReason }): void {
async participate(model: ITextFileEditorModel, env: { reason: SaveReason }): Promise<void> {
if (this.configurationService.getValue('files.trimFinalNewlines', { overrideIdentifier: model.textEditorModel.getLanguageIdentifier().language, resource: model.getResource() })) {
this.doTrimFinalNewLines(model.textEditorModel, env.reason === SaveReason.AUTO);
}
@@ -247,7 +248,7 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant {
// Nothing
}
participate(editorModel: ITextFileEditorModel, env: { reason: SaveReason }): Promise<void> {
async participate(editorModel: ITextFileEditorModel, env: { reason: SaveReason }): Promise<void> {
const model = editorModel.textEditorModel;
if (env.reason === SaveReason.AUTO
@@ -270,7 +271,7 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant {
}, timeout);
request.then(edits => this._editorWorkerService.computeMoreMinimalEdits(model.uri, edits)).then(resolve, err => {
if (!(err instanceof Error) || err.name !== NoProviderError.Name) {
if (!NoProviderError.is(err)) {
reject(err);
} else {
resolve();
@@ -317,7 +318,7 @@ class FormatOnSaveParticipant implements ISaveParticipantParticipant {
}
}
class CodeActionOnParticipant implements ISaveParticipant {
class CodeActionOnSaveParticipant implements ISaveParticipant {
constructor(
@IBulkEditService private readonly _bulkEditService: IBulkEditService,
@@ -338,17 +339,49 @@ class CodeActionOnParticipant implements ISaveParticipant {
return undefined;
}
const codeActionsOnSave = Object.keys(setting).filter(x => setting[x]).map(x => new CodeActionKind(x));
const codeActionsOnSave = Object.keys(setting)
.filter(x => setting[x]).map(x => new CodeActionKind(x))
.sort((a, b) => {
if (a.value === CodeActionKind.SourceFixAll.value) {
return -1;
}
if (b.value === CodeActionKind.SourceFixAll.value) {
return 1;
}
return 0;
});
if (!codeActionsOnSave.length) {
return undefined;
}
const tokenSource = new CancellationTokenSource();
const timeout = this._configurationService.getValue<number>('editor.codeActionsOnSaveTimeout', settingsOverrides);
return new Promise<CodeAction[]>((resolve, reject) => {
setTimeout(() => reject(localize('codeActionsOnSave.didTimeout', "Aborted codeActionsOnSave after {0}ms", timeout)), timeout);
this.getActionsToRun(model, codeActionsOnSave).then(resolve);
}).then(actionsToRun => this.applyCodeActions(actionsToRun));
return Promise.race([
new Promise<void>((_resolve, reject) =>
setTimeout(() => {
tokenSource.cancel();
reject(localize('codeActionsOnSave.didTimeout', "Aborted codeActionsOnSave after {0}ms", timeout));
}, timeout)),
this.applyOnSaveActions(model, codeActionsOnSave, tokenSource.token)
]).then(() => {
tokenSource.cancel();
}, (e) => {
tokenSource.cancel();
return Promise.reject(e);
});
}
private async applyOnSaveActions(model: ITextModel, codeActionsOnSave: CodeActionKind[], token: CancellationToken): Promise<void> {
for (const codeActionKind of codeActionsOnSave) {
const actionsToRun = await this.getActionsToRun(model, codeActionKind, token);
try {
await this.applyCodeActions(actionsToRun);
} catch {
// Failure to apply a code action should not block other on save actions
}
}
}
private async applyCodeActions(actionsToRun: CodeAction[]) {
@@ -357,13 +390,11 @@ class CodeActionOnParticipant implements ISaveParticipant {
}
}
private async getActionsToRun(model: ITextModel, codeActionsOnSave: CodeActionKind[]) {
const actions = await getCodeActions(model, model.getFullModelRange(), {
private getActionsToRun(model: ITextModel, codeActionKind: CodeActionKind, token: CancellationToken) {
return getCodeActions(model, model.getFullModelRange(), {
type: 'auto',
filter: { kind: CodeActionKind.Source, includeSourceActions: true },
});
const actionsToRun = actions.filter(returnedAction => returnedAction.kind && codeActionsOnSave.some(onSaveKind => onSaveKind.contains(returnedAction.kind)));
return actionsToRun;
filter: { kind: codeActionKind, includeSourceActions: true },
}, token);
}
}
@@ -375,7 +406,7 @@ class ExtHostSaveParticipant implements ISaveParticipantParticipant {
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostDocumentSaveParticipant);
}
participate(editorModel: ITextFileEditorModel, env: { reason: SaveReason }): Promise<void> {
async participate(editorModel: ITextFileEditorModel, env: { reason: SaveReason }): Promise<void> {
if (!shouldSynchronizeModel(editorModel.textEditorModel)) {
// the model never made it to the extension
@@ -411,7 +442,7 @@ export class SaveParticipant implements ISaveParticipant {
) {
this._saveParticipants = new IdleValue(() => [
instantiationService.createInstance(TrimWhitespaceParticipant),
instantiationService.createInstance(CodeActionOnParticipant),
instantiationService.createInstance(CodeActionOnSaveParticipant),
instantiationService.createInstance(FormatOnSaveParticipant),
instantiationService.createInstance(FinalNewLineParticipant),
instantiationService.createInstance(TrimFinalNewLinesParticipant),
@@ -428,11 +459,11 @@ export class SaveParticipant implements ISaveParticipant {
this._saveParticipants.dispose();
}
participate(model: ITextFileEditorModel, env: { reason: SaveReason }): Thenable<void> {
async participate(model: ITextFileEditorModel, env: { reason: SaveReason }): Promise<void> {
return this._progressService.withProgress({ location: ProgressLocation.Window }, progress => {
progress.report({ message: localize('saveParticipants', "Running Save Participants...") });
const promiseFactory = this._saveParticipants.getValue().map(p => () => {
return Promise.resolve(p.participate(model, env));
return p.participate(model, env);
});
return sequence(promiseFactory).then(() => { }, err => this._logService.warn(err));
});

View File

@@ -140,7 +140,7 @@ class RemoteSearchProvider implements ISearchResultProvider, IDisposable {
return Promise.resolve(this._proxy.$clearCache(cacheKey));
}
handleFindMatch(session: number, dataOrUri: (UriComponents | IRawFileMatch2)[]): void {
handleFindMatch(session: number, dataOrUri: Array<UriComponents | IRawFileMatch2>): void {
if (!this._searches.has(session)) {
// ignore...
return;

View File

@@ -8,6 +8,7 @@ import { IDisposable } from 'vs/base/common/lifecycle';
import { MainThreadStatusBarShape, MainContext, IExtHostContext } from '../node/extHost.protocol';
import { ThemeColor } from 'vs/platform/theme/common/themeService';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
@extHostNamedCustomer(MainContext.MainThreadStatusBar)
export class MainThreadStatusBar implements MainThreadStatusBarShape {
@@ -27,7 +28,7 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape {
}
}
$setEntry(id: number, extensionId: string, text: string, tooltip: string, command: string, color: string | ThemeColor, alignment: MainThreadStatusBarAlignment, priority: number): void {
$setEntry(id: number, extensionId: ExtensionIdentifier, text: string, tooltip: string, command: string, color: string | ThemeColor, alignment: MainThreadStatusBarAlignment, priority: number): void {
// Dispose any old
this.$dispose(id);

View File

@@ -39,7 +39,7 @@ export class MainThreadStorage implements MainThreadStorageShape {
this._storageListener.dispose();
}
$getValue<T>(shared: boolean, key: string): Thenable<T> {
$getValue<T>(shared: boolean, key: string): Promise<T> {
if (shared) {
this._sharedStorageKeysToWatch.set(key, true);
}
@@ -58,7 +58,7 @@ export class MainThreadStorage implements MainThreadStorageShape {
return JSON.parse(jsonValue);
}
$setValue(shared: boolean, key: string, value: object): Thenable<void> {
$setValue(shared: boolean, key: string, value: object): Promise<void> {
let jsonValue: string;
try {
jsonValue = JSON.stringify(value);

View File

@@ -16,8 +16,8 @@ import { IDisposable } from 'vs/base/common/lifecycle';
import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import {
ContributedTask, ExtensionTaskSourceTransfer, KeyedTaskIdentifier, TaskExecution, Task, TaskEvent, TaskEventKind,
PresentationOptions, CommandOptions, CommandConfiguration, RuntimeType, CustomTask, TaskScope, TaskSource, TaskSourceKind, ExtensionTaskSource, RevealKind, PanelKind, RunOptions
ContributedTask, KeyedTaskIdentifier, TaskExecution, Task, TaskEvent, TaskEventKind,
PresentationOptions, CommandOptions, CommandConfiguration, RuntimeType, CustomTask, TaskScope, TaskSource, TaskSourceKind, ExtensionTaskSource, RunOptions, TaskSet
} from 'vs/workbench/parts/tasks/common/tasks';
@@ -76,7 +76,7 @@ namespace TaskDefinitionDTO {
}
export function to(value: TaskDefinitionDTO, executeOnly: boolean): KeyedTaskIdentifier {
let result = TaskDefinition.createTaskIdentifier(value, console);
if (result === void 0 && executeOnly) {
if (result === undefined && executeOnly) {
result = {
_key: generateUuid(),
type: '$executeOnly'
@@ -88,31 +88,37 @@ namespace TaskDefinitionDTO {
namespace TaskPresentationOptionsDTO {
export function from(value: PresentationOptions): TaskPresentationOptionsDTO {
if (value === void 0 || value === null) {
if (value === undefined || value === null) {
return undefined;
}
return Objects.assign(Object.create(null), value);
}
export function to(value: TaskPresentationOptionsDTO): PresentationOptions {
if (value === void 0 || value === null) {
return { reveal: RevealKind.Always, echo: true, focus: false, panel: PanelKind.Shared, showReuseMessage: true, clear: false };
if (value === undefined || value === null) {
return PresentationOptions.defaults;
}
return Objects.assign(Object.create(null), value);
return Objects.assign(Object.create(null), PresentationOptions.defaults, value);
}
}
namespace RunOptionsDTO {
export function from(value: RunOptions): RunOptionsDTO {
if (value === void 0 || value === null) {
if (value === undefined || value === null) {
return undefined;
}
return Objects.assign(Object.create(null), value);
}
export function to(value: RunOptionsDTO): RunOptions {
if (value === undefined || value === null) {
return RunOptions.defaults;
}
return Objects.assign(Object.create(null), RunOptions.defaults, value);
}
}
namespace ProcessExecutionOptionsDTO {
export function from(value: CommandOptions): ProcessExecutionOptionsDTO {
if (value === void 0 || value === null) {
if (value === undefined || value === null) {
return undefined;
}
return {
@@ -121,11 +127,11 @@ namespace ProcessExecutionOptionsDTO {
};
}
export function to(value: ProcessExecutionOptionsDTO): CommandOptions {
if (value === void 0 || value === null) {
return undefined;
if (value === undefined || value === null) {
return CommandOptions.defaults;
}
return {
cwd: value.cwd,
cwd: value.cwd || CommandOptions.defaults.cwd,
env: value.env
};
}
@@ -155,20 +161,18 @@ namespace ProcessExecutionDTO {
args: value.args,
presentation: undefined
};
if (value.options) {
result.options = ProcessExecutionOptionsDTO.to(value.options);
}
result.options = ProcessExecutionOptionsDTO.to(value.options);
return result;
}
}
namespace ShellExecutionOptionsDTO {
export function from(value: CommandOptions): ShellExecutionOptionsDTO {
if (value === void 0 || value === null) {
if (value === undefined || value === null) {
return undefined;
}
let result: ShellExecutionOptionsDTO = {
cwd: value.cwd,
cwd: value.cwd || CommandOptions.defaults.cwd,
env: value.env
};
if (value.shell) {
@@ -179,7 +183,7 @@ namespace ShellExecutionOptionsDTO {
return result;
}
export function to(value: ShellExecutionOptionsDTO): CommandOptions {
if (value === void 0 || value === null) {
if (value === undefined || value === null) {
return undefined;
}
let result: CommandOptions = {
@@ -208,7 +212,7 @@ namespace ShellExecutionDTO {
}
export function from(value: CommandConfiguration): ShellExecutionDTO {
let result: ShellExecutionDTO = {};
if (value.name && Types.isString(value.name) && (value.args === void 0 || value.args === null || value.args.length === 0)) {
if (value.name && Types.isString(value.name) && (value.args === undefined || value.args === null || value.args.length === 0)) {
result.commandLine = value.name;
} else {
result.command = value.name;
@@ -254,7 +258,7 @@ namespace TaskSourceDTO {
export function to(value: TaskSourceDTO, workspace: IWorkspaceContextService): ExtensionTaskSource {
let scope: TaskScope;
let workspaceFolder: IWorkspaceFolder;
if ((value.scope === void 0) || ((typeof value.scope === 'number') && (value.scope !== TaskScope.Global))) {
if ((value.scope === undefined) || ((typeof value.scope === 'number') && (value.scope !== TaskScope.Global))) {
if (workspace.getWorkspace().folders.length === 0) {
scope = TaskScope.Global;
workspaceFolder = undefined;
@@ -288,23 +292,23 @@ namespace TaskHandleDTO {
namespace TaskDTO {
export function from(task: Task): TaskDTO {
if (task === void 0 || task === null || (!CustomTask.is(task) && !ContributedTask.is(task))) {
if (task === undefined || task === null || (!CustomTask.is(task) && !ContributedTask.is(task))) {
return undefined;
}
let result: TaskDTO = {
_id: task._id,
name: task.name,
definition: TaskDefinitionDTO.from(Task.getTaskDefinition(task)),
name: task.configurationProperties.name,
definition: TaskDefinitionDTO.from(task.getDefinition()),
source: TaskSourceDTO.from(task._source),
execution: undefined,
presentationOptions: task.command ? TaskPresentationOptionsDTO.from(task.command.presentation) : undefined,
isBackground: task.isBackground,
isBackground: task.configurationProperties.isBackground,
problemMatchers: [],
hasDefinedMatchers: ContributedTask.is(task) ? task.hasDefinedMatchers : false,
runOptions: RunOptionsDTO.from(task.runOptions),
};
if (task.group) {
result.group = task.group;
if (task.configurationProperties.group) {
result.group = task.configurationProperties.group;
}
if (task.command) {
if (task.command.runtime === RuntimeType.Process) {
@@ -313,8 +317,8 @@ namespace TaskDTO {
result.execution = ShellExecutionDTO.from(task.command);
}
}
if (task.problemMatchers) {
for (let matcher of task.problemMatchers) {
if (task.configurationProperties.problemMatchers) {
for (let matcher of task.configurationProperties.problemMatchers) {
if (Types.isString(matcher)) {
result.problemMatchers.push(matcher);
}
@@ -323,7 +327,7 @@ namespace TaskDTO {
return result;
}
export function to(task: TaskDTO, workspace: IWorkspaceContextService, executeOnly: boolean): Task {
export function to(task: TaskDTO, workspace: IWorkspaceContextService, executeOnly: boolean): ContributedTask {
if (typeof task.name !== 'string') {
return undefined;
}
@@ -337,28 +341,28 @@ namespace TaskDTO {
return undefined;
}
command.presentation = TaskPresentationOptionsDTO.to(task.presentationOptions);
command.presentation = Objects.assign(command.presentation || ({} as PresentationOptions), { echo: true, reveal: RevealKind.Always, focus: false, panel: PanelKind.Shared });
let source = TaskSourceDTO.to(task.source, workspace);
let label = nls.localize('task.label', '{0}: {1}', source.label, task.name);
let definition = TaskDefinitionDTO.to(task.definition, executeOnly);
let id = `${task.source.extensionId}.${definition._key}`;
let result: ContributedTask = {
_id: id, // uuidMap.getUUID(identifier)
_source: source,
_label: label,
type: definition.type,
defines: definition,
name: task.name,
identifier: label,
group: task.group,
command: command,
isBackground: !!task.isBackground,
problemMatchers: task.problemMatchers.slice(),
hasDefinedMatchers: task.hasDefinedMatchers,
runOptions: task.runOptions,
};
let result: ContributedTask = new ContributedTask(
id, // uuidMap.getUUID(identifier)
source,
label,
definition.type,
definition,
command,
task.hasDefinedMatchers,
RunOptionsDTO.to(task.runOptions),
{
name: task.name,
identifier: label,
group: task.group,
isBackground: !!task.isBackground,
problemMatchers: task.problemMatchers.slice(),
}
);
return result;
}
}
@@ -390,13 +394,13 @@ export class MainThreadTask implements MainThreadTaskShape {
this._taskService.onDidStateChange((event: TaskEvent) => {
let task = event.__task;
if (event.kind === TaskEventKind.Start) {
this._proxy.$onDidStartTask(TaskExecutionDTO.from(Task.getTaskExecution(task)));
this._proxy.$onDidStartTask(TaskExecutionDTO.from(task.getTaskExecution()));
} else if (event.kind === TaskEventKind.ProcessStarted) {
this._proxy.$onDidStartTaskProcess(TaskProcessStartedDTO.from(Task.getTaskExecution(task), event.processId));
this._proxy.$onDidStartTaskProcess(TaskProcessStartedDTO.from(task.getTaskExecution(), event.processId));
} else if (event.kind === TaskEventKind.ProcessEnded) {
this._proxy.$onDidEndTaskProcess(TaskProcessEndedDTO.from(Task.getTaskExecution(task), event.exitCode));
this._proxy.$onDidEndTaskProcess(TaskProcessEndedDTO.from(task.getTaskExecution(), event.exitCode));
} else if (event.kind === TaskEventKind.End) {
this._proxy.$OnDidEndTask(TaskExecutionDTO.from(Task.getTaskExecution(task)));
this._proxy.$OnDidEndTask(TaskExecutionDTO.from(task.getTaskExecution()));
}
});
}
@@ -408,29 +412,23 @@ export class MainThreadTask implements MainThreadTaskShape {
this._providers.clear();
}
public $registerTaskProvider(handle: number): Thenable<void> {
public $registerTaskProvider(handle: number): Promise<void> {
let provider: ITaskProvider = {
provideTasks: (validTypes: IStringDictionary<boolean>) => {
return Promise.resolve(this._proxy.$provideTasks(handle, validTypes)).then((value) => {
let tasks: Task[] = [];
for (let task of value.tasks) {
let taskTransfer = task._source as any as ExtensionTaskSourceTransfer;
if (taskTransfer.__workspaceFolder !== void 0 && taskTransfer.__definition !== void 0) {
(task._source as any).workspaceFolder = this._workspaceContextServer.getWorkspaceFolder(URI.revive(taskTransfer.__workspaceFolder));
delete taskTransfer.__workspaceFolder;
let taskIdentifier = TaskDefinition.createTaskIdentifier(taskTransfer.__definition, console);
delete taskTransfer.__definition;
if (taskIdentifier !== void 0) {
(task as ContributedTask).defines = taskIdentifier;
task._id = `${task._id}.${taskIdentifier._key}`;
tasks.push(task);
}
for (let dto of value.tasks) {
let task = TaskDTO.to(dto, this._workspaceContextServer, true);
if (task) {
tasks.push(task);
} else {
console.warn(`Dropping task ${task.name}. Missing workspace folder and task definition`);
console.error(`Task System: can not convert task: ${JSON.stringify(dto.definition, undefined, 0)}. Task will be dropped`);
}
}
value.tasks = tasks;
return value;
return {
tasks,
extension: value.extension
} as TaskSet;
});
}
};
@@ -439,12 +437,12 @@ export class MainThreadTask implements MainThreadTaskShape {
return Promise.resolve(undefined);
}
public $unregisterTaskProvider(handle: number): Thenable<void> {
public $unregisterTaskProvider(handle: number): Promise<void> {
this._providers.delete(handle);
return Promise.resolve(undefined);
}
public $fetchTasks(filter?: TaskFilterDTO): Thenable<TaskDTO[]> {
public $fetchTasks(filter?: TaskFilterDTO): Promise<TaskDTO[]> {
return this._taskService.tasks(TaskFilterDTO.to(filter)).then((tasks) => {
let result: TaskDTO[] = [];
for (let task of tasks) {
@@ -457,7 +455,7 @@ export class MainThreadTask implements MainThreadTaskShape {
});
}
public $executeTask(value: TaskHandleDTO | TaskDTO): Thenable<TaskExecutionDTO> {
public $executeTask(value: TaskHandleDTO | TaskDTO): Promise<TaskExecutionDTO> {
return new Promise<TaskExecutionDTO>((resolve, reject) => {
if (TaskHandleDTO.is(value)) {
let workspaceFolder = this._workspaceContextServer.getWorkspaceFolder(URI.revive(value.workspaceFolder));
@@ -487,7 +485,7 @@ export class MainThreadTask implements MainThreadTaskShape {
});
}
public $terminateTask(id: string): Thenable<void> {
public $terminateTask(id: string): Promise<void> {
return new Promise<void>((resolve, reject) => {
this._taskService.getActiveTasks().then((tasks) => {
for (let task of tasks) {

View File

@@ -20,7 +20,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
constructor(
extHostContext: IExtHostContext,
@ITerminalService private terminalService: ITerminalService
@ITerminalService private readonly terminalService: ITerminalService
) {
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostTerminalService);
this._remoteAuthority = extHostContext.remoteAuthority;
@@ -55,7 +55,7 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
// when the extension host process goes down ?
}
public $createTerminal(name?: string, shellPath?: string, shellArgs?: string[], cwd?: string, env?: { [key: string]: string }, waitOnExit?: boolean): Thenable<number> {
public $createTerminal(name?: string, shellPath?: string, shellArgs?: string[], cwd?: string, env?: { [key: string]: string }, waitOnExit?: boolean, strictEnv?: boolean): Promise<{ id: number, name: string }> {
const shellLaunchConfig: IShellLaunchConfig = {
name,
executable: shellPath,
@@ -63,12 +63,17 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
cwd,
waitOnExit,
ignoreConfigurationCwd: true,
env
env,
strictEnv
};
return Promise.resolve(this.terminalService.createTerminal(shellLaunchConfig).id);
const terminal = this.terminalService.createTerminal(shellLaunchConfig);
return Promise.resolve({
id: terminal.id,
name: terminal.title
});
}
public $createTerminalRenderer(name: string): Thenable<number> {
public $createTerminalRenderer(name: string): Promise<number> {
const instance = this.terminalService.createTerminalRenderer(name);
return Promise.resolve(instance.id);
}
@@ -216,6 +221,8 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
request.proxy.onInput(data => this._proxy.$acceptProcessInput(request.proxy.terminalId, data));
request.proxy.onResize(dimensions => this._proxy.$acceptProcessResize(request.proxy.terminalId, dimensions.cols, dimensions.rows));
request.proxy.onShutdown(immediate => this._proxy.$acceptProcessShutdown(request.proxy.terminalId, immediate));
request.proxy.onRequestCwd(() => this._proxy.$acceptProcessRequestCwd(request.proxy.terminalId));
request.proxy.onRequestInitialCwd(() => this._proxy.$acceptProcessRequestInitialCwd(request.proxy.terminalId));
}
public $sendProcessTitle(terminalId: number, title: string): void {
@@ -234,4 +241,12 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape
this._terminalProcesses[terminalId].emitExit(exitCode);
delete this._terminalProcesses[terminalId];
}
public $sendProcessInitialCwd(terminalId: number, initialCwd: string): void {
this._terminalProcesses[terminalId].emitInitialCwd(initialCwd);
}
public $sendProcessCwd(terminalId: number, cwd: string): void {
this._terminalProcesses[terminalId].emitCwd(cwd);
}
}

View File

@@ -5,7 +5,7 @@
import { Disposable } from 'vs/base/common/lifecycle';
import { ExtHostContext, MainThreadTreeViewsShape, ExtHostTreeViewsShape, MainContext, IExtHostContext } from '../node/extHost.protocol';
import { ITreeViewDataProvider, ITreeItem, IViewsService, ITreeView, ViewsRegistry, ICustomViewDescriptor, IRevealOptions } from 'vs/workbench/common/views';
import { ITreeViewDataProvider, ITreeItem, IViewsService, ITreeView, ViewsRegistry, ITreeViewDescriptor, IRevealOptions } from 'vs/workbench/common/views';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import { distinct } from 'vs/base/common/arrays';
import { INotificationService } from 'vs/platform/notification/common/notification';
@@ -20,8 +20,8 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie
constructor(
extHostContext: IExtHostContext,
@IViewsService private viewsService: IViewsService,
@INotificationService private notificationService: INotificationService,
@IViewsService private readonly viewsService: IViewsService,
@INotificationService private readonly notificationService: INotificationService
) {
super();
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostTreeViews);
@@ -41,7 +41,7 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie
}
}
$reveal(treeViewId: string, item: ITreeItem, parentChain: ITreeItem[], options: IRevealOptions): Thenable<void> {
$reveal(treeViewId: string, item: ITreeItem, parentChain: ITreeItem[], options: IRevealOptions): Promise<void> {
return this.viewsService.openView(treeViewId, options.focus)
.then(() => {
const viewer = this.getTreeView(treeViewId);
@@ -49,12 +49,12 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie
});
}
$refresh(treeViewId: string, itemsToRefreshByHandle: { [treeItemHandle: string]: ITreeItem }): Thenable<void> {
$refresh(treeViewId: string, itemsToRefreshByHandle: { [treeItemHandle: string]: ITreeItem }): Promise<void> {
const viewer = this.getTreeView(treeViewId);
const dataProvider = this._dataProviders.get(treeViewId);
if (viewer && dataProvider) {
const itemsToRefresh = dataProvider.getItemsToRefresh(itemsToRefreshByHandle);
return viewer.refresh(itemsToRefresh.length ? itemsToRefresh : void 0);
return viewer.refresh(itemsToRefresh.length ? itemsToRefresh : undefined);
}
return null;
}
@@ -110,7 +110,7 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie
}
private getTreeView(treeViewId: string): ITreeView {
const viewDescriptor: ICustomViewDescriptor = <ICustomViewDescriptor>ViewsRegistry.getView(treeViewId);
const viewDescriptor: ITreeViewDescriptor = <ITreeViewDescriptor>ViewsRegistry.getView(treeViewId);
return viewDescriptor ? viewDescriptor.treeView : null;
}
@@ -143,7 +143,7 @@ export class TreeViewDataProvider implements ITreeViewDataProvider {
}
getChildren(treeItem?: ITreeItem): Promise<ITreeItem[]> {
return Promise.resolve(this._proxy.$getChildren(this.treeViewId, treeItem ? treeItem.handle : void 0)
return Promise.resolve(this._proxy.$getChildren(this.treeViewId, treeItem ? treeItem.handle : undefined)
.then(
children => this.postGetChildren(children),
err => {

View File

@@ -9,17 +9,18 @@ import { IURLService, IURLHandler } from 'vs/platform/url/common/url';
import { URI } from 'vs/base/common/uri';
import { IDisposable } from 'vs/base/common/lifecycle';
import { IExtensionUrlHandler } from 'vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
class ExtensionUrlHandler implements IURLHandler {
constructor(
private readonly proxy: ExtHostUrlsShape,
private readonly handle: number,
readonly extensionId: string
readonly extensionId: ExtensionIdentifier
) { }
handleURL(uri: URI): Promise<boolean> {
if (uri.authority !== this.extensionId) {
if (!ExtensionIdentifier.equals(this.extensionId, uri.authority)) {
return Promise.resolve(false);
}
@@ -31,31 +32,31 @@ class ExtensionUrlHandler implements IURLHandler {
export class MainThreadUrls implements MainThreadUrlsShape {
private readonly proxy: ExtHostUrlsShape;
private handlers = new Map<number, { extensionId: string, disposable: IDisposable }>();
private handlers = new Map<number, { extensionId: ExtensionIdentifier, disposable: IDisposable }>();
constructor(
context: IExtHostContext,
@IURLService private urlService: IURLService,
@IExtensionUrlHandler private inactiveExtensionUrlHandler: IExtensionUrlHandler
@IURLService private readonly urlService: IURLService,
@IExtensionUrlHandler private readonly inactiveExtensionUrlHandler: IExtensionUrlHandler
) {
this.proxy = context.getProxy(ExtHostContext.ExtHostUrls);
}
$registerUriHandler(handle: number, extensionId: string): Thenable<void> {
$registerUriHandler(handle: number, extensionId: ExtensionIdentifier): Promise<void> {
const handler = new ExtensionUrlHandler(this.proxy, handle, extensionId);
const disposable = this.urlService.registerHandler(handler);
this.handlers.set(handle, { extensionId, disposable });
this.inactiveExtensionUrlHandler.registerExtensionHandler(extensionId, handler);
return Promise.resolve(null);
return Promise.resolve(undefined);
}
$unregisterUriHandler(handle: number): Thenable<void> {
$unregisterUriHandler(handle: number): Promise<void> {
const tuple = this.handlers.get(handle);
if (!tuple) {
return Promise.resolve(null);
return Promise.resolve(undefined);
}
const { extensionId, disposable } = tuple;
@@ -64,7 +65,7 @@ export class MainThreadUrls implements MainThreadUrlsShape {
this.handlers.delete(handle);
disposable.dispose();
return Promise.resolve(null);
return Promise.resolve(undefined);
}
dispose(): void {

View File

@@ -19,6 +19,8 @@ import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorG
import * as vscode from 'vscode';
import { extHostNamedCustomer } from './extHostCustomers';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { onUnexpectedError } from 'vs/base/common/errors';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
@extHostNamedCustomer(MainContext.MainThreadWebviews)
export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviver {
@@ -68,7 +70,7 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
title: string,
showOptions: { viewColumn: EditorViewColumn | null, preserveFocus: boolean },
options: WebviewInputOptions,
extensionId: string,
extensionId: ExtensionIdentifier,
extensionLocation: UriComponents
): void {
const mainThreadShowOptions: ICreateWebViewShowOptions = Object.create(null);
@@ -91,7 +93,7 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
"extensionId" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
this._telemetryService.publicLog('webviews:createWebviewPanel', { extensionId: extensionId });
this._telemetryService.publicLog('webviews:createWebviewPanel', { extensionId: extensionId.value });
}
public $disposeWebview(handle: WebviewPanelHandle): void {
@@ -130,7 +132,7 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
this._webviewService.revealWebview(webview, targetGroup || this._editorGroupService.activeGroup, showOptions.preserveFocus);
}
public $postMessage(handle: WebviewPanelHandle, message: any): Thenable<boolean> {
public $postMessage(handle: WebviewPanelHandle, message: any): Promise<boolean> {
const webview = this.getWebview(handle);
const editors = this._editorService.visibleControls
.filter(e => e instanceof WebviewEditor)
@@ -169,7 +171,9 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
}
return this._proxy.$deserializeWebviewPanel(handle, webview.state.viewType, webview.getTitle(), state, editorGroupToViewColumn(this._editorGroupService, webview.group), webview.options)
.then(undefined, () => {
.then(undefined, error => {
onUnexpectedError(error);
webview.html = MainThreadWebviews.getDeserializationFailedContents(viewType);
});
}));

View File

@@ -3,11 +3,12 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IWindowService } from 'vs/platform/windows/common/windows';
import { MainThreadWindowShape, ExtHostWindowShape, ExtHostContext, MainContext, IExtHostContext } from '../node/extHost.protocol';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { Event } from 'vs/base/common/event';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { URI, UriComponents } from 'vs/base/common/uri';
import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import { latch } from 'vs/base/common/event';
import { ExtHostContext, ExtHostWindowShape, IExtHostContext, MainContext, MainThreadWindowShape } from '../node/extHost.protocol';
@extHostNamedCustomer(MainContext.MainThreadWindow)
export class MainThreadWindow implements MainThreadWindowShape {
@@ -17,19 +18,24 @@ export class MainThreadWindow implements MainThreadWindowShape {
constructor(
extHostContext: IExtHostContext,
@IWindowService private windowService: IWindowService
@IWindowService private readonly windowService: IWindowService,
@IWindowsService private readonly windowsService: IWindowsService
) {
this.proxy = extHostContext.getProxy(ExtHostContext.ExtHostWindow);
latch(windowService.onDidChangeFocus)
Event.latch(windowService.onDidChangeFocus)
(this.proxy.$onDidChangeWindowFocus, this.proxy, this.disposables);
}
$getWindowVisibility(): Thenable<boolean> {
return this.windowService.isFocused();
}
dispose(): void {
this.disposables = dispose(this.disposables);
}
$getWindowVisibility(): Promise<boolean> {
return this.windowService.isFocused();
}
$openUri(uri: UriComponents): Promise<boolean> {
return this.windowsService.openExternal(URI.revive(uri).toString(true));
}
}

View File

@@ -9,10 +9,9 @@ import { URI, UriComponents } from 'vs/base/common/uri';
import { localize } from 'vs/nls';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { ILabelService } from 'vs/platform/label/common/label';
import { IFolderQuery, IPatternInfo, ISearchConfiguration, ISearchProgressItem, ISearchService, QueryType, IFileQuery } from 'vs/platform/search/common/search';
import { IFolderQuery, IPatternInfo, ISearchConfiguration, ISearchProgressItem, ISearchService, QueryType, IFileQuery, IFileMatch } from 'vs/platform/search/common/search';
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
@@ -24,6 +23,7 @@ import { IWorkspaceEditingService } from 'vs/workbench/services/workspace/common
import { ExtHostContext, ExtHostWorkspaceShape, IExtHostContext, MainContext, MainThreadWorkspaceShape } from '../node/extHost.protocol';
import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation';
import { TextSearchComplete } from 'vscode';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
@extHostNamedCustomer(MainContext.MainThreadWorkspace)
export class MainThreadWorkspace implements MainThreadWorkspaceShape {
@@ -60,7 +60,7 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
// --- workspace ---
$updateWorkspaceFolders(extensionName: string, index: number, deleteCount: number, foldersToAdd: { uri: UriComponents, name?: string }[]): Thenable<void> {
$updateWorkspaceFolders(extensionName: string, index: number, deleteCount: number, foldersToAdd: { uri: UriComponents, name?: string }[]): Promise<void> {
const workspaceFoldersToAdd = foldersToAdd.map(f => ({ uri: URI.revive(f.uri), name: f.name }));
// Indicate in status message
@@ -113,7 +113,7 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
// --- search ---
$startFileSearch(includePattern: string, _includeFolder: UriComponents, excludePatternOrDisregardExcludes: string | false, maxResults: number, token: CancellationToken): Thenable<URI[]> {
$startFileSearch(includePattern: string, _includeFolder: UriComponents, excludePatternOrDisregardExcludes: string | false, maxResults: number, token: CancellationToken): Promise<URI[]> {
const includeFolder = URI.revive(_includeFolder);
const workspace = this._contextService.getWorkspace();
if (!workspace.folders.length) {
@@ -131,11 +131,6 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
return undefined; // invalid query parameters
}
const useRipgrep = folderQueries.every(folderQuery => {
const folderConfig = this._configurationService.getValue<ISearchConfiguration>({ resource: folderQuery.folder });
return folderConfig.search.useRipgrep;
});
const ignoreSymlinks = folderQueries.every(folderQuery => {
const folderConfig = this._configurationService.getValue<ISearchConfiguration>({ resource: folderQuery.folder });
return !folderConfig.search.followSymlinks;
@@ -151,7 +146,6 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
type: QueryType.File,
maxResults,
disregardExcludeSettings: excludePatternOrDisregardExcludes === false,
useRipgrep,
_reason: 'startFileSearch'
};
if (typeof includePattern === 'string') {
@@ -174,7 +168,7 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
});
}
$startTextSearch(pattern: IPatternInfo, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Thenable<TextSearchComplete> {
$startTextSearch(pattern: IPatternInfo, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Promise<TextSearchComplete> {
const workspace = this._contextService.getWorkspace();
const folders = workspace.folders.map(folder => folder.uri);
@@ -183,8 +177,8 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
query._reason = 'startTextSearch';
const onProgress = (p: ISearchProgressItem) => {
if (p.results) {
this._proxy.$handleTextSearchResult(p, requestId);
if ((<IFileMatch>p).results) {
this._proxy.$handleTextSearchResult(<IFileMatch>p, requestId);
}
};
@@ -203,7 +197,7 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
return search;
}
$checkExists(includes: string[], token: CancellationToken): Thenable<boolean> {
$checkExists(includes: string[], token: CancellationToken): Promise<boolean> {
const queryBuilder = this._instantiationService.createInstance(QueryBuilder);
const folders = this._contextService.getWorkspace().folders.map(folder => folder.uri);
const query = queryBuilder.file(folders, {
@@ -227,13 +221,13 @@ export class MainThreadWorkspace implements MainThreadWorkspaceShape {
// --- save & edit resources ---
$saveAll(includeUntitled?: boolean): Thenable<boolean> {
$saveAll(includeUntitled?: boolean): Promise<boolean> {
return this._textFileService.saveAll(includeUntitled).then(result => {
return result.results.every(each => each.success === true);
});
}
$resolveProxy(url: string): Thenable<string> {
$resolveProxy(url: string): Promise<string> {
return this._windowService.resolveProxy(url);
}
}
@@ -246,10 +240,10 @@ CommandsRegistry.registerCommand('_workbench.enterWorkspace', async function (ac
if (disableExtensions && disableExtensions.length) {
const runningExtensions = await extensionService.getExtensions();
// If requested extension to disable is running, then reload window with given workspace
if (disableExtensions && runningExtensions.some(runningExtension => disableExtensions.some(id => areSameExtensions({ id }, { id: runningExtension.id })))) {
if (disableExtensions && runningExtensions.some(runningExtension => disableExtensions.some(id => ExtensionIdentifier.equals(runningExtension.identifier, id)))) {
return windowService.openWindow([URI.file(workspace.fsPath)], { args: { _: [], 'disable-extension': disableExtensions } });
}
}
return workspaceEditingService.enterWorkspace(workspace.fsPath);
return workspaceEditingService.enterWorkspace(workspace);
});

View File

@@ -3,15 +3,21 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { tmpdir } from 'os';
import { posix } from 'path';
import * as vscode from 'vscode';
import { URI } from 'vs/base/common/uri';
import { isMalformedFileUri } from 'vs/base/common/resources';
import * as vscode from 'vscode';
import * as typeConverters from 'vs/workbench/api/node/extHostTypeConverters';
import { CommandsRegistry, ICommandService, ICommandHandler } from 'vs/platform/commands/common/commands';
import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { EditorViewColumn } from 'vs/workbench/api/shared/editor';
import { EditorGroupLayout } from 'vs/workbench/services/group/common/editorGroupsService';
import { isWindows } from 'vs/base/common/platform';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { IWindowsService } from 'vs/platform/windows/common/windows';
import { IDownloadService } from 'vs/platform/download/common/download';
import { generateUuid } from 'vs/base/common/uuid';
// -----------------------------------------------------------------
// The following commands are registered on both sides separately.
@@ -21,7 +27,7 @@ import { isWindows } from 'vs/base/common/platform';
// -----------------------------------------------------------------
export interface ICommandsExecutor {
executeCommand<T>(id: string, ...args: any[]): Thenable<T>;
executeCommand<T>(id: string, ...args: any[]): Promise<T>;
}
function adjustHandler(handler: (executor: ICommandsExecutor, ...args: any[]) => any): ICommandHandler {
@@ -32,7 +38,7 @@ function adjustHandler(handler: (executor: ICommandsExecutor, ...args: any[]) =>
export class PreviewHTMLAPICommand {
public static ID = 'vscode.previewHtml';
public static execute(executor: ICommandsExecutor, uri: URI, position?: vscode.ViewColumn, label?: string, options?: any): Thenable<any> {
public static execute(executor: ICommandsExecutor, uri: URI, position?: vscode.ViewColumn, label?: string, options?: any): Promise<any> {
return executor.executeCommand('_workbench.previewHtml',
uri,
typeof position === 'number' && typeConverters.ViewColumn.from(position),
@@ -45,7 +51,7 @@ CommandsRegistry.registerCommand(PreviewHTMLAPICommand.ID, adjustHandler(Preview
export class OpenFolderAPICommand {
public static ID = 'vscode.openFolder';
public static execute(executor: ICommandsExecutor, uri?: URI, forceNewWindow?: boolean): Thenable<any> {
public static execute(executor: ICommandsExecutor, uri?: URI, forceNewWindow?: boolean): Promise<any> {
if (!uri) {
return executor.executeCommand('_files.pickFolderAndOpen', forceNewWindow);
}
@@ -56,14 +62,14 @@ export class OpenFolderAPICommand {
uri = correctedUri;
}
return executor.executeCommand('_files.windowOpen', [uri], forceNewWindow);
return executor.executeCommand('_files.windowOpen', { folderURIs: [uri], forceNewWindow });
}
}
CommandsRegistry.registerCommand(OpenFolderAPICommand.ID, adjustHandler(OpenFolderAPICommand.execute));
export class DiffAPICommand {
public static ID = 'vscode.diff';
public static execute(executor: ICommandsExecutor, left: URI, right: URI, label: string, options?: vscode.TextDocumentShowOptions): Thenable<any> {
public static execute(executor: ICommandsExecutor, left: URI, right: URI, label: string, options?: vscode.TextDocumentShowOptions): Promise<any> {
return executor.executeCommand('_workbench.diff', [
left, right,
label,
@@ -77,7 +83,7 @@ CommandsRegistry.registerCommand(DiffAPICommand.ID, adjustHandler(DiffAPICommand
export class OpenAPICommand {
public static ID = 'vscode.open';
public static execute(executor: ICommandsExecutor, resource: URI, columnOrOptions?: vscode.ViewColumn | vscode.TextDocumentShowOptions, label?: string): Thenable<any> {
public static execute(executor: ICommandsExecutor, resource: URI, columnOrOptions?: vscode.ViewColumn | vscode.TextDocumentShowOptions, label?: string): Promise<any> {
let options: ITextEditorOptions;
let position: EditorViewColumn;
@@ -100,9 +106,15 @@ export class OpenAPICommand {
}
CommandsRegistry.registerCommand(OpenAPICommand.ID, adjustHandler(OpenAPICommand.execute));
CommandsRegistry.registerCommand('_workbench.removeFromRecentlyOpened', function (accessor: ServicesAccessor, path: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI | string) {
const windowsService = accessor.get(IWindowsService);
return windowsService.removeFromRecentlyOpened([path]).then(() => undefined);
});
export class RemoveFromRecentlyOpenedAPICommand {
public static ID = 'vscode.removeFromRecentlyOpened';
public static execute(executor: ICommandsExecutor, path: string): Thenable<any> {
public static execute(executor: ICommandsExecutor, path: string): Promise<any> {
return executor.executeCommand('_workbench.removeFromRecentlyOpened', path);
}
}
@@ -110,8 +122,15 @@ CommandsRegistry.registerCommand(RemoveFromRecentlyOpenedAPICommand.ID, adjustHa
export class SetEditorLayoutAPICommand {
public static ID = 'vscode.setEditorLayout';
public static execute(executor: ICommandsExecutor, layout: EditorGroupLayout): Thenable<any> {
public static execute(executor: ICommandsExecutor, layout: EditorGroupLayout): Promise<any> {
return executor.executeCommand('layoutEditorGroups', layout);
}
}
CommandsRegistry.registerCommand(SetEditorLayoutAPICommand.ID, adjustHandler(SetEditorLayoutAPICommand.execute));
CommandsRegistry.registerCommand(SetEditorLayoutAPICommand.ID, adjustHandler(SetEditorLayoutAPICommand.execute));
CommandsRegistry.registerCommand('_workbench.downloadResource', function (accessor: ServicesAccessor, resource: URI) {
const downloadService = accessor.get(IDownloadService);
const location = posix.join(tmpdir(), generateUuid());
return downloadService.download(resource, location).then(() => URI.file(location));
});

View File

@@ -6,7 +6,7 @@
import { localize } from 'vs/nls';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import * as errors from 'vs/base/common/errors';
import { Emitter, mapEvent } from 'vs/base/common/event';
import { Emitter, Event } from 'vs/base/common/event';
import { TernarySearchTree } from 'vs/base/common/map';
import * as paths from 'vs/base/common/paths';
import * as platform from 'vs/base/common/platform';
@@ -24,7 +24,7 @@ import { ExtHostApiCommands } from 'vs/workbench/api/node/extHostApiCommands';
import { ExtHostClipboard } from 'vs/workbench/api/node/extHostClipboard';
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
import { ExtHostComments } from 'vs/workbench/api/node/extHostComments';
import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration';
import { ExtHostConfiguration, ExtHostConfigProvider } from 'vs/workbench/api/node/extHostConfiguration';
// {{SQL CARBON EDIT}} - Remove ExtHostDebugService
// import { ExtHostDebugService } from 'vs/workbench/api/node/extHostDebugService';
import { ExtHostDecorations } from 'vs/workbench/api/node/extHostDecorations';
@@ -64,16 +64,17 @@ import { IExtensionDescription, throwProposedApiError, checkProposedApiEnabled,
import { ProxyIdentifier } from 'vs/workbench/services/extensions/node/proxyIdentifier';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry';
import * as vscode from 'vscode';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
export interface IExtensionApiFactory {
(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry): typeof vscode;
(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode;
}
function proposedApiFunction<T>(extension: IExtensionDescription, fn: T): T {
if (extension.enableProposedApi) {
return fn;
} else {
return throwProposedApiError.bind(null, extension);
return throwProposedApiError.bind(null, extension) as any as T;
}
}
@@ -112,11 +113,11 @@ export function createApiFactory(
const extHostFileSystem = rpcProtocol.set(ExtHostContext.ExtHostFileSystem, new ExtHostFileSystem(rpcProtocol, extHostLanguageFeatures));
const extHostFileSystemEvent = rpcProtocol.set(ExtHostContext.ExtHostFileSystemEventService, new ExtHostFileSystemEventService(rpcProtocol, extHostDocumentsAndEditors));
const extHostQuickOpen = rpcProtocol.set(ExtHostContext.ExtHostQuickOpen, new ExtHostQuickOpen(rpcProtocol, extHostWorkspace, extHostCommands));
const extHostTerminalService = rpcProtocol.set(ExtHostContext.ExtHostTerminalService, new ExtHostTerminalService(rpcProtocol, extHostConfiguration, extHostLogService));
const extHostTerminalService = rpcProtocol.set(ExtHostContext.ExtHostTerminalService, new ExtHostTerminalService(rpcProtocol, extHostConfiguration, extHostLogService, extHostCommands));
// {{SQL CARBON EDIT}}
// const extHostDebugService = rpcProtocol.set(ExtHostContext.ExtHostDebugService, new ExtHostDebugService(rpcProtocol, extHostWorkspace, extensionService, extHostDocumentsAndEditors, extHostConfiguration, extHostTerminalService, extHostCommands));
const extHostSCM = rpcProtocol.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(rpcProtocol, extHostCommands, extHostLogService));
const extHostSearch = rpcProtocol.set(ExtHostContext.ExtHostSearch, new ExtHostSearch(rpcProtocol, schemeTransformer, extHostLogService, extHostConfiguration));
const extHostSearch = rpcProtocol.set(ExtHostContext.ExtHostSearch, new ExtHostSearch(rpcProtocol, schemeTransformer, extHostLogService));
const extHostTask = rpcProtocol.set(ExtHostContext.ExtHostTask, new ExtHostTask(rpcProtocol, extHostWorkspace, extHostDocumentsAndEditors, extHostConfiguration));
const extHostWindow = rpcProtocol.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(rpcProtocol));
rpcProtocol.set(ExtHostContext.ExtHostExtensionService, extensionService);
@@ -143,7 +144,7 @@ export function createApiFactory(
// Register API-ish commands
ExtHostApiCommands.register(extHostCommands);
return function (extension: IExtensionDescription, extensionRegistry: ExtensionDescriptionRegistry): typeof vscode {
return function (extension: IExtensionDescription, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode {
// Check document selectors for being overly generic. Technically this isn't a problem but
// in practice many extensions say they support `fooLang` but need fs-access to do so. Those
@@ -154,7 +155,7 @@ export function createApiFactory(
let done = (!extension.isUnderDevelopment);
function informOnce(selector: vscode.DocumentSelector) {
if (!done) {
console.info(`Extension '${extension.id}' uses a document selector without scheme. Learn more about this: https://go.microsoft.com/fwlink/?linkid=872305`);
console.info(`Extension '${extension.identifier.value}' uses a document selector without scheme. Learn more about this: https://go.microsoft.com/fwlink/?linkid=872305`);
done = true;
}
}
@@ -182,7 +183,7 @@ export function createApiFactory(
const informOnce = () => {
if (!done) {
done = true;
console.warn(`Extension '${extension.id}' uses the 'vscode.previewHtml' command which is deprecated and will be removed. Please update your extension to use the Webview API: https://go.microsoft.com/fwlink/?linkid=2039309`);
console.warn(`Extension '${extension.identifier.value}' uses the 'vscode.previewHtml' command which is deprecated and will be removed. Please update your extension to use the Webview API: https://go.microsoft.com/fwlink/?linkid=2039309`);
}
};
return (commandId: string) => {
@@ -252,10 +253,13 @@ export function createApiFactory(
},
get onDidChangeLogLevel() {
checkProposedApiEnabled(extension);
return mapEvent(extHostLogService.onDidChangeLogLevel, l => typeConverters.LogLevel.to(l));
return Event.map(extHostLogService.onDidChangeLogLevel, l => typeConverters.LogLevel.to(l));
},
get clipboard(): vscode.Clipboard {
return extHostClipboard;
},
openExternal(uri: URI) {
return extHostWindow.openUri(uri);
}
});
@@ -270,6 +274,9 @@ export function createApiFactory(
},
get all(): Extension<any>[] {
return extensionRegistry.getAllExtensionDescriptions().map((desc) => new Extension(extensionService, desc));
},
get onDidChange() {
return extensionRegistry.onDidChange;
}
};
@@ -312,7 +319,7 @@ export function createApiFactory(
return extHostLanguageFeatures.registerTypeDefinitionProvider(extension, checkSelector(selector), provider);
},
registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider): vscode.Disposable {
return extHostLanguageFeatures.registerHoverProvider(extension, checkSelector(selector), provider, extension.id);
return extHostLanguageFeatures.registerHoverProvider(extension, checkSelector(selector), provider, extension.identifier);
},
registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable {
return extHostLanguageFeatures.registerDocumentHighlightProvider(extension, checkSelector(selector), provider);
@@ -450,7 +457,7 @@ export function createApiFactory(
return extHostDialogs.showSaveDialog(options);
},
createStatusBarItem(position?: vscode.StatusBarAlignment, priority?: number): vscode.StatusBarItem {
return extHostStatusBar.createStatusBarEntry(extension.id, <number>position, priority);
return extHostStatusBar.createStatusBarEntry(extension.identifier, <number>position, priority);
},
setStatusBarMessage(text: string, timeoutOrThenable?: number | Thenable<any>): vscode.Disposable {
return extHostStatusBar.setStatusBarMessage(text, timeoutOrThenable);
@@ -487,17 +494,17 @@ export function createApiFactory(
return extHostWebviews.registerWebviewPanelSerializer(viewType, serializer);
},
registerDecorationProvider: proposedApiFunction(extension, (provider: vscode.DecorationProvider) => {
return extHostDecorations.registerDecorationProvider(provider, extension.id);
return extHostDecorations.registerDecorationProvider(provider, extension.identifier);
}),
registerUriHandler(handler: vscode.UriHandler) {
return extHostUrls.registerUriHandler(extension.id, handler);
return extHostUrls.registerUriHandler(extension.identifier, handler);
},
createQuickPick<T extends vscode.QuickPickItem>(): vscode.QuickPick<T> {
return extHostQuickOpen.createQuickPick(extension.id, extension.enableProposedApi);
return extHostQuickOpen.createQuickPick(extension.identifier, extension.enableProposedApi);
},
createInputBox(): vscode.InputBox {
return extHostQuickOpen.createInputBox(extension.id);
},
return extHostQuickOpen.createInputBox(extension.identifier);
}
};
// namespace: workspace
@@ -530,7 +537,7 @@ export function createApiFactory(
return extHostWorkspace.getRelativePath(pathOrUri, includeWorkspace);
},
findFiles: (include, exclude, maxResults?, token?) => {
return extHostWorkspace.findFiles(typeConverters.GlobPattern.from(include), typeConverters.GlobPattern.from(exclude), maxResults, extension.id, token);
return extHostWorkspace.findFiles(typeConverters.GlobPattern.from(include), typeConverters.GlobPattern.from(exclude), maxResults, extension.identifier, token);
},
findTextInFiles: (query: vscode.TextSearchQuery, optionsOrCallback, callbackOrToken?, token?: vscode.CancellationToken) => {
let options: vscode.FindTextInFilesOptions;
@@ -545,7 +552,7 @@ export function createApiFactory(
token = callbackOrToken;
}
return extHostWorkspace.findTextInFiles(query, options || {}, callback, extension.id, token);
return extHostWorkspace.findTextInFiles(query, options || {}, callback, extension.identifier, token);
},
saveAll: (includeUntitled?) => {
return extHostWorkspace.saveAll(includeUntitled);
@@ -599,11 +606,11 @@ export function createApiFactory(
return extHostDocumentSaveParticipant.getOnWillSaveTextDocumentEvent(extension)(listener, thisArgs, disposables);
},
onDidChangeConfiguration: (listener: (_: any) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) => {
return extHostConfiguration.onDidChangeConfiguration(listener, thisArgs, disposables);
return configProvider.onDidChangeConfiguration(listener, thisArgs, disposables);
},
getConfiguration(section?: string, resource?: vscode.Uri): vscode.WorkspaceConfiguration {
resource = arguments.length === 1 ? void 0 : resource;
return extHostConfiguration.getConfiguration(section, resource, extension.id);
resource = arguments.length === 1 ? undefined : resource;
return configProvider.getConfiguration(section, resource, extension.identifier);
},
registerTextDocumentContentProvider(scheme: string, provider: vscode.TextDocumentContentProvider) {
return extHostDocumentContentProviders.registerTextDocumentContentProvider(scheme, provider);
@@ -628,10 +635,10 @@ export function createApiFactory(
return extHostSearch.registerFileIndexProvider(scheme, provider);
}),
registerDocumentCommentProvider: proposedApiFunction(extension, (provider: vscode.DocumentCommentProvider) => {
return exthostCommentProviders.registerDocumentCommentProvider(provider);
return exthostCommentProviders.registerDocumentCommentProvider(extension.identifier, provider);
}),
registerWorkspaceCommentProvider: proposedApiFunction(extension, (provider: vscode.WorkspaceCommentProvider) => {
return exthostCommentProviders.registerWorkspaceCommentProvider(extension.id, provider);
return exthostCommentProviders.registerWorkspaceCommentProvider(extension.identifier, provider);
}),
onDidRenameFile: proposedApiFunction(extension, (listener, thisArg?, disposables?) => {
return extHostFileSystemEvent.onDidRenameFile(listener, thisArg, disposables);
@@ -788,6 +795,8 @@ export function createApiFactory(
Range: extHostTypes.Range,
RelativePattern: extHostTypes.RelativePattern,
Selection: extHostTypes.Selection,
SelectionRange: extHostTypes.SelectionRange,
SelectionRangeKind: extHostTypes.SelectionRangeKind,
ShellExecution: extHostTypes.ShellExecution,
ShellQuoting: extHostTypes.ShellQuoting,
SignatureHelpTriggerKind: extHostTypes.SignatureHelpTriggerKind,
@@ -839,6 +848,7 @@ export function originalFSPath(uri: URI): string {
class Extension<T> implements vscode.Extension<T> {
private _extensionService: ExtHostExtensionService;
private _identifier: ExtensionIdentifier;
public id: string;
public extensionPath: string;
@@ -846,29 +856,30 @@ class Extension<T> implements vscode.Extension<T> {
constructor(extensionService: ExtHostExtensionService, description: IExtensionDescription) {
this._extensionService = extensionService;
this.id = description.id;
this._identifier = description.identifier;
this.id = description.identifier.value;
this.extensionPath = paths.normalize(originalFSPath(description.extensionLocation), true);
this.packageJSON = description;
}
get isActive(): boolean {
return this._extensionService.isActivated(this.id);
return this._extensionService.isActivated(this._identifier);
}
get exports(): T {
return <T>this._extensionService.getExtensionExports(this.id);
return <T>this._extensionService.getExtensionExports(this._identifier);
}
activate(): Thenable<T> {
return this._extensionService.activateByIdWithErrors(this.id, new ExtensionActivatedByAPI(false)).then(() => this.exports);
return this._extensionService.activateByIdWithErrors(this._identifier, new ExtensionActivatedByAPI(false)).then(() => this.exports);
}
}
export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: IExtensionApiFactory, extensionRegistry: ExtensionDescriptionRegistry): Promise<void> {
return extensionService.getExtensionPathIndex().then(trie => defineAPI(apiFactory, trie, extensionRegistry));
export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: IExtensionApiFactory, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): Promise<void> {
return extensionService.getExtensionPathIndex().then(trie => defineAPI(apiFactory, trie, extensionRegistry, configProvider));
}
function defineAPI(factory: IExtensionApiFactory, extensionPaths: TernarySearchTree<IExtensionDescription>, extensionRegistry: ExtensionDescriptionRegistry): void {
function defineAPI(factory: IExtensionApiFactory, extensionPaths: TernarySearchTree<IExtensionDescription>, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): void {
// each extension is meant to get its own api implementation
const extApiImpl = new Map<string, typeof vscode>();
@@ -884,10 +895,10 @@ function defineAPI(factory: IExtensionApiFactory, extensionPaths: TernarySearchT
// get extension id from filename and api for extension
const ext = extensionPaths.findSubstr(URI.file(parent.filename).fsPath);
if (ext) {
let apiImpl = extApiImpl.get(ext.id);
let apiImpl = extApiImpl.get(ExtensionIdentifier.toKey(ext.identifier));
if (!apiImpl) {
apiImpl = factory(ext, extensionRegistry);
extApiImpl.set(ext.id, apiImpl);
apiImpl = factory(ext, extensionRegistry, configProvider);
extApiImpl.set(ExtensionIdentifier.toKey(ext.identifier), apiImpl);
}
return apiImpl;
}
@@ -895,9 +906,9 @@ function defineAPI(factory: IExtensionApiFactory, extensionPaths: TernarySearchT
// fall back to a default implementation
if (!defaultApiImpl) {
let extensionPathsPretty = '';
extensionPaths.forEach((value, index) => extensionPathsPretty += `\t${index} -> ${value.id}\n`);
extensionPaths.forEach((value, index) => extensionPathsPretty += `\t${index} -> ${value.identifier.value}\n`);
console.warn(`Could not identify extension for 'vscode' require call from ${parent.filename}. These are the extension path mappings: \n${extensionPathsPretty}`);
defaultApiImpl = factory(nullExtensionDescription, extensionRegistry);
defaultApiImpl = factory(nullExtensionDescription, extensionRegistry, configProvider);
}
return defaultApiImpl;
};

View File

@@ -20,8 +20,8 @@ import { CharacterPair, CommentRule, EnterAction } from 'vs/editor/common/modes/
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
import { ConfigurationTarget, IConfigurationData, IConfigurationModel } from 'vs/platform/configuration/common/configuration';
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
import { FileChangeType, FileDeleteOptions, FileOverwriteOptions, FileSystemProviderCapabilities, FileType, FileWriteOptions, IStat, IWatchOptions } from 'vs/platform/files/common/files';
import { LabelRules } from 'vs/platform/label/common/label';
import { FileChangeType, FileDeleteOptions, FileOverwriteOptions, FileSystemProviderCapabilities, FileType, FileWriteOptions, IStat, IWatchOptions, FileOpenOptions } from 'vs/platform/files/common/files';
import { ResourceLabelFormatter } from 'vs/platform/label/common/label';
import { LogLevel } from 'vs/platform/log/common/log';
import { IMarkerData } from 'vs/platform/markers/common/markers';
import { IPickOptions, IQuickInputButton, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
@@ -31,19 +31,20 @@ import { ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
import { ThemeColor } from 'vs/platform/theme/common/themeService';
import { EndOfLine, IFileOperationOptions, TextEditorLineNumbersStyle } from 'vs/workbench/api/node/extHostTypes';
import { EditorViewColumn } from 'vs/workbench/api/shared/editor';
import { TaskDTO, TaskExecutionDTO, TaskFilterDTO, TaskHandleDTO, TaskProcessEndedDTO, TaskProcessStartedDTO, TaskSystemInfoDTO } from 'vs/workbench/api/shared/tasks';
import { TaskDTO, TaskExecutionDTO, TaskFilterDTO, TaskHandleDTO, TaskProcessEndedDTO, TaskProcessStartedDTO, TaskSystemInfoDTO, TaskSetDTO } from 'vs/workbench/api/shared/tasks';
import { ITreeItem, IRevealOptions } from 'vs/workbench/common/views';
import { IAdapterDescriptor, IConfig, ITerminalSettings } from 'vs/workbench/parts/debug/common/debug';
import { ITextQueryBuilderOptions } from 'vs/workbench/parts/search/common/queryBuilder';
import { TaskSet } from 'vs/workbench/parts/tasks/common/tasks';
import { ITerminalDimensions } from 'vs/workbench/parts/terminal/common/terminal';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { IRPCProtocol, ProxyIdentifier, createExtHostContextProxyIdentifier as createExtId, createMainContextProxyIdentifier as createMainId } from 'vs/workbench/services/extensions/node/proxyIdentifier';
import { IRPCProtocol, createExtHostContextProxyIdentifier as createExtId, createMainContextProxyIdentifier as createMainId } from 'vs/workbench/services/extensions/node/proxyIdentifier';
import { IProgressOptions, IProgressStep } from 'vs/platform/progress/common/progress';
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
import * as vscode from 'vscode';
import { IMarkdownString } from 'vs/base/common/htmlContent';
import { ResolvedAuthority } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IRemoteConsoleLog } from 'vs/base/node/console';
// {{SQL CARBON EDIT}}
import { ITreeItem as sqlITreeItem } from 'sql/workbench/common/views';
@@ -69,8 +70,8 @@ export interface IInitData {
parentPid: number;
environment: IEnvironment;
workspace: IWorkspaceData;
resolvedExtensions: ExtensionIdentifier[];
extensions: IExtensionDescription[];
configuration: IConfigurationInitData;
telemetryInfo: ITelemetryInfo;
logLevel: LogLevel;
logsLocation: URI;
@@ -104,27 +105,28 @@ export interface MainThreadClipboardShape extends IDisposable {
export interface MainThreadCommandsShape extends IDisposable {
$registerCommand(id: string): void;
$unregisterCommand(id: string): void;
$executeCommand<T>(id: string, args: any[]): Thenable<T>;
$getCommands(): Thenable<string[]>;
$executeCommand<T>(id: string, args: any[]): Promise<T>;
$getCommands(): Promise<string[]>;
}
export interface CommentProviderFeatures {
startDraftLabel?: string;
deleteDraftLabel?: string;
finishDraftLabel?: string;
reactionGroup?: vscode.CommentReaction[];
}
export interface MainThreadCommentsShape extends IDisposable {
$registerDocumentCommentProvider(handle: number, features: CommentProviderFeatures): void;
$unregisterDocumentCommentProvider(handle: number): void;
$registerWorkspaceCommentProvider(handle: number, extensionId: string): void;
$registerWorkspaceCommentProvider(handle: number, extensionId: ExtensionIdentifier): void;
$unregisterWorkspaceCommentProvider(handle: number): void;
$onDidCommentThreadsChange(handle: number, event: modes.CommentThreadChangedEvent): void;
}
export interface MainThreadConfigurationShape extends IDisposable {
$updateConfigurationOption(target: ConfigurationTarget, key: string, value: any, resource: UriComponents): Thenable<void>;
$removeConfigurationOption(target: ConfigurationTarget, key: string, resource: UriComponents): Thenable<void>;
$updateConfigurationOption(target: ConfigurationTarget, key: string, value: any, resource: UriComponents): Promise<void>;
$removeConfigurationOption(target: ConfigurationTarget, key: string, resource: UriComponents): Promise<void>;
}
export interface MainThreadDiagnosticsShape extends IDisposable {
@@ -148,8 +150,8 @@ export interface MainThreadDialogSaveOptions {
}
export interface MainThreadDiaglogsShape extends IDisposable {
$showOpenDialog(options: MainThreadDialogOpenOptions): Thenable<UriComponents[]>;
$showSaveDialog(options: MainThreadDialogSaveOptions): Thenable<UriComponents>;
$showOpenDialog(options: MainThreadDialogOpenOptions): Promise<UriComponents[]>;
$showSaveDialog(options: MainThreadDialogSaveOptions): Promise<UriComponents>;
}
export interface MainThreadDecorationsShape extends IDisposable {
@@ -165,9 +167,9 @@ export interface MainThreadDocumentContentProvidersShape extends IDisposable {
}
export interface MainThreadDocumentsShape extends IDisposable {
$tryCreateDocument(options?: { language?: string; content?: string; }): Thenable<UriComponents>;
$tryOpenDocument(uri: UriComponents): Thenable<void>;
$trySaveDocument(uri: UriComponents): Thenable<boolean>;
$tryCreateDocument(options?: { language?: string; content?: string; }): Promise<UriComponents>;
$tryOpenDocument(uri: UriComponents): Promise<void>;
$trySaveDocument(uri: UriComponents): Promise<boolean>;
}
export interface ITextEditorConfigurationUpdate {
@@ -208,26 +210,26 @@ export interface ITextDocumentShowOptions {
}
export interface MainThreadTextEditorsShape extends IDisposable {
$tryShowTextDocument(resource: UriComponents, options: ITextDocumentShowOptions): Thenable<string>;
$tryShowTextDocument(resource: UriComponents, options: ITextDocumentShowOptions): Promise<string>;
$registerTextEditorDecorationType(key: string, options: editorCommon.IDecorationRenderOptions): void;
$removeTextEditorDecorationType(key: string): void;
$tryShowEditor(id: string, position: EditorViewColumn): Thenable<void>;
$tryHideEditor(id: string): Thenable<void>;
$trySetOptions(id: string, options: ITextEditorConfigurationUpdate): Thenable<void>;
$trySetDecorations(id: string, key: string, ranges: editorCommon.IDecorationOptions[]): Thenable<void>;
$trySetDecorationsFast(id: string, key: string, ranges: number[]): Thenable<void>;
$tryRevealRange(id: string, range: IRange, revealType: TextEditorRevealType): Thenable<void>;
$trySetSelections(id: string, selections: ISelection[]): Thenable<void>;
$tryApplyEdits(id: string, modelVersionId: number, edits: ISingleEditOperation[], opts: IApplyEditsOptions): Thenable<boolean>;
$tryApplyWorkspaceEdit(workspaceEditDto: WorkspaceEditDto): Thenable<boolean>;
$tryInsertSnippet(id: string, template: string, selections: IRange[], opts: IUndoStopOptions): Thenable<boolean>;
$getDiffInformation(id: string): Thenable<editorCommon.ILineChange[]>;
$tryShowEditor(id: string, position: EditorViewColumn): Promise<void>;
$tryHideEditor(id: string): Promise<void>;
$trySetOptions(id: string, options: ITextEditorConfigurationUpdate): Promise<void>;
$trySetDecorations(id: string, key: string, ranges: editorCommon.IDecorationOptions[]): Promise<void>;
$trySetDecorationsFast(id: string, key: string, ranges: number[]): Promise<void>;
$tryRevealRange(id: string, range: IRange, revealType: TextEditorRevealType): Promise<void>;
$trySetSelections(id: string, selections: ISelection[]): Promise<void>;
$tryApplyEdits(id: string, modelVersionId: number, edits: ISingleEditOperation[], opts: IApplyEditsOptions): Promise<boolean>;
$tryApplyWorkspaceEdit(workspaceEditDto: WorkspaceEditDto): Promise<boolean>;
$tryInsertSnippet(id: string, template: string, selections: IRange[], opts: IUndoStopOptions): Promise<boolean>;
$getDiffInformation(id: string): Promise<editorCommon.ILineChange[]>;
}
export interface MainThreadTreeViewsShape extends IDisposable {
$registerTreeViewDataProvider(treeViewId: string, options: { showCollapseAll: boolean }): void;
$refresh(treeViewId: string, itemsToRefresh?: { [treeItemHandle: string]: ITreeItem }): Thenable<void>;
$reveal(treeViewId: string, treeItem: ITreeItem, parentChain: ITreeItem[], options: IRevealOptions): Thenable<void>;
$refresh(treeViewId: string, itemsToRefresh?: { [treeItemHandle: string]: ITreeItem }): Promise<void>;
$reveal(treeViewId: string, treeItem: ITreeItem, parentChain: ITreeItem[], options: IRevealOptions): Promise<void>;
$setMessage(treeViewId: string, message: string | IMarkdownString): void;
}
@@ -235,6 +237,10 @@ export interface MainThreadErrorsShape extends IDisposable {
$onUnexpectedError(err: any | SerializedError): void;
}
export interface MainThreadConsoleShape extends IDisposable {
$logExtensionHostMessage(msg: IRemoteConsoleLog): void;
}
export interface ISerializedRegExp {
pattern: string;
flags?: string;
@@ -290,7 +296,7 @@ export interface ISerializedSignatureHelpProviderMetadata {
export interface MainThreadLanguageFeaturesShape extends IDisposable {
$unregister(handle: number): void;
$registerOutlineSupport(handle: number, selector: ISerializedDocumentFilter[], label: string): void;
$registerDocumentSymbolProvider(handle: number, selector: ISerializedDocumentFilter[], label: string): void;
$registerCodeLensSupport(handle: number, selector: ISerializedDocumentFilter[], eventHandle: number): void;
$emitCodeLensEvent(eventHandle: number, event?: any): void;
$registerDefinitionSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
@@ -301,8 +307,8 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable {
$registerDocumentHighlightProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerReferenceSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerQuickFixSupport(handle: number, selector: ISerializedDocumentFilter[], supportedKinds?: string[]): void;
$registerDocumentFormattingSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerRangeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerDocumentFormattingSupport(handle: number, selector: ISerializedDocumentFilter[], label: string): void;
$registerRangeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[], label: string): void;
$registerOnTypeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[], autoFormatTriggerCharacters: string[]): void;
$registerNavigateTypeSupport(handle: number): void;
$registerRenameSupport(handle: number, selector: ISerializedDocumentFilter[], supportsResolveInitialValues: boolean): void;
@@ -316,8 +322,8 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable {
}
export interface MainThreadLanguagesShape extends IDisposable {
$getLanguages(): Thenable<string[]>;
$changeLanguage(resource: UriComponents, languageId: string): Thenable<void>;
$getLanguages(): Promise<string[]>;
$changeLanguage(resource: UriComponents, languageId: string): Promise<void>;
}
export interface MainThreadMessageOptions {
@@ -326,17 +332,17 @@ export interface MainThreadMessageOptions {
}
export interface MainThreadMessageServiceShape extends IDisposable {
$showMessage(severity: Severity, message: string, options: MainThreadMessageOptions, commands: { title: string; isCloseAffordance: boolean; handle: number; }[]): Thenable<number>;
$showMessage(severity: Severity, message: string, options: MainThreadMessageOptions, commands: { title: string; isCloseAffordance: boolean; handle: number; }[]): Promise<number>;
}
export interface MainThreadOutputServiceShape extends IDisposable {
$register(label: string, log: boolean, file?: UriComponents): Thenable<string>;
$append(channelId: string, value: string): Thenable<void>;
$update(channelId: string): Thenable<void>;
$clear(channelId: string, till: number): Thenable<void>;
$reveal(channelId: string, preserveFocus: boolean): Thenable<void>;
$close(channelId: string): Thenable<void>;
$dispose(channelId: string): Thenable<void>;
$register(label: string, log: boolean, file?: UriComponents): Promise<string>;
$append(channelId: string, value: string): Promise<void>;
$update(channelId: string): Promise<void>;
$clear(channelId: string, till: number): Promise<void>;
$reveal(channelId: string, preserveFocus: boolean): Promise<void>;
$close(channelId: string): Promise<void>;
$dispose(channelId: string): Promise<void>;
}
export interface MainThreadProgressShape extends IDisposable {
@@ -347,8 +353,8 @@ export interface MainThreadProgressShape extends IDisposable {
}
export interface MainThreadTerminalServiceShape extends IDisposable {
$createTerminal(name?: string, shellPath?: string, shellArgs?: string[], cwd?: string, env?: { [key: string]: string }, waitOnExit?: boolean): Thenable<number>;
$createTerminalRenderer(name: string): Thenable<number>;
$createTerminal(name?: string, shellPath?: string, shellArgs?: string[], cwd?: string | URI, env?: { [key: string]: string }, waitOnExit?: boolean, strictEnv?: boolean): Promise<{ id: number, name: string }>;
$createTerminalRenderer(name: string): Promise<number>;
$dispose(terminalId: number): void;
$hide(terminalId: number): void;
$sendText(terminalId: number, text: string, addNewLine: boolean): void;
@@ -360,6 +366,8 @@ export interface MainThreadTerminalServiceShape extends IDisposable {
$sendProcessData(terminalId: number, data: string): void;
$sendProcessPid(terminalId: number, pid: number): void;
$sendProcessExit(terminalId: number, exitCode: number): void;
$sendProcessInitialCwd(terminalId: number, cwd: string): void;
$sendProcessCwd(terminalId: number, initialCwd: string): void;
// Renderer
$terminalRendererSetName(terminalId: number, name: string): void;
@@ -434,22 +442,22 @@ export interface TransferInputBox extends BaseTransferQuickInput {
}
export interface MainThreadQuickOpenShape extends IDisposable {
$show(instance: number, options: IPickOptions<TransferQuickPickItems>, token: CancellationToken): Thenable<number | number[]>;
$setItems(instance: number, items: TransferQuickPickItems[]): Thenable<void>;
$setError(instance: number, error: Error): Thenable<void>;
$input(options: vscode.InputBoxOptions, validateInput: boolean, token: CancellationToken): Thenable<string>;
$createOrUpdate(params: TransferQuickInput): Thenable<void>;
$dispose(id: number): Thenable<void>;
$show(instance: number, options: IPickOptions<TransferQuickPickItems>, token: CancellationToken): Promise<number | number[]>;
$setItems(instance: number, items: TransferQuickPickItems[]): Promise<void>;
$setError(instance: number, error: Error): Promise<void>;
$input(options: vscode.InputBoxOptions, validateInput: boolean, token: CancellationToken): Promise<string>;
$createOrUpdate(params: TransferQuickInput): Promise<void>;
$dispose(id: number): Promise<void>;
}
export interface MainThreadStatusBarShape extends IDisposable {
$setEntry(id: number, extensionId: string, text: string, tooltip: string, command: string, color: string | ThemeColor, alignment: MainThreadStatusBarAlignment, priority: number): void;
$setEntry(id: number, extensionId: ExtensionIdentifier, text: string, tooltip: string, command: string, color: string | ThemeColor, alignment: MainThreadStatusBarAlignment, priority: number): void;
$dispose(id: number): void;
}
export interface MainThreadStorageShape extends IDisposable {
$getValue<T>(shared: boolean, key: string): Thenable<T>;
$setValue(shared: boolean, key: string, value: object): Thenable<void>;
$getValue<T>(shared: boolean, key: string): Promise<T>;
$setValue(shared: boolean, key: string, value: object): Promise<void>;
}
export interface MainThreadTelemetryShape extends IDisposable {
@@ -464,14 +472,14 @@ export interface WebviewPanelShowOptions {
}
export interface MainThreadWebviewsShape extends IDisposable {
$createWebviewPanel(handle: WebviewPanelHandle, viewType: string, title: string, showOptions: WebviewPanelShowOptions, options: vscode.WebviewPanelOptions & vscode.WebviewOptions, extensionId: string, extensionLocation: UriComponents): void;
$createWebviewPanel(handle: WebviewPanelHandle, viewType: string, title: string, showOptions: WebviewPanelShowOptions, options: vscode.WebviewPanelOptions & vscode.WebviewOptions, extensionId: ExtensionIdentifier, extensionLocation: UriComponents): void;
$disposeWebview(handle: WebviewPanelHandle): void;
$reveal(handle: WebviewPanelHandle, showOptions: WebviewPanelShowOptions): void;
$setTitle(handle: WebviewPanelHandle, value: string): void;
$setIconPath(handle: WebviewPanelHandle, value: { light: UriComponents, dark: UriComponents } | undefined): void;
$setHtml(handle: WebviewPanelHandle, value: string): void;
$setOptions(handle: WebviewPanelHandle, options: vscode.WebviewOptions): void;
$postMessage(handle: WebviewPanelHandle, value: any): Thenable<boolean>;
$postMessage(handle: WebviewPanelHandle, value: any): Promise<boolean>;
$registerSerializer(viewType: string): void;
$unregisterSerializer(viewType: string): void;
@@ -486,26 +494,26 @@ export interface WebviewPanelViewState {
export interface ExtHostWebviewsShape {
$onMessage(handle: WebviewPanelHandle, message: any): void;
$onDidChangeWebviewPanelViewState(handle: WebviewPanelHandle, newState: WebviewPanelViewState): void;
$onDidDisposeWebviewPanel(handle: WebviewPanelHandle): Thenable<void>;
$deserializeWebviewPanel(newWebviewHandle: WebviewPanelHandle, viewType: string, title: string, state: any, position: EditorViewColumn, options: vscode.WebviewOptions): Thenable<void>;
$onDidDisposeWebviewPanel(handle: WebviewPanelHandle): Promise<void>;
$deserializeWebviewPanel(newWebviewHandle: WebviewPanelHandle, viewType: string, title: string, state: any, position: EditorViewColumn, options: vscode.WebviewOptions): Promise<void>;
}
export interface MainThreadUrlsShape extends IDisposable {
$registerUriHandler(handle: number, extensionId: string): Thenable<void>;
$unregisterUriHandler(handle: number): Thenable<void>;
$registerUriHandler(handle: number, extensionId: ExtensionIdentifier): Promise<void>;
$unregisterUriHandler(handle: number): Promise<void>;
}
export interface ExtHostUrlsShape {
$handleExternalUri(handle: number, uri: UriComponents): Thenable<void>;
$handleExternalUri(handle: number, uri: UriComponents): Promise<void>;
}
export interface MainThreadWorkspaceShape extends IDisposable {
$startFileSearch(includePattern: string, includeFolder: URI, excludePatternOrDisregardExcludes: string | false, maxResults: number, token: CancellationToken): Thenable<UriComponents[]>;
$startTextSearch(query: IPatternInfo, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Thenable<vscode.TextSearchComplete>;
$checkExists(includes: string[], token: CancellationToken): Thenable<boolean>;
$saveAll(includeUntitled?: boolean): Thenable<boolean>;
$updateWorkspaceFolders(extensionName: string, index: number, deleteCount: number, workspaceFoldersToAdd: { uri: UriComponents, name?: string }[]): Thenable<void>;
$resolveProxy(url: string): Thenable<string>;
$startFileSearch(includePattern: string, includeFolder: URI, excludePatternOrDisregardExcludes: string | false, maxResults: number, token: CancellationToken): Promise<UriComponents[]>;
$startTextSearch(query: IPatternInfo, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Promise<vscode.TextSearchComplete>;
$checkExists(includes: string[], token: CancellationToken): Promise<boolean>;
$saveAll(includeUntitled?: boolean): Promise<boolean>;
$updateWorkspaceFolders(extensionName: string, index: number, deleteCount: number, workspaceFoldersToAdd: { uri: UriComponents, name?: string }[]): Promise<void>;
$resolveProxy(url: string): Promise<string>;
}
export interface IFileChangeDto {
@@ -516,7 +524,7 @@ export interface IFileChangeDto {
export interface MainThreadFileSystemShape extends IDisposable {
$registerFileSystemProvider(handle: number, scheme: string, capabilities: FileSystemProviderCapabilities): void;
$unregisterProvider(handle: number): void;
$setUriFormatter(scheme: string, formatter: LabelRules): void;
$setUriFormatter(formatter: ResourceLabelFormatter): void;
$onFileSystemChange(handle: number, resource: IFileChangeDto[]): void;
}
@@ -531,20 +539,21 @@ export interface MainThreadSearchShape extends IDisposable {
}
export interface MainThreadTaskShape extends IDisposable {
$registerTaskProvider(handle: number): Thenable<void>;
$unregisterTaskProvider(handle: number): Thenable<void>;
$fetchTasks(filter?: TaskFilterDTO): Thenable<TaskDTO[]>;
$executeTask(task: TaskHandleDTO | TaskDTO): Thenable<TaskExecutionDTO>;
$terminateTask(id: string): Thenable<void>;
$registerTaskProvider(handle: number): Promise<void>;
$unregisterTaskProvider(handle: number): Promise<void>;
$fetchTasks(filter?: TaskFilterDTO): Promise<TaskDTO[]>;
$executeTask(task: TaskHandleDTO | TaskDTO): Promise<TaskExecutionDTO>;
$terminateTask(id: string): Promise<void>;
$registerTaskSystem(scheme: string, info: TaskSystemInfoDTO): void;
}
export interface MainThreadExtensionServiceShape extends IDisposable {
$localShowMessage(severity: Severity, msg: string): void;
$onExtensionActivated(extensionId: string, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationEvent: string): void;
$onExtensionActivationFailed(extensionId: string): void;
$onExtensionRuntimeError(extensionId: string, error: SerializedError): void;
$addMessage(extensionId: string, severity: Severity, message: string): void;
$onWillActivateExtension(extensionId: ExtensionIdentifier): void;
$onDidActivateExtension(extensionId: ExtensionIdentifier, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationEvent: string): void;
$onExtensionActivationFailed(extensionId: ExtensionIdentifier): void;
$onExtensionRuntimeError(extensionId: ExtensionIdentifier, error: SerializedError): void;
$addMessage(extensionId: ExtensionIdentifier, severity: Severity, message: string): void;
}
export interface SCMProviderFeatures {
@@ -608,33 +617,35 @@ export interface MainThreadDebugServiceShape extends IDisposable {
$acceptDAMessage(handle: number, message: DebugProtocol.ProtocolMessage): void;
$acceptDAError(handle: number, name: string, message: string, stack: string): void;
$acceptDAExit(handle: number, code: number, signal: string): void;
$registerDebugConfigurationProvider(type: string, hasProvideMethod: boolean, hasResolveMethod: boolean, hasProvideDaMethod: boolean, hasProvideTrackerMethod: boolean, handle: number): Thenable<void>;
$registerDebugAdapterDescriptorFactory(type: string, handle: number): Thenable<void>;
$registerDebugConfigurationProvider(type: string, hasProvideMethod: boolean, hasResolveMethod: boolean, hasProvideDaMethod: boolean, handle: number): Promise<void>;
$registerDebugAdapterDescriptorFactory(type: string, handle: number): Promise<void>;
$registerDebugAdapterTrackerFactory(type: string, handle: number);
$unregisterDebugConfigurationProvider(handle: number): void;
$unregisterDebugAdapterDescriptorFactory(handle: number): void;
$unregisterDebugAdapterTrackerFactory(handle: number): void;
$startDebugging(folder: UriComponents | undefined, nameOrConfig: string | vscode.DebugConfiguration): Thenable<boolean>;
$customDebugAdapterRequest(id: DebugSessionUUID, command: string, args: any): Thenable<any>;
$startDebugging(folder: UriComponents | undefined, nameOrConfig: string | vscode.DebugConfiguration): Promise<boolean>;
$customDebugAdapterRequest(id: DebugSessionUUID, command: string, args: any): Promise<any>;
$appendDebugConsole(value: string): void;
$startBreakpointEvents(): void;
$registerBreakpoints(breakpoints: (ISourceMultiBreakpointDto | IFunctionBreakpointDto)[]): Thenable<void>;
$unregisterBreakpoints(breakpointIds: string[], functionBreakpointIds: string[]): Thenable<void>;
$registerBreakpoints(breakpoints: Array<ISourceMultiBreakpointDto | IFunctionBreakpointDto>): Promise<void>;
$unregisterBreakpoints(breakpointIds: string[], functionBreakpointIds: string[]): Promise<void>;
}
export interface MainThreadWindowShape extends IDisposable {
$getWindowVisibility(): Thenable<boolean>;
$getWindowVisibility(): Promise<boolean>;
$openUri(uri: UriComponents): Promise<boolean>;
}
// -- extension host
export interface ExtHostCommandsShape {
$executeContributedCommand<T>(id: string, ...args: any[]): Thenable<T>;
$getContributedCommandHandlerDescriptions(): Thenable<{ [id: string]: string | ICommandHandlerDescription }>;
$executeContributedCommand<T>(id: string, ...args: any[]): Promise<T>;
$getContributedCommandHandlerDescriptions(): Promise<{ [id: string]: string | ICommandHandlerDescription }>;
}
export interface ExtHostConfigurationShape {
$acceptConfigurationChanged(data: IConfigurationData, eventData: IWorkspaceConfigurationChangeEventData): void;
$initializeConfiguration(data: IConfigurationInitData): void;
$acceptConfigurationChanged(data: IConfigurationInitData, eventData: IWorkspaceConfigurationChangeEventData): void;
}
export interface ExtHostDiagnosticsShape {
@@ -661,7 +672,7 @@ export interface ExtHostDocumentsShape {
}
export interface ExtHostDocumentSaveParticipantShape {
$participateInSave(resource: UriComponents, reason: SaveReason): Thenable<boolean[]>;
$participateInSave(resource: UriComponents, reason: SaveReason): Promise<boolean[]>;
}
export interface ITextEditorAddData {
@@ -704,7 +715,7 @@ export interface ExtHostDocumentsAndEditorsShape {
export interface ExtHostTreeViewsShape {
// {{SQL CARBON EDIT}}
$getChildren(treeViewId: string, treeItemHandle?: string): Thenable<sqlITreeItem[]>;
$getChildren(treeViewId: string, treeItemHandle?: string): Promise<sqlITreeItem[]>;
$setExpanded(treeViewId: string, treeItemHandle: string, expanded: boolean): void;
$setSelection(treeViewId: string, treeItemHandles: string[]): void;
$setVisible(treeViewId: string, visible: boolean): void;
@@ -716,32 +727,39 @@ export interface ExtHostWorkspaceShape {
}
export interface ExtHostFileSystemShape {
$stat(handle: number, resource: UriComponents): Thenable<IStat>;
$readdir(handle: number, resource: UriComponents): Thenable<[string, FileType][]>;
$readFile(handle: number, resource: UriComponents): Thenable<Buffer>;
$writeFile(handle: number, resource: UriComponents, content: Buffer, opts: FileWriteOptions): Thenable<void>;
$rename(handle: number, resource: UriComponents, target: UriComponents, opts: FileOverwriteOptions): Thenable<void>;
$copy(handle: number, resource: UriComponents, target: UriComponents, opts: FileOverwriteOptions): Thenable<void>;
$mkdir(handle: number, resource: UriComponents): Thenable<void>;
$delete(handle: number, resource: UriComponents, opts: FileDeleteOptions): Thenable<void>;
$stat(handle: number, resource: UriComponents): Promise<IStat>;
$readdir(handle: number, resource: UriComponents): Promise<[string, FileType][]>;
$readFile(handle: number, resource: UriComponents): Promise<Buffer>;
$writeFile(handle: number, resource: UriComponents, content: Buffer, opts: FileWriteOptions): Promise<void>;
$rename(handle: number, resource: UriComponents, target: UriComponents, opts: FileOverwriteOptions): Promise<void>;
$copy(handle: number, resource: UriComponents, target: UriComponents, opts: FileOverwriteOptions): Promise<void>;
$mkdir(handle: number, resource: UriComponents): Promise<void>;
$delete(handle: number, resource: UriComponents, opts: FileDeleteOptions): Promise<void>;
$watch(handle: number, session: number, resource: UriComponents, opts: IWatchOptions): void;
$unwatch(handle: number, session: number): void;
$open(handle: number, resource: UriComponents): Thenable<number>;
$close(handle: number, fd: number): Thenable<void>;
$read(handle: number, fd: number, pos: number, data: Buffer, offset: number, length: number): Thenable<number>;
$write(handle: number, fd: number, pos: number, data: Buffer, offset: number, length: number): Thenable<number>;
$open(handle: number, resource: UriComponents, opts: FileOpenOptions): Promise<number>;
$close(handle: number, fd: number): Promise<void>;
$read(handle: number, fd: number, pos: number, length: number): Promise<Buffer>;
$write(handle: number, fd: number, pos: number, data: Buffer): Promise<number>;
}
export interface ExtHostSearchShape {
$provideFileSearchResults(handle: number, session: number, query: IRawQuery, token: CancellationToken): Thenable<ISearchCompleteStats>;
$provideTextSearchResults(handle: number, session: number, query: IRawTextQuery, token: CancellationToken): Thenable<ISearchCompleteStats>;
$clearCache(cacheKey: string): Thenable<void>;
$provideFileSearchResults(handle: number, session: number, query: IRawQuery, token: CancellationToken): Promise<ISearchCompleteStats>;
$provideTextSearchResults(handle: number, session: number, query: IRawTextQuery, token: CancellationToken): Promise<ISearchCompleteStats>;
$clearCache(cacheKey: string): Promise<void>;
}
export interface ExtHostExtensionServiceShape {
$resolveAuthority(remoteAuthority: string): Thenable<ResolvedAuthority>;
$startExtensionHost(enabledExtensionIds: string[]): Thenable<void>;
$activateByEvent(activationEvent: string): Thenable<void>;
$resolveAuthority(remoteAuthority: string): Promise<ResolvedAuthority>;
$startExtensionHost(enabledExtensionIds: ExtensionIdentifier[]): Promise<void>;
$activateByEvent(activationEvent: string): Promise<void>;
$activate(extensionId: ExtensionIdentifier, activationEvent: string): Promise<void>;
$deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise<void>;
$test_latency(n: number): Promise<number>;
$test_up(b: Buffer): Promise<number>;
$test_down(size: number): Promise<Buffer>;
}
export interface FileSystemEvents {
@@ -752,7 +770,7 @@ export interface FileSystemEvents {
export interface ExtHostFileSystemEventServiceShape {
$onFileEvent(events: FileSystemEvents): void;
$onFileRename(oldUri: UriComponents, newUri: UriComponents): void;
$onWillRename(oldUri: UriComponents, newUri: UriComponents): Thenable<any>;
$onWillRename(oldUri: UriComponents, newUri: UriComponents): Promise<any>;
}
export interface ObjectIdentifier {
@@ -803,10 +821,10 @@ export interface LocationDto {
}
export interface DefinitionLinkDto {
origin?: IRange;
originSelectionRange?: IRange;
uri: UriComponents;
range: IRange;
selectionRange?: IRange;
targetSelectionRange?: IRange;
}
export interface WorkspaceSymbolDto extends IdObject {
@@ -833,7 +851,7 @@ export interface ResourceTextEditDto {
}
export interface WorkspaceEditDto {
edits: (ResourceFileEditDto | ResourceTextEditDto)[];
edits: Array<ResourceFileEditDto | ResourceTextEditDto>;
// todo@joh reject should go into rename
rejectReason?: string;
@@ -859,43 +877,44 @@ export interface CodeActionDto {
diagnostics?: IMarkerData[];
command?: modes.Command;
kind?: string;
isPreferred?: boolean;
}
export interface ExtHostLanguageFeaturesShape {
$provideDocumentSymbols(handle: number, resource: UriComponents, token: CancellationToken): Thenable<modes.DocumentSymbol[]>;
$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Thenable<modes.ICodeLensSymbol[]>;
$resolveCodeLens(handle: number, resource: UriComponents, symbol: modes.ICodeLensSymbol, token: CancellationToken): Thenable<modes.ICodeLensSymbol>;
$provideDefinition(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Thenable<DefinitionLinkDto[]>;
$provideDeclaration(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Thenable<DefinitionLinkDto[]>;
$provideImplementation(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Thenable<DefinitionLinkDto[]>;
$provideTypeDefinition(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Thenable<DefinitionLinkDto[]>;
$provideHover(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Thenable<modes.Hover>;
$provideDocumentHighlights(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Thenable<modes.DocumentHighlight[]>;
$provideReferences(handle: number, resource: UriComponents, position: IPosition, context: modes.ReferenceContext, token: CancellationToken): Thenable<LocationDto[]>;
$provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Thenable<CodeActionDto[]>;
$provideDocumentFormattingEdits(handle: number, resource: UriComponents, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]>;
$provideDocumentRangeFormattingEdits(handle: number, resource: UriComponents, range: IRange, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]>;
$provideOnTypeFormattingEdits(handle: number, resource: UriComponents, position: IPosition, ch: string, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]>;
$provideWorkspaceSymbols(handle: number, search: string, token: CancellationToken): Thenable<WorkspaceSymbolsDto>;
$resolveWorkspaceSymbol(handle: number, symbol: WorkspaceSymbolDto, token: CancellationToken): Thenable<WorkspaceSymbolDto>;
$provideDocumentSymbols(handle: number, resource: UriComponents, token: CancellationToken): Promise<modes.DocumentSymbol[]>;
$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Promise<modes.ICodeLensSymbol[]>;
$resolveCodeLens(handle: number, resource: UriComponents, symbol: modes.ICodeLensSymbol, token: CancellationToken): Promise<modes.ICodeLensSymbol>;
$provideDefinition(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<DefinitionLinkDto[]>;
$provideDeclaration(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<DefinitionLinkDto[]>;
$provideImplementation(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<DefinitionLinkDto[]>;
$provideTypeDefinition(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<DefinitionLinkDto[]>;
$provideHover(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.Hover>;
$provideDocumentHighlights(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.DocumentHighlight[]>;
$provideReferences(handle: number, resource: UriComponents, position: IPosition, context: modes.ReferenceContext, token: CancellationToken): Promise<LocationDto[]>;
$provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise<CodeActionDto[]>;
$provideDocumentFormattingEdits(handle: number, resource: UriComponents, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]>;
$provideDocumentRangeFormattingEdits(handle: number, resource: UriComponents, range: IRange, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]>;
$provideOnTypeFormattingEdits(handle: number, resource: UriComponents, position: IPosition, ch: string, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]>;
$provideWorkspaceSymbols(handle: number, search: string, token: CancellationToken): Promise<WorkspaceSymbolsDto>;
$resolveWorkspaceSymbol(handle: number, symbol: WorkspaceSymbolDto, token: CancellationToken): Promise<WorkspaceSymbolDto>;
$releaseWorkspaceSymbols(handle: number, id: number): void;
$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string, token: CancellationToken): Thenable<WorkspaceEditDto>;
$resolveRenameLocation(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Thenable<modes.RenameLocation>;
$provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Thenable<SuggestResultDto>;
$resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, suggestion: modes.CompletionItem, token: CancellationToken): Thenable<modes.CompletionItem>;
$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string, token: CancellationToken): Promise<WorkspaceEditDto>;
$resolveRenameLocation(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.RenameLocation>;
$provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise<SuggestResultDto>;
$resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, suggestion: modes.CompletionItem, token: CancellationToken): Promise<modes.CompletionItem>;
$releaseCompletionItems(handle: number, id: number): void;
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Thenable<modes.SignatureHelp>;
$provideDocumentLinks(handle: number, resource: UriComponents, token: CancellationToken): Thenable<modes.ILink[]>;
$resolveDocumentLink(handle: number, link: modes.ILink, token: CancellationToken): Thenable<modes.ILink>;
$provideDocumentColors(handle: number, resource: UriComponents, token: CancellationToken): Thenable<IRawColorInfo[]>;
$provideColorPresentations(handle: number, resource: UriComponents, colorInfo: IRawColorInfo, token: CancellationToken): Thenable<modes.IColorPresentation[]>;
$provideFoldingRanges(handle: number, resource: UriComponents, context: modes.FoldingContext, token: CancellationToken): Thenable<modes.FoldingRange[]>;
$provideSelectionRanges(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Thenable<IRange[]>;
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise<modes.SignatureHelp>;
$provideDocumentLinks(handle: number, resource: UriComponents, token: CancellationToken): Promise<modes.ILink[]>;
$resolveDocumentLink(handle: number, link: modes.ILink, token: CancellationToken): Promise<modes.ILink>;
$provideDocumentColors(handle: number, resource: UriComponents, token: CancellationToken): Promise<IRawColorInfo[]>;
$provideColorPresentations(handle: number, resource: UriComponents, colorInfo: IRawColorInfo, token: CancellationToken): Promise<modes.IColorPresentation[]>;
$provideFoldingRanges(handle: number, resource: UriComponents, context: modes.FoldingContext, token: CancellationToken): Promise<modes.FoldingRange[]>;
$provideSelectionRanges(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.SelectionRange[]>;
}
export interface ExtHostQuickOpenShape {
$onItemSelected(handle: number): void;
$validateInput(input: string): Thenable<string>;
$validateInput(input: string): Promise<string>;
$onDidChangeActive(sessionId: number, handles: number[]): void;
$onDidChangeSelection(sessionId: number, handles: number[]): void;
$onDidAccept(sessionId: number): void;
@@ -908,7 +927,7 @@ export interface ShellLaunchConfigDto {
name?: string;
executable?: string;
args?: string[] | string;
cwd?: string;
cwd?: string | URI;
env?: { [key: string]: string };
}
@@ -925,23 +944,25 @@ export interface ExtHostTerminalServiceShape {
$acceptProcessInput(id: number, data: string): void;
$acceptProcessResize(id: number, cols: number, rows: number): void;
$acceptProcessShutdown(id: number, immediate: boolean): void;
$acceptProcessRequestInitialCwd(id: number): void;
$acceptProcessRequestCwd(id: number): void;
}
export interface ExtHostSCMShape {
$provideOriginalResource(sourceControlHandle: number, uri: UriComponents, token: CancellationToken): Thenable<UriComponents>;
$provideOriginalResource(sourceControlHandle: number, uri: UriComponents, token: CancellationToken): Promise<UriComponents>;
$onInputBoxValueChange(sourceControlHandle: number, value: string): void;
$executeResourceCommand(sourceControlHandle: number, groupHandle: number, handle: number): Thenable<void>;
$validateInput(sourceControlHandle: number, value: string, cursorPosition: number): Thenable<[string, number] | undefined>;
$setSelectedSourceControls(selectedSourceControlHandles: number[]): Thenable<void>;
$executeResourceCommand(sourceControlHandle: number, groupHandle: number, handle: number): Promise<void>;
$validateInput(sourceControlHandle: number, value: string, cursorPosition: number): Promise<[string, number] | undefined>;
$setSelectedSourceControls(selectedSourceControlHandles: number[]): Promise<void>;
}
export interface ExtHostTaskShape {
$provideTasks(handle: number, validTypes: { [key: string]: boolean; }): Thenable<TaskSet>;
$provideTasks(handle: number, validTypes: { [key: string]: boolean; }): Thenable<TaskSetDTO>;
$onDidStartTask(execution: TaskExecutionDTO): void;
$onDidStartTaskProcess(value: TaskProcessStartedDTO): void;
$onDidEndTaskProcess(value: TaskProcessEndedDTO): void;
$OnDidEndTask(execution: TaskExecutionDTO): void;
$resolveVariables(workspaceFolder: UriComponents, toResolve: { process?: { name: string; cwd?: string }, variables: string[] }): Thenable<{ process?: string; variables: { [key: string]: string } }>;
$resolveVariables(workspaceFolder: UriComponents, toResolve: { process?: { name: string; cwd?: string }, variables: string[] }): Promise<{ process?: string; variables: { [key: string]: string } }>;
}
export interface IBreakpointDto {
@@ -966,9 +987,9 @@ export interface ISourceBreakpointDto extends IBreakpointDto {
}
export interface IBreakpointsDeltaDto {
added?: (ISourceBreakpointDto | IFunctionBreakpointDto)[];
added?: Array<ISourceBreakpointDto | IFunctionBreakpointDto>;
removed?: string[];
changed?: (ISourceBreakpointDto | IFunctionBreakpointDto)[];
changed?: Array<ISourceBreakpointDto | IFunctionBreakpointDto>;
}
export interface ISourceMultiBreakpointDto {
@@ -998,15 +1019,15 @@ export interface IDebugSessionFullDto {
export type IDebugSessionDto = IDebugSessionFullDto | DebugSessionUUID;
export interface ExtHostDebugServiceShape {
$substituteVariables(folder: UriComponents | undefined, config: IConfig): Thenable<IConfig>;
$runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): Thenable<number | undefined>;
$startDASession(handle: number, session: IDebugSessionDto): Thenable<void>;
$stopDASession(handle: number): Thenable<void>;
$substituteVariables(folder: UriComponents | undefined, config: IConfig): Promise<IConfig>;
$runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): Promise<number | undefined>;
$startDASession(handle: number, session: IDebugSessionDto): Promise<void>;
$stopDASession(handle: number): Promise<void>;
$sendDAMessage(handle: number, message: DebugProtocol.ProtocolMessage): void;
$resolveDebugConfiguration(handle: number, folder: UriComponents | undefined, debugConfiguration: IConfig): Thenable<IConfig>;
$provideDebugConfigurations(handle: number, folder: UriComponents | undefined): Thenable<IConfig[]>;
$legacyDebugAdapterExecutable(handle: number, folderUri: UriComponents | undefined): Thenable<IAdapterDescriptor>; // TODO@AW legacy
$provideDebugAdapter(handle: number, session: IDebugSessionDto): Thenable<IAdapterDescriptor>;
$resolveDebugConfiguration(handle: number, folder: UriComponents | undefined, debugConfiguration: IConfig): Promise<IConfig>;
$provideDebugConfigurations(handle: number, folder: UriComponents | undefined): Promise<IConfig[]>;
$legacyDebugAdapterExecutable(handle: number, folderUri: UriComponents | undefined): Promise<IAdapterDescriptor>; // TODO@AW legacy
$provideDebugAdapter(handle: number, session: IDebugSessionDto): Promise<IAdapterDescriptor>;
$acceptDebugSessionStarted(session: IDebugSessionDto): void;
$acceptDebugSessionTerminated(session: IDebugSessionDto): void;
$acceptDebugSessionActiveChanged(session: IDebugSessionDto): void;
@@ -1026,7 +1047,7 @@ export type DecorationData = [number, boolean, string, string, ThemeColor, strin
export type DecorationReply = { [id: number]: DecorationData };
export interface ExtHostDecorationsShape {
$provideDecorations(requests: DecorationRequest[], token: CancellationToken): Thenable<DecorationReply>;
$provideDecorations(requests: DecorationRequest[], token: CancellationToken): Promise<DecorationReply>;
}
export interface ExtHostWindowShape {
@@ -1046,15 +1067,17 @@ export interface ExtHostProgressShape {
}
export interface ExtHostCommentsShape {
$provideDocumentComments(handle: number, document: UriComponents): Thenable<modes.CommentInfo>;
$createNewCommentThread(handle: number, document: UriComponents, range: IRange, text: string): Thenable<modes.CommentThread>;
$replyToCommentThread(handle: number, document: UriComponents, range: IRange, commentThread: modes.CommentThread, text: string): Thenable<modes.CommentThread>;
$editComment(handle: number, document: UriComponents, comment: modes.Comment, text: string): Thenable<void>;
$deleteComment(handle: number, document: UriComponents, comment: modes.Comment): Thenable<void>;
$startDraft(handle: number): Thenable<void>;
$deleteDraft(handle: number): Thenable<void>;
$finishDraft(handle: number): Thenable<void>;
$provideWorkspaceComments(handle: number): Thenable<modes.CommentThread[]>;
$provideDocumentComments(handle: number, document: UriComponents): Promise<modes.CommentInfo>;
$createNewCommentThread(handle: number, document: UriComponents, range: IRange, text: string): Promise<modes.CommentThread>;
$replyToCommentThread(handle: number, document: UriComponents, range: IRange, commentThread: modes.CommentThread, text: string): Promise<modes.CommentThread>;
$editComment(handle: number, document: UriComponents, comment: modes.Comment, text: string): Promise<void>;
$deleteComment(handle: number, document: UriComponents, comment: modes.Comment): Promise<void>;
$startDraft(handle: number, document: UriComponents): Promise<void>;
$deleteDraft(handle: number, document: UriComponents): Promise<void>;
$finishDraft(handle: number, document: UriComponents): Promise<void>;
$addReaction(handle: number, document: UriComponents, comment: modes.Comment, reaction: modes.CommentReaction): Promise<void>;
$deleteReaction(handle: number, document: UriComponents, comment: modes.Comment, reaction: modes.CommentReaction): Promise<void>;
$provideWorkspaceComments(handle: number): Promise<modes.CommentThread[]>;
}
export interface ExtHostStorageShape {
@@ -1064,10 +1087,11 @@ export interface ExtHostStorageShape {
// --- proxy identifiers
export const MainContext = {
MainThreadClipboard: <ProxyIdentifier<MainThreadClipboardShape>>createMainId<MainThreadClipboardShape>('MainThreadClipboard'),
MainThreadCommands: <ProxyIdentifier<MainThreadCommandsShape>>createMainId<MainThreadCommandsShape>('MainThreadCommands'),
MainThreadClipboard: createMainId<MainThreadClipboardShape>('MainThreadClipboard'),
MainThreadCommands: createMainId<MainThreadCommandsShape>('MainThreadCommands'),
MainThreadComments: createMainId<MainThreadCommentsShape>('MainThreadComments'),
MainThreadConfiguration: createMainId<MainThreadConfigurationShape>('MainThreadConfiguration'),
MainThreadConsole: createMainId<MainThreadConsoleShape>('MainThreadConsole'),
// {{SQL CARBON EDIT}}
// MainThreadDebugService: createMainId<MainThreadDebugServiceShape>('MainThreadDebugService'),
MainThreadDecorations: createMainId<MainThreadDecorationsShape>('MainThreadDecorations'),

View File

@@ -18,7 +18,6 @@ import { CustomCodeAction } from 'vs/workbench/api/node/extHostLanguageFeatures'
import { ICommandsExecutor, PreviewHTMLAPICommand, OpenFolderAPICommand, DiffAPICommand, OpenAPICommand, RemoveFromRecentlyOpenedAPICommand, SetEditorLayoutAPICommand } from './apiCommands';
import { EditorGroupLayout } from 'vs/workbench/services/group/common/editorGroupsService';
import { isFalsyOrEmpty, isNonEmptyArray } from 'vs/base/common/arrays';
import { IRange } from 'vs/editor/common/core/range';
export class ExtHostApiCommands {
@@ -110,7 +109,7 @@ export class ExtHostApiCommands {
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
{ name: 'position', description: 'Position in a text document', constraint: types.Position },
{ name: 'triggerCharacter', description: '(optional) Trigger signature help when the user types the character, like `,` or `(`', constraint: (value: any) => value === void 0 || typeof value === 'string' }
{ name: 'triggerCharacter', description: '(optional) Trigger signature help when the user types the character, like `,` or `(`', constraint: (value: any) => value === undefined || typeof value === 'string' }
],
returns: 'A promise that resolves to SignatureHelp.'
});
@@ -126,8 +125,8 @@ export class ExtHostApiCommands {
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
{ name: 'position', description: 'Position in a text document', constraint: types.Position },
{ name: 'triggerCharacter', description: '(optional) Trigger completion when the user types the character, like `,` or `(`', constraint: (value: any) => value === void 0 || typeof value === 'string' },
{ name: 'itemResolveCount', description: '(optional) Number of completions to resolve (too large numbers slow down completions)', constraint: (value: any) => value === void 0 || typeof value === 'number' }
{ name: 'triggerCharacter', description: '(optional) Trigger completion when the user types the character, like `,` or `(`', constraint: (value: any) => value === undefined || typeof value === 'string' },
{ name: 'itemResolveCount', description: '(optional) Number of completions to resolve (too large numbers slow down completions)', constraint: (value: any) => value === undefined || typeof value === 'number' }
],
returns: 'A promise that resolves to a CompletionList-instance.'
});
@@ -143,7 +142,7 @@ export class ExtHostApiCommands {
description: 'Execute CodeLens provider.',
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
{ name: 'itemResolveCount', description: '(optional) Number of lenses that should be resolved and returned. Will only retrun resolved lenses, will impact performance)', constraint: (value: any) => value === void 0 || typeof value === 'number' }
{ name: 'itemResolveCount', description: '(optional) Number of lenses that should be resolved and returned. Will only retrun resolved lenses, will impact performance)', constraint: (value: any) => value === undefined || typeof value === 'number' }
],
returns: 'A promise that resolves to an array of CodeLens-instances.'
});
@@ -236,8 +235,8 @@ export class ExtHostApiCommands {
this._register(OpenFolderAPICommand.ID, adjustHandler(OpenFolderAPICommand.execute), {
description: 'Open a folder or workspace in the current window or new window depending on the newWindow argument. Note that opening in the same window will shutdown the current extension host process and start a new one on the given folder/workspace unless the newWindow parameter is set to true.',
args: [
{ name: 'uri', description: '(optional) Uri of the folder or workspace file to open. If not provided, a native dialog will ask the user for the folder', constraint: (value: any) => value === void 0 || value instanceof URI },
{ name: 'newWindow', description: '(optional) Whether to open the folder/workspace in a new window or the same. Defaults to opening in the same window.', constraint: (value: any) => value === void 0 || typeof value === 'boolean' }
{ name: 'uri', description: '(optional) Uri of the folder or workspace file to open. If not provided, a native dialog will ask the user for the folder', constraint: (value: any) => value === undefined || value instanceof URI },
{ name: 'newWindow', description: '(optional) Whether to open the folder/workspace in a new window or the same. Defaults to opening in the same window.', constraint: (value: any) => value === undefined || typeof value === 'boolean' }
]
});
@@ -246,7 +245,7 @@ export class ExtHostApiCommands {
args: [
{ name: 'left', description: 'Left-hand side resource of the diff editor', constraint: URI },
{ name: 'right', description: 'Right-hand side resource of the diff editor', constraint: URI },
{ name: 'title', description: '(optional) Human readable title for the diff editor', constraint: (v: any) => v === void 0 || typeof v === 'string' },
{ name: 'title', description: '(optional) Human readable title for the diff editor', constraint: (v: any) => v === undefined || typeof v === 'string' },
{ name: 'options', description: '(optional) Editor options, see vscode.TextDocumentShowOptions' }
]
});
@@ -255,7 +254,7 @@ export class ExtHostApiCommands {
description: 'Opens the provided resource in the editor. Can be a text or binary file, or a http(s) url. If you need more control over the options for opening a text file, use vscode.window.showTextDocument instead.',
args: [
{ name: 'resource', description: 'Resource to open', constraint: URI },
{ name: 'columnOrOptions', description: '(optional) Either the column in which to open or editor options, see vscode.TextDocumentShowOptions', constraint: (v: any) => v === void 0 || typeof v === 'number' || typeof v === 'object' }
{ name: 'columnOrOptions', description: '(optional) Either the column in which to open or editor options, see vscode.TextDocumentShowOptions', constraint: (v: any) => v === undefined || typeof v === 'number' || typeof v === 'object' }
]
});
@@ -287,7 +286,7 @@ export class ExtHostApiCommands {
* @param query Search string to match query symbol names
* @return A promise that resolves to an array of symbol information.
*/
private _executeWorkspaceSymbolProvider(query: string): Thenable<types.SymbolInformation[]> {
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)) {
@@ -299,7 +298,7 @@ export class ExtHostApiCommands {
});
}
private _executeDefinitionProvider(resource: URI, position: types.Position): Thenable<types.Location[]> {
private _executeDefinitionProvider(resource: URI, position: types.Position): Promise<types.Location[]> {
const args = {
resource,
position: position && typeConverters.Position.from(position)
@@ -308,7 +307,7 @@ export class ExtHostApiCommands {
.then(tryMapWith(typeConverters.location.to));
}
private _executeDeclaraionProvider(resource: URI, position: types.Position): Thenable<types.Location[]> {
private _executeDeclaraionProvider(resource: URI, position: types.Position): Promise<types.Location[]> {
const args = {
resource,
position: position && typeConverters.Position.from(position)
@@ -317,7 +316,7 @@ export class ExtHostApiCommands {
.then(tryMapWith(typeConverters.location.to));
}
private _executeTypeDefinitionProvider(resource: URI, position: types.Position): Thenable<types.Location[]> {
private _executeTypeDefinitionProvider(resource: URI, position: types.Position): Promise<types.Location[]> {
const args = {
resource,
position: position && typeConverters.Position.from(position)
@@ -326,7 +325,7 @@ export class ExtHostApiCommands {
.then(tryMapWith(typeConverters.location.to));
}
private _executeImplementationProvider(resource: URI, position: types.Position): Thenable<types.Location[]> {
private _executeImplementationProvider(resource: URI, position: types.Position): Promise<types.Location[]> {
const args = {
resource,
position: position && typeConverters.Position.from(position)
@@ -335,7 +334,7 @@ export class ExtHostApiCommands {
.then(tryMapWith(typeConverters.location.to));
}
private _executeHoverProvider(resource: URI, position: types.Position): Thenable<types.Hover[]> {
private _executeHoverProvider(resource: URI, position: types.Position): Promise<types.Hover[]> {
const args = {
resource,
position: position && typeConverters.Position.from(position)
@@ -344,7 +343,7 @@ export class ExtHostApiCommands {
.then(tryMapWith(typeConverters.Hover.to));
}
private _executeDocumentHighlights(resource: URI, position: types.Position): Thenable<types.DocumentHighlight[]> {
private _executeDocumentHighlights(resource: URI, position: types.Position): Promise<types.DocumentHighlight[]> {
const args = {
resource,
position: position && typeConverters.Position.from(position)
@@ -353,7 +352,7 @@ export class ExtHostApiCommands {
.then(tryMapWith(typeConverters.DocumentHighlight.to));
}
private _executeReferenceProvider(resource: URI, position: types.Position): Thenable<types.Location[]> {
private _executeReferenceProvider(resource: URI, position: types.Position): Promise<types.Location[]> {
const args = {
resource,
position: position && typeConverters.Position.from(position)
@@ -362,7 +361,7 @@ export class ExtHostApiCommands {
.then(tryMapWith(typeConverters.location.to));
}
private _executeDocumentRenameProvider(resource: URI, position: types.Position, newName: string): Thenable<types.WorkspaceEdit> {
private _executeDocumentRenameProvider(resource: URI, position: types.Position, newName: string): Promise<types.WorkspaceEdit> {
const args = {
resource,
position: position && typeConverters.Position.from(position),
@@ -379,7 +378,7 @@ export class ExtHostApiCommands {
});
}
private _executeSignatureHelpProvider(resource: URI, position: types.Position, triggerCharacter: string): Thenable<types.SignatureHelp> {
private _executeSignatureHelpProvider(resource: URI, position: types.Position, triggerCharacter: string): Promise<types.SignatureHelp> {
const args = {
resource,
position: position && typeConverters.Position.from(position),
@@ -393,7 +392,7 @@ export class ExtHostApiCommands {
});
}
private _executeCompletionItemProvider(resource: URI, position: types.Position, triggerCharacter: string, maxItemsToResolve: number): Thenable<types.CompletionList> {
private _executeCompletionItemProvider(resource: URI, position: types.Position, triggerCharacter: string, maxItemsToResolve: number): Promise<types.CompletionList> {
const args = {
resource,
position: position && typeConverters.Position.from(position),
@@ -409,7 +408,7 @@ export class ExtHostApiCommands {
});
}
private _executeDocumentColorProvider(resource: URI): Thenable<types.ColorInformation[]> {
private _executeDocumentColorProvider(resource: URI): Promise<types.ColorInformation[]> {
const args = {
resource
};
@@ -421,20 +420,20 @@ export class ExtHostApiCommands {
});
}
private _executeSelectionRangeProvider(resource: URI, position: types.Position): Thenable<types.Range[]> {
private _executeSelectionRangeProvider(resource: URI, position: types.Position): Promise<vscode.SelectionRange[]> {
const args = {
resource,
position: position && typeConverters.Position.from(position)
};
return this._commands.executeCommand<IRange[]>('_executeSelectionRangeProvider', args).then(result => {
return this._commands.executeCommand<modes.SelectionRange[]>('_executeSelectionRangeProvider', args).then(result => {
if (isNonEmptyArray(result)) {
return result.map(typeConverters.Range.to);
return result.map(typeConverters.SelectionRange.to);
}
return [];
});
}
private _executeColorPresentationProvider(color: types.Color, context: { uri: URI, range: types.Range }): Thenable<types.ColorPresentation[]> {
private _executeColorPresentationProvider(color: types.Color, context: { uri: URI, range: types.Range }): Promise<types.ColorPresentation[]> {
const args = {
resource: context.uri,
color: typeConverters.Color.from(color),
@@ -448,7 +447,7 @@ export class ExtHostApiCommands {
});
}
private _executeDocumentSymbolProvider(resource: URI): Thenable<vscode.SymbolInformation[]> {
private _executeDocumentSymbolProvider(resource: URI): Promise<vscode.SymbolInformation[]> {
const args = {
resource
};
@@ -480,7 +479,7 @@ export class ExtHostApiCommands {
});
}
private _executeCodeActionProvider(resource: URI, range: types.Range): Thenable<(vscode.CodeAction | vscode.Command)[]> {
private _executeCodeActionProvider(resource: URI, range: types.Range): Promise<(vscode.CodeAction | vscode.Command)[]> {
const args = {
resource,
range: typeConverters.Range.from(range)
@@ -505,7 +504,7 @@ export class ExtHostApiCommands {
}));
}
private _executeCodeLensProvider(resource: URI, itemResolveCount: number): Thenable<vscode.CodeLens[]> {
private _executeCodeLensProvider(resource: URI, itemResolveCount: number): Promise<vscode.CodeLens[]> {
const args = { resource, itemResolveCount };
return this._commands.executeCommand<modes.ICodeLensSymbol[]>('_executeCodeLensProvider', args)
.then(tryMapWith(item => {
@@ -516,7 +515,7 @@ export class ExtHostApiCommands {
}
private _executeFormatDocumentProvider(resource: URI, options: vscode.FormattingOptions): Thenable<vscode.TextEdit[]> {
private _executeFormatDocumentProvider(resource: URI, options: vscode.FormattingOptions): Promise<vscode.TextEdit[]> {
const args = {
resource,
options
@@ -525,7 +524,7 @@ export class ExtHostApiCommands {
.then(tryMapWith(edit => new types.TextEdit(typeConverters.Range.to(edit.range), edit.text)));
}
private _executeFormatRangeProvider(resource: URI, range: types.Range, options: vscode.FormattingOptions): Thenable<vscode.TextEdit[]> {
private _executeFormatRangeProvider(resource: URI, range: types.Range, options: vscode.FormattingOptions): Promise<vscode.TextEdit[]> {
const args = {
resource,
range: typeConverters.Range.from(range),
@@ -535,7 +534,7 @@ export class ExtHostApiCommands {
.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): Thenable<vscode.TextEdit[]> {
private _executeFormatOnTypeProvider(resource: URI, position: types.Position, ch: string, options: vscode.FormattingOptions): Promise<vscode.TextEdit[]> {
const args = {
resource,
position: typeConverters.Position.from(position),
@@ -546,7 +545,7 @@ export class ExtHostApiCommands {
.then(tryMapWith(edit => new types.TextEdit(typeConverters.Range.to(edit.range), edit.text)));
}
private _executeDocumentLinkProvider(resource: URI): Thenable<vscode.DocumentLink[]> {
private _executeDocumentLinkProvider(resource: URI): Promise<vscode.DocumentLink[]> {
return this._commands.executeCommand<modes.ILink[]>('_executeLinkProvider', resource)
.then(tryMapWith(typeConverters.DocumentLink.to));
}

View File

@@ -15,6 +15,9 @@ import * as modes from 'vs/editor/common/modes';
import * as vscode from 'vscode';
import { ILogService } from 'vs/platform/log/common/log';
import { revive } from 'vs/base/common/marshalling';
import { Range } from 'vs/editor/common/core/range';
import { Position } from 'vs/editor/common/core/position';
import { URI } from 'vs/base/common/uri';
interface CommandHandler {
callback: Function;
@@ -42,7 +45,33 @@ export class ExtHostCommands implements ExtHostCommandsShape {
this._proxy = mainContext.getProxy(MainContext.MainThreadCommands);
this._logService = logService;
this._converter = new CommandsConverter(this, heapService);
this._argumentProcessors = [{ processArgument(a) { return revive(a, 0); } }];
this._argumentProcessors = [
{
processArgument(a) {
// URI, Regex
return revive(a, 0);
}
},
{
processArgument(arg) {
return cloneAndChange(arg, function (obj) {
// Reverse of https://github.com/Microsoft/vscode/blob/1f28c5fc681f4c01226460b6d1c7e91b8acb4a5b/src/vs/workbench/api/node/extHostCommands.ts#L112-L127
if (Range.isIRange(obj)) {
return extHostTypeConverter.Range.to(obj);
}
if (Position.isIPosition(obj)) {
return extHostTypeConverter.Position.to(obj);
}
if (Range.isIRange((obj as modes.Location).range) && URI.isUri((obj as modes.Location).uri)) {
return extHostTypeConverter.location.to(obj);
}
if (!Array.isArray(obj)) {
return obj;
}
});
}
}
];
}
get converter(): CommandsConverter {
@@ -78,7 +107,7 @@ export class ExtHostCommands implements ExtHostCommandsShape {
});
}
executeCommand<T>(id: string, ...args: any[]): Thenable<T> {
executeCommand<T>(id: string, ...args: any[]): Promise<T> {
this._logService.trace('ExtHostCommands#executeCommand', id);
if (this._commands.has(id)) {
@@ -108,7 +137,7 @@ export class ExtHostCommands implements ExtHostCommandsShape {
}
}
private _executeContributedCommand<T>(id: string, args: any[]): Thenable<T> {
private _executeContributedCommand<T>(id: string, args: any[]): Promise<T> {
let { callback, thisArg, description } = this._commands.get(id);
if (description) {
for (let i = 0; i < description.args.length; i++) {
@@ -129,7 +158,7 @@ export class ExtHostCommands implements ExtHostCommandsShape {
}
}
$executeContributedCommand<T>(id: string, ...args: any[]): Thenable<T> {
$executeContributedCommand<T>(id: string, ...args: any[]): Promise<T> {
this._logService.trace('ExtHostCommands#$executeContributedCommand', id);
if (!this._commands.has(id)) {
@@ -140,7 +169,7 @@ export class ExtHostCommands implements ExtHostCommandsShape {
}
}
getCommands(filterUnderscoreCommands: boolean = false): Thenable<string[]> {
getCommands(filterUnderscoreCommands: boolean = false): Promise<string[]> {
this._logService.trace('ExtHostCommands#getCommands', filterUnderscoreCommands);
return this._proxy.$getCommands().then(result => {
@@ -151,7 +180,7 @@ export class ExtHostCommands implements ExtHostCommandsShape {
});
}
$getContributedCommandHandlerDescriptions(): Thenable<{ [id: string]: string | ICommandHandlerDescription }> {
$getContributedCommandHandlerDescriptions(): Promise<{ [id: string]: string | ICommandHandlerDescription }> {
const result: { [id: string]: string | ICommandHandlerDescription } = Object.create(null);
this._commands.forEach((command, id) => {
let { description } = command;
@@ -226,7 +255,7 @@ export class CommandsConverter {
}
}
private _executeConvertedCommand<R>(...args: any[]): Thenable<R> {
private _executeConvertedCommand<R>(...args: any[]): Promise<R> {
const actualCmd = this._heap.get<vscode.Command>(args[0]);
return this._commands.executeCommand(actualCmd.command, ...actualCmd.arguments);
}

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { asThenable } from 'vs/base/common/async';
import { asPromise } from 'vs/base/common/async';
import { URI, UriComponents } from 'vs/base/common/uri';
import * as modes from 'vs/editor/common/modes';
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
@@ -13,14 +13,21 @@ import { ExtHostCommentsShape, IMainContext, MainContext, MainThreadCommentsShap
import { CommandsConverter } from './extHostCommands';
import { IRange } from 'vs/editor/common/core/range';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
interface HandlerData<T> {
extensionId: ExtensionIdentifier;
provider: T;
}
export class ExtHostComments implements ExtHostCommentsShape {
private static handlePool = 0;
private _proxy: MainThreadCommentsShape;
private _documentProviders = new Map<number, vscode.DocumentCommentProvider>();
private _workspaceProviders = new Map<number, vscode.WorkspaceCommentProvider>();
private _documentProviders = new Map<number, HandlerData<vscode.DocumentCommentProvider>>();
private _workspaceProviders = new Map<number, HandlerData<vscode.WorkspaceCommentProvider>>();
constructor(
mainContext: IMainContext,
@@ -31,13 +38,16 @@ export class ExtHostComments implements ExtHostCommentsShape {
}
registerWorkspaceCommentProvider(
extensionId: string,
extensionId: ExtensionIdentifier,
provider: vscode.WorkspaceCommentProvider
): vscode.Disposable {
const handle = ExtHostComments.handlePool++;
this._workspaceProviders.set(handle, provider);
this._workspaceProviders.set(handle, {
extensionId,
provider
});
this._proxy.$registerWorkspaceCommentProvider(handle, extensionId);
this.registerListeners(handle, provider);
this.registerListeners(handle, extensionId, provider);
return {
dispose: () => {
@@ -48,16 +58,21 @@ export class ExtHostComments implements ExtHostCommentsShape {
}
registerDocumentCommentProvider(
extensionId: ExtensionIdentifier,
provider: vscode.DocumentCommentProvider
): vscode.Disposable {
const handle = ExtHostComments.handlePool++;
this._documentProviders.set(handle, provider);
this._documentProviders.set(handle, {
extensionId,
provider
});
this._proxy.$registerDocumentCommentProvider(handle, {
startDraftLabel: provider.startDraftLabel,
deleteDraftLabel: provider.deleteDraftLabel,
finishDraftLabel: provider.finishDraftLabel
finishDraftLabel: provider.finishDraftLabel,
reactionGroup: provider.reactionGroup
});
this.registerListeners(handle, provider);
this.registerListeners(handle, extensionId, provider);
return {
dispose: () => {
@@ -67,7 +82,7 @@ export class ExtHostComments implements ExtHostCommentsShape {
};
}
$createNewCommentThread(handle: number, uri: UriComponents, range: IRange, text: string): Thenable<modes.CommentThread> {
$createNewCommentThread(handle: number, uri: UriComponents, range: IRange, text: string): Promise<modes.CommentThread | null> {
const data = this._documents.getDocumentData(URI.revive(uri));
const ran = <vscode.Range>extHostTypeConverter.Range.to(range);
@@ -75,13 +90,13 @@ export class ExtHostComments implements ExtHostCommentsShape {
return Promise.resolve(null);
}
const provider = this._documentProviders.get(handle);
return asThenable(() => {
return provider.createNewCommentThread(data.document, ran, text, CancellationToken.None);
}).then(commentThread => commentThread ? convertToCommentThread(provider, commentThread, this._commandsConverter) : null);
const handlerData = this._documentProviders.get(handle);
return asPromise(() => {
return handlerData.provider.createNewCommentThread(data.document, ran, text, CancellationToken.None);
}).then(commentThread => commentThread ? convertToCommentThread(handlerData.extensionId, handlerData.provider, commentThread, this._commandsConverter) : null);
}
$replyToCommentThread(handle: number, uri: UriComponents, range: IRange, thread: modes.CommentThread, text: string): Thenable<modes.CommentThread> {
$replyToCommentThread(handle: number, uri: UriComponents, range: IRange, thread: modes.CommentThread, text: string): Promise<modes.CommentThread | null> {
const data = this._documents.getDocumentData(URI.revive(uri));
const ran = <vscode.Range>extHostTypeConverter.Range.to(range);
@@ -89,107 +104,155 @@ export class ExtHostComments implements ExtHostCommentsShape {
return Promise.resolve(null);
}
const provider = this._documentProviders.get(handle);
return asThenable(() => {
return provider.replyToCommentThread(data.document, ran, convertFromCommentThread(thread), text, CancellationToken.None);
}).then(commentThread => commentThread ? convertToCommentThread(provider, commentThread, this._commandsConverter) : null);
const handlerData = this._documentProviders.get(handle);
return asPromise(() => {
return handlerData.provider.replyToCommentThread(data.document, ran, convertFromCommentThread(thread), text, CancellationToken.None);
}).then(commentThread => commentThread ? convertToCommentThread(handlerData.extensionId, handlerData.provider, commentThread, this._commandsConverter) : null);
}
$editComment(handle: number, uri: UriComponents, comment: modes.Comment, text: string): Thenable<void> {
$editComment(handle: number, uri: UriComponents, comment: modes.Comment, text: string): Promise<void> {
const data = this._documents.getDocumentData(URI.revive(uri));
if (!data || !data.document) {
throw new Error('Unable to retrieve document from URI');
}
const provider = this._documentProviders.get(handle);
return asThenable(() => {
return provider.editComment(data.document, convertFromComment(comment), text, CancellationToken.None);
const handlerData = this._documentProviders.get(handle);
return asPromise(() => {
return handlerData.provider.editComment(data.document, convertFromComment(comment), text, CancellationToken.None);
});
}
$deleteComment(handle: number, uri: UriComponents, comment: modes.Comment): Thenable<void> {
$deleteComment(handle: number, uri: UriComponents, comment: modes.Comment): Promise<void> {
const data = this._documents.getDocumentData(URI.revive(uri));
if (!data || !data.document) {
throw new Error('Unable to retrieve document from URI');
}
const provider = this._documentProviders.get(handle);
return asThenable(() => {
return provider.deleteComment(data.document, convertFromComment(comment), CancellationToken.None);
const handlerData = this._documentProviders.get(handle);
return asPromise(() => {
return handlerData.provider.deleteComment(data.document, convertFromComment(comment), CancellationToken.None);
});
}
$startDraft(handle: number): Thenable<void> {
const provider = this._documentProviders.get(handle);
return asThenable(() => {
return provider.startDraft(CancellationToken.None);
$startDraft(handle: number, uri: UriComponents): Promise<void> {
const data = this._documents.getDocumentData(URI.revive(uri));
if (!data || !data.document) {
throw new Error('Unable to retrieve document from URI');
}
const handlerData = this._documentProviders.get(handle);
return asPromise(() => {
return handlerData.provider.startDraft(data.document, CancellationToken.None);
});
}
$deleteDraft(handle: number): Thenable<void> {
const provider = this._documentProviders.get(handle);
return asThenable(() => {
return provider.deleteDraft(CancellationToken.None);
$deleteDraft(handle: number, uri: UriComponents): Promise<void> {
const data = this._documents.getDocumentData(URI.revive(uri));
if (!data || !data.document) {
throw new Error('Unable to retrieve document from URI');
}
const handlerData = this._documentProviders.get(handle);
return asPromise(() => {
return handlerData.provider.deleteDraft(data.document, CancellationToken.None);
});
}
$finishDraft(handle: number): Thenable<void> {
const provider = this._documentProviders.get(handle);
return asThenable(() => {
return provider.finishDraft(CancellationToken.None);
$finishDraft(handle: number, uri: UriComponents): Promise<void> {
const data = this._documents.getDocumentData(URI.revive(uri));
if (!data || !data.document) {
throw new Error('Unable to retrieve document from URI');
}
const handlerData = this._documentProviders.get(handle);
return asPromise(() => {
return handlerData.provider.finishDraft(data.document, CancellationToken.None);
});
}
$provideDocumentComments(handle: number, uri: UriComponents): Thenable<modes.CommentInfo> {
$addReaction(handle: number, uri: UriComponents, comment: modes.Comment, reaction: modes.CommentReaction): Promise<void> {
const data = this._documents.getDocumentData(URI.revive(uri));
if (!data || !data.document) {
throw new Error('Unable to retrieve document from URI');
}
const handlerData = this._documentProviders.get(handle);
return asPromise(() => {
return handlerData.provider.addReaction(data.document, convertFromComment(comment), reaction);
});
}
$deleteReaction(handle: number, uri: UriComponents, comment: modes.Comment, reaction: modes.CommentReaction): Promise<void> {
const data = this._documents.getDocumentData(URI.revive(uri));
if (!data || !data.document) {
throw new Error('Unable to retrieve document from URI');
}
const handlerData = this._documentProviders.get(handle);
return asPromise(() => {
return handlerData.provider.deleteReaction(data.document, convertFromComment(comment), reaction);
});
}
$provideDocumentComments(handle: number, uri: UriComponents): Promise<modes.CommentInfo> {
const data = this._documents.getDocumentData(URI.revive(uri));
if (!data || !data.document) {
return Promise.resolve(null);
}
const provider = this._documentProviders.get(handle);
return asThenable(() => {
return provider.provideDocumentComments(data.document, CancellationToken.None);
}).then(commentInfo => commentInfo ? convertCommentInfo(handle, provider, commentInfo, this._commandsConverter) : null);
const handlerData = this._documentProviders.get(handle);
return asPromise(() => {
return handlerData.provider.provideDocumentComments(data.document, CancellationToken.None);
}).then(commentInfo => commentInfo ? convertCommentInfo(handle, handlerData.extensionId, handlerData.provider, commentInfo, this._commandsConverter) : null);
}
$provideWorkspaceComments(handle: number): Thenable<modes.CommentThread[]> {
const provider = this._workspaceProviders.get(handle);
if (!provider) {
$provideWorkspaceComments(handle: number): Promise<modes.CommentThread[] | null> {
const handlerData = this._workspaceProviders.get(handle);
if (!handlerData) {
return Promise.resolve(null);
}
return asThenable(() => {
return provider.provideWorkspaceComments(CancellationToken.None);
return asPromise(() => {
return handlerData.provider.provideWorkspaceComments(CancellationToken.None);
}).then(comments =>
comments.map(comment => convertToCommentThread(provider, comment, this._commandsConverter)
comments.map(comment => convertToCommentThread(handlerData.extensionId, handlerData.provider, comment, this._commandsConverter)
));
}
private registerListeners(handle: number, provider: vscode.DocumentCommentProvider | vscode.WorkspaceCommentProvider) {
private registerListeners(handle: number, extensionId: ExtensionIdentifier, provider: vscode.DocumentCommentProvider | vscode.WorkspaceCommentProvider) {
provider.onDidChangeCommentThreads(event => {
this._proxy.$onDidCommentThreadsChange(handle, {
changed: event.changed.map(thread => convertToCommentThread(provider, thread, this._commandsConverter)),
added: event.added.map(thread => convertToCommentThread(provider, thread, this._commandsConverter)),
removed: event.removed.map(thread => convertToCommentThread(provider, thread, this._commandsConverter)),
changed: event.changed.map(thread => convertToCommentThread(extensionId, provider, thread, this._commandsConverter)),
added: event.added.map(thread => convertToCommentThread(extensionId, provider, thread, this._commandsConverter)),
removed: event.removed.map(thread => convertToCommentThread(extensionId, provider, thread, this._commandsConverter)),
draftMode: !!(provider as vscode.DocumentCommentProvider).startDraft && !!(provider as vscode.DocumentCommentProvider).finishDraft ? (event.inDraftMode ? modes.DraftMode.InDraft : modes.DraftMode.NotInDraft) : modes.DraftMode.NotSupported
});
});
}
}
function convertCommentInfo(owner: number, provider: vscode.DocumentCommentProvider, vscodeCommentInfo: vscode.CommentInfo, commandsConverter: CommandsConverter): modes.CommentInfo {
function convertCommentInfo(owner: number, extensionId: ExtensionIdentifier, provider: vscode.DocumentCommentProvider, vscodeCommentInfo: vscode.CommentInfo, commandsConverter: CommandsConverter): modes.CommentInfo {
return {
threads: vscodeCommentInfo.threads.map(x => convertToCommentThread(provider, x, commandsConverter)),
extensionId: extensionId.value,
threads: vscodeCommentInfo.threads.map(x => convertToCommentThread(extensionId, provider, x, commandsConverter)),
commentingRanges: vscodeCommentInfo.commentingRanges ? vscodeCommentInfo.commentingRanges.map(range => extHostTypeConverter.Range.from(range)) : [],
draftMode: provider.startDraft && provider.finishDraft ? (vscodeCommentInfo.inDraftMode ? modes.DraftMode.InDraft : modes.DraftMode.NotInDraft) : modes.DraftMode.NotSupported
};
}
function convertToCommentThread(provider: vscode.DocumentCommentProvider | vscode.WorkspaceCommentProvider, vscodeCommentThread: vscode.CommentThread, commandsConverter: CommandsConverter): modes.CommentThread {
function convertToCommentThread(extensionId: ExtensionIdentifier, provider: vscode.DocumentCommentProvider | vscode.WorkspaceCommentProvider, vscodeCommentThread: vscode.CommentThread, commandsConverter: CommandsConverter): modes.CommentThread {
return {
extensionId: extensionId.value,
threadId: vscodeCommentThread.threadId,
resource: vscodeCommentThread.resource.toString(),
range: extHostTypeConverter.Range.from(vscodeCommentThread.range),
@@ -225,7 +288,8 @@ function convertFromComment(comment: modes.Comment): vscode.Comment {
userIconPath: userIconPath,
canEdit: comment.canEdit,
canDelete: comment.canDelete,
isDraft: comment.isDraft
isDraft: comment.isDraft,
commentReactions: comment.commentReactions
};
}
@@ -241,6 +305,7 @@ function convertToComment(provider: vscode.DocumentCommentProvider | vscode.Work
canEdit: canEdit,
canDelete: canDelete,
command: vscodeComment.command ? commandsConverter.toInternal(vscodeComment.command) : null,
isDraft: vscodeComment.isDraft
isDraft: vscodeComment.isDraft,
commentReactions: vscodeComment.commentReactions
};
}

View File

@@ -16,6 +16,8 @@ import { WorkspaceConfigurationChangeEvent } from 'vs/workbench/services/configu
import { ResourceMap } from 'vs/base/common/map';
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 { Barrier } from 'vs/base/common/async';
function lookUp(tree: any, key: string) {
if (key) {
@@ -38,6 +40,34 @@ type ConfigurationInspect<T> = {
export class ExtHostConfiguration implements ExtHostConfigurationShape {
private readonly _proxy: MainThreadConfigurationShape;
private readonly _extHostWorkspace: ExtHostWorkspace;
private readonly _barrier: Barrier;
private _actual: ExtHostConfigProvider;
constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspace) {
this._proxy = proxy;
this._extHostWorkspace = extHostWorkspace;
this._barrier = new Barrier();
this._actual = null;
}
public getConfigProvider(): Promise<ExtHostConfigProvider> {
return this._barrier.wait().then(_ => this._actual);
}
$initializeConfiguration(data: IConfigurationInitData): void {
this._actual = new ExtHostConfigProvider(this._proxy, this._extHostWorkspace, data);
this._barrier.open();
}
$acceptConfigurationChanged(data: IConfigurationInitData, eventData: IWorkspaceConfigurationChangeEventData): void {
this._actual.$acceptConfigurationChanged(data, eventData);
}
}
export class ExtHostConfigProvider {
private readonly _onDidChangeConfiguration = new Emitter<vscode.ConfigurationChangeEvent>();
private readonly _proxy: MainThreadConfigurationShape;
private readonly _extHostWorkspace: ExtHostWorkspace;
@@ -47,7 +77,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspace, data: IConfigurationInitData) {
this._proxy = proxy;
this._extHostWorkspace = extHostWorkspace;
this._configuration = ExtHostConfiguration.parse(data);
this._configuration = ExtHostConfigProvider.parse(data);
this._configurationScopes = data.configurationScopes;
}
@@ -55,12 +85,13 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
return this._onDidChangeConfiguration && this._onDidChangeConfiguration.event;
}
$acceptConfigurationChanged(data: IConfigurationData, eventData: IWorkspaceConfigurationChangeEventData) {
this._configuration = ExtHostConfiguration.parse(data);
$acceptConfigurationChanged(data: IConfigurationInitData, eventData: IWorkspaceConfigurationChangeEventData) {
this._configuration = ExtHostConfigProvider.parse(data);
this._configurationScopes = data.configurationScopes;
this._onDidChangeConfiguration.fire(this._toConfigurationChangeEvent(eventData));
}
getConfiguration(section?: string, resource?: URI, extensionId?: string): vscode.WorkspaceConfiguration {
getConfiguration(section?: string, resource?: URI, extensionId?: ExtensionIdentifier): vscode.WorkspaceConfiguration {
const config = this._toReadonlyValue(section
? lookUp(this._configuration.getValue(null, { resource }, this._extHostWorkspace.workspace), section)
: this._configuration.getValue(null, { resource }, this._extHostWorkspace.workspace));
@@ -70,7 +101,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
}
function parseConfigurationTarget(arg: boolean | ExtHostConfigurationTarget): ConfigurationTarget {
if (arg === void 0 || arg === null) {
if (arg === undefined || arg === null) {
return null;
}
if (typeof arg === 'boolean') {
@@ -94,9 +125,9 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
if (typeof result === 'undefined') {
result = defaultValue;
} else {
let clonedConfig = void 0;
let clonedConfig = undefined;
const cloneOnWriteProxy = (target: any, accessor: string): any => {
let clonedTarget = void 0;
let clonedTarget = undefined;
const cloneTarget = () => {
clonedConfig = clonedConfig ? clonedConfig : deepClone(config);
clonedTarget = clonedTarget ? clonedTarget : lookUp(clonedConfig, accessor);
@@ -142,7 +173,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
update: (key: string, value: any, arg: ExtHostConfigurationTarget | boolean) => {
key = section ? `${section}.${key}` : key;
const target = parseConfigurationTarget(arg);
if (value !== void 0) {
if (value !== undefined) {
return this._proxy.$updateConfigurationOption(target, key, value, resource);
} else {
return this._proxy.$removeConfigurationOption(target, key, resource);
@@ -187,11 +218,11 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
return readonlyProxy(result);
}
private _validateConfigurationAccess(key: string, resource: URI, extensionId: string): void {
private _validateConfigurationAccess(key: string, resource: URI, extensionId: ExtensionIdentifier): void {
const scope = OVERRIDE_PROPERTY_PATTERN.test(key) ? ConfigurationScope.RESOURCE : this._configurationScopes[key];
const extensionIdText = extensionId ? `[${extensionId}] ` : '';
const extensionIdText = extensionId ? `[${extensionId.value}] ` : '';
if (ConfigurationScope.RESOURCE === scope) {
if (resource === void 0) {
if (resource === undefined) {
console.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;
@@ -219,11 +250,11 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
}
private static parse(data: IConfigurationData): Configuration {
const defaultConfiguration = ExtHostConfiguration.parseConfigurationModel(data.defaults);
const userConfiguration = ExtHostConfiguration.parseConfigurationModel(data.user);
const workspaceConfiguration = ExtHostConfiguration.parseConfigurationModel(data.workspace);
const defaultConfiguration = ExtHostConfigProvider.parseConfigurationModel(data.defaults);
const userConfiguration = ExtHostConfigProvider.parseConfigurationModel(data.user);
const workspaceConfiguration = ExtHostConfigProvider.parseConfigurationModel(data.workspace);
const folders: ResourceMap<ConfigurationModel> = Object.keys(data.folders).reduce((result, key) => {
result.set(URI.parse(key), ExtHostConfiguration.parseConfigurationModel(data.folders[key]));
result.set(URI.parse(key), ExtHostConfigProvider.parseConfigurationModel(data.folders[key]));
return result;
}, new ResourceMap<ConfigurationModel>());
return new Configuration(defaultConfiguration, userConfiguration, workspaceConfiguration, folders, new ConfigurationModel(), new ResourceMap<ConfigurationModel>(), false);

View File

@@ -9,7 +9,7 @@ import * as paths from 'vs/base/common/paths';
import { Schemas } from 'vs/base/common/network';
import { URI, UriComponents } from 'vs/base/common/uri';
import { Event, Emitter } from 'vs/base/common/event';
import { asThenable } from 'vs/base/common/async';
import { asPromise } from 'vs/base/common/async';
import * as nls from 'vs/nls';
import {
MainContext, MainThreadDebugServiceShape, ExtHostDebugServiceShape, DebugSessionUUID,
@@ -22,11 +22,11 @@ import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumentsAndEditors';
import { ITerminalSettings, IDebuggerContribution, IConfig, IDebugAdapter, IDebugAdapterServer, IDebugAdapterExecutable, IAdapterDescriptor } from 'vs/workbench/parts/debug/common/debug';
import { getTerminalLauncher, hasChildprocesses, prepareCommand } from 'vs/workbench/parts/debug/node/terminals';
import { getTerminalLauncher, hasChildProcesses, prepareCommand } from 'vs/workbench/parts/debug/node/terminals';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { AbstractVariableResolverService } from 'vs/workbench/services/configurationResolver/node/variableResolver';
import { ExtHostConfiguration } from './extHostConfiguration';
import { convertToVSCPaths, convertToDAPaths, stringToUri, uriToString } from 'vs/workbench/parts/debug/common/debugUtils';
import { ExtHostConfiguration, ExtHostConfigProvider } from './extHostConfiguration';
import { convertToVSCPaths, convertToDAPaths } from 'vs/workbench/parts/debug/common/debugUtils';
import { ExtHostTerminalService } from 'vs/workbench/api/node/extHostTerminalService';
import { IDisposable } from 'vs/base/common/lifecycle';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
@@ -130,8 +130,8 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
const debuggers = <IDebuggerContribution[]>ed.contributes['debuggers'];
if (debuggers && debuggers.length > 0) {
for (const dbg of debuggers) {
// only debugger contributions with a "label" are considered a "defining" debugger contribution
if (dbg.type && dbg.label) {
// only debugger contributions with a label, program, or runtime attribute are considered a "defining" debugger contribution
if (dbg.type && (dbg.label || dbg.program || dbg.runtime)) {
debugTypes.push(dbg.type);
if (dbg.adapterExecutableCommand) {
this._aexCommands.set(dbg.type, dbg.adapterExecutableCommand);
@@ -162,7 +162,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
return result;
}
public addBreakpoints(breakpoints0: vscode.Breakpoint[]): Thenable<void> {
public addBreakpoints(breakpoints0: vscode.Breakpoint[]): Promise<void> {
this.startBreakpoints();
@@ -180,7 +180,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
this.fireBreakpointChanges(breakpoints, [], []);
// convert added breakpoints to DTOs
const dtos: (ISourceMultiBreakpointDto | IFunctionBreakpointDto)[] = [];
const dtos: Array<ISourceMultiBreakpointDto | IFunctionBreakpointDto> = [];
const map = new Map<string, ISourceMultiBreakpointDto>();
for (const bp of breakpoints) {
if (bp instanceof SourceBreakpoint) {
@@ -220,7 +220,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
return this._debugServiceProxy.$registerBreakpoints(dtos);
}
public removeBreakpoints(breakpoints0: vscode.Breakpoint[]): Thenable<void> {
public removeBreakpoints(breakpoints0: vscode.Breakpoint[]): Promise<void> {
this.startBreakpoints();
@@ -236,7 +236,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
return this._debugServiceProxy.$unregisterBreakpoints(ids, fids);
}
public startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration): Thenable<boolean> {
public startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration): Promise<boolean> {
return this._debugServiceProxy.$startDebugging(folder ? folder.uri : undefined, nameOrConfig);
}
@@ -250,10 +250,6 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
console.error('DebugConfigurationProvider.debugAdapterExecutable is deprecated and will be removed soon; please use DebugAdapterDescriptorFactory.createDebugAdapterDescriptor instead.');
}
if (provider.provideDebugAdapterTracker) {
// console.error('DebugConfigurationProvider.provideDebugAdapterTracker is deprecated and will be removed soon; please use DebugAdapterTrackerFactory.createDebugAdapterTracker instead.');
}
let handle = this._configProviderHandleCounter++;
this._configProviders.push({ type, handle, provider });
@@ -261,7 +257,6 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
!!provider.provideDebugConfigurations,
!!provider.resolveDebugConfiguration,
!!provider.debugAdapterExecutable, // TODO@AW: deprecated
!!provider.provideDebugAdapterTracker, // TODO@AW: deprecated
handle);
return new Disposable(() => {
@@ -316,7 +311,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
// RPC methods (ExtHostDebugServiceShape)
public $runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): Thenable<number | undefined> {
public $runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): Promise<number | undefined> {
if (args.kind === 'integrated') {
@@ -332,7 +327,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
return new Promise(resolve => {
if (this._integratedTerminalInstance) {
this._integratedTerminalInstance.processId.then(pid => {
resolve(hasChildprocesses(pid));
resolve(hasChildProcesses(pid));
}, err => {
resolve(true);
});
@@ -363,12 +358,13 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
return terminalLauncher.runInTerminal(args, config);
}
}
return void 0;
return undefined;
}
public $substituteVariables(folderUri: UriComponents | undefined, config: IConfig): Promise<IConfig> {
public async $substituteVariables(folderUri: UriComponents | undefined, config: IConfig): Promise<IConfig> {
const configProvider = await this._configurationService.getConfigProvider();
if (!this._variableResolver) {
this._variableResolver = new ExtHostVariableResolverService(this._workspaceService, this._editorsService, this._configurationService);
this._variableResolver = new ExtHostVariableResolverService(this._workspaceService, this._editorsService, configProvider);
}
let ws: IWorkspaceFolder;
const folder = this.getFolder(folderUri);
@@ -382,10 +378,10 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
}
};
}
return Promise.resolve(this._variableResolver.resolveAny(ws, config));
return this._variableResolver.resolveAny(ws, config);
}
public $startDASession(debugAdapterHandle: number, sessionDto: IDebugSessionDto): Thenable<void> {
public $startDASession(debugAdapterHandle: number, sessionDto: IDebugSessionDto): Promise<void> {
const mythis = this;
const session = this.getSession(sessionDto);
@@ -428,7 +424,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
}
// DA -> VS Code
message = convertToVSCPaths(message, source => stringToUri(source));
message = convertToVSCPaths(message, true);
mythis._debugServiceProxy.$acceptDAMessage(debugAdapterHandle, message);
});
@@ -460,7 +456,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
public $sendDAMessage(debugAdapterHandle: number, message: DebugProtocol.ProtocolMessage): Promise<void> {
// VS Code -> DA
message = convertToDAPaths(message, source => uriToString(source));
message = convertToDAPaths(message, false);
const tracker = this._debugAdaptersTrackers.get(debugAdapterHandle); // TODO@AW: same handle?
if (tracker) {
@@ -471,10 +467,10 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
if (da) {
da.sendMessage(message);
}
return void 0;
return undefined;
}
public $stopDASession(debugAdapterHandle: number): Thenable<void> {
public $stopDASession(debugAdapterHandle: number): Promise<void> {
const tracker = this._debugAdaptersTrackers.get(debugAdapterHandle);
this._debugAdaptersTrackers.delete(debugAdapterHandle);
@@ -487,7 +483,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
if (da) {
return da.stopSession();
} else {
return void 0;
return undefined;
}
}
@@ -552,7 +548,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
this.fireBreakpointChanges(a, r, c);
}
public $provideDebugConfigurations(configProviderHandle: number, folderUri: UriComponents | undefined): Thenable<vscode.DebugConfiguration[]> {
public $provideDebugConfigurations(configProviderHandle: number, folderUri: UriComponents | undefined): Promise<vscode.DebugConfiguration[]> {
let provider = this.getConfigProviderByHandle(configProviderHandle);
if (!provider) {
return Promise.reject(new Error('no handler found'));
@@ -560,10 +556,10 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
if (!provider.provideDebugConfigurations) {
return Promise.reject(new Error('handler has no method provideDebugConfigurations'));
}
return asThenable(() => provider.provideDebugConfigurations(this.getFolder(folderUri), CancellationToken.None));
return asPromise(() => provider.provideDebugConfigurations(this.getFolder(folderUri), CancellationToken.None));
}
public $resolveDebugConfiguration(configProviderHandle: number, folderUri: UriComponents | undefined, debugConfiguration: vscode.DebugConfiguration): Thenable<vscode.DebugConfiguration> {
public $resolveDebugConfiguration(configProviderHandle: number, folderUri: UriComponents | undefined, debugConfiguration: vscode.DebugConfiguration): Promise<vscode.DebugConfiguration> {
let provider = this.getConfigProviderByHandle(configProviderHandle);
if (!provider) {
return Promise.reject(new Error('no handler found'));
@@ -571,11 +567,11 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
if (!provider.resolveDebugConfiguration) {
return Promise.reject(new Error('handler has no method resolveDebugConfiguration'));
}
return asThenable(() => provider.resolveDebugConfiguration(this.getFolder(folderUri), debugConfiguration, CancellationToken.None));
return asPromise(() => provider.resolveDebugConfiguration(this.getFolder(folderUri), debugConfiguration, CancellationToken.None));
}
// TODO@AW legacy
public $legacyDebugAdapterExecutable(configProviderHandle: number, folderUri: UriComponents | undefined): Thenable<IAdapterDescriptor> {
public $legacyDebugAdapterExecutable(configProviderHandle: number, folderUri: UriComponents | undefined): Promise<IAdapterDescriptor> {
let provider = this.getConfigProviderByHandle(configProviderHandle);
if (!provider) {
return Promise.reject(new Error('no handler found'));
@@ -583,10 +579,10 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
if (!provider.debugAdapterExecutable) {
return Promise.reject(new Error('handler has no method debugAdapterExecutable'));
}
return asThenable(() => provider.debugAdapterExecutable(this.getFolder(folderUri), CancellationToken.None)).then(x => this.convertToDto(x));
return asPromise(() => provider.debugAdapterExecutable(this.getFolder(folderUri), CancellationToken.None)).then(x => this.convertToDto(x));
}
public $provideDebugAdapter(adapterProviderHandle: number, sessionDto: IDebugSessionDto): Thenable<IAdapterDescriptor> {
public $provideDebugAdapter(adapterProviderHandle: number, sessionDto: IDebugSessionDto): Promise<IAdapterDescriptor> {
let adapterProvider = this.getAdapterProviderByHandle(adapterProviderHandle);
if (!adapterProvider) {
return Promise.reject(new Error('no handler found'));
@@ -696,15 +692,9 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
const config = session.configuration;
const type = config.type;
const promises1 = this._configProviders
.filter(tuple => tuple.provider.provideDebugAdapterTracker && (tuple.type === type || tuple.type === '*'))
.map(tuple => asThenable(() => tuple.provider.provideDebugAdapterTracker(session, session.workspaceFolder, session.configuration, CancellationToken.None)).then(p => p).catch(err => null));
const promises2 = this._trackerFactories
const promises = this._trackerFactories
.filter(tuple => tuple.type === type || tuple.type === '*')
.map(tuple => asThenable(() => tuple.factory.createDebugAdapterTracker(session)).then(p => p).catch(err => null));
const promises = promises1.concat(promises2);
.map(tuple => asPromise(() => tuple.factory.createDebugAdapterTracker(session)).then(p => p).catch(err => null));
return Promise.race([
Promise.all(promises).then(trackers => {
@@ -738,13 +728,13 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
const pairs = this._configProviders.filter(p => p.type === session.type);
if (pairs.length > 0) {
if (pairs[0].provider.debugAdapterExecutable) {
return asThenable(() => pairs[0].provider.debugAdapterExecutable(session.workspaceFolder, CancellationToken.None));
return asPromise(() => pairs[0].provider.debugAdapterExecutable(session.workspaceFolder, CancellationToken.None));
}
}
if (adapterProvider) {
const extensionRegistry = await this._extensionService.getExtensionRegistry();
return asThenable(() => adapterProvider.createDebugAdapterDescriptor(session, this.daExecutableFromPackage(session, extensionRegistry)));
return asPromise(() => adapterProvider.createDebugAdapterDescriptor(session, this.daExecutableFromPackage(session, extensionRegistry)));
}
// try deprecated command based extension API "adapterExecutableCommand" to determine the executable
@@ -841,7 +831,7 @@ export class ExtHostDebugSession implements vscode.DebugSession {
return this._configuration;
}
public customRequest(command: string, args: any): Thenable<any> {
public customRequest(command: string, args: any): Promise<any> {
return this._debugServiceProxy.$customDebugAdapterRequest(this._id, command, args);
}
}
@@ -865,7 +855,7 @@ export class ExtHostDebugConsole implements vscode.DebugConsole {
export class ExtHostVariableResolverService extends AbstractVariableResolverService {
constructor(workspaceService: ExtHostWorkspace, editorService: ExtHostDocumentsAndEditors, configurationService: ExtHostConfiguration) {
constructor(workspaceService: ExtHostWorkspace, editorService: ExtHostDocumentsAndEditors, configurationService: ExtHostConfigProvider) {
super({
getFolderUri: (folderName: string): URI => {
const folders = workspaceService.getWorkspaceFolders();
@@ -936,27 +926,27 @@ class MultiTracker implements vscode.DebugAdapterTracker {
}
onWillStartSession(): void {
this.trackers.forEach(t => t.onWillStartSession ? t.onWillStartSession() : (t.startDebugAdapter ? t.startDebugAdapter() : void 0));
this.trackers.forEach(t => t.onWillStartSession ? t.onWillStartSession() : undefined);
}
onWillReceiveMessage(message: any): void {
this.trackers.forEach(t => t.onWillReceiveMessage ? t.onWillReceiveMessage(message) : (t.toDebugAdapter ? t.toDebugAdapter(message) : void 0));
this.trackers.forEach(t => t.onWillReceiveMessage ? t.onWillReceiveMessage(message) : undefined);
}
onDidSendMessage(message: any): void {
this.trackers.forEach(t => t.onDidSendMessage ? t.onDidSendMessage(message) : (t.fromDebugAdapter ? t.fromDebugAdapter(message) : void 0));
this.trackers.forEach(t => t.onDidSendMessage ? t.onDidSendMessage(message) : undefined);
}
onWillStopSession(): void {
this.trackers.forEach(t => t.onWillStopSession ? t.onWillStopSession() : (t.stopDebugAdapter ? t.stopDebugAdapter() : void 0));
this.trackers.forEach(t => t.onWillStopSession ? t.onWillStopSession() : undefined);
}
onError(error: Error): void {
this.trackers.forEach(t => t.onError ? t.onError(error) : (t.debugAdapterError ? t.debugAdapterError(error) : void 0));
this.trackers.forEach(t => t.onError ? t.onError(error) : undefined);
}
onExit(code: number, signal: string): void {
this.trackers.forEach(t => t.onExit ? t.onExit(code, signal) : (t.debugAdapterExit ? t.debugAdapterExit(code, signal) : void 0));
this.trackers.forEach(t => t.onExit ? t.onExit(code, signal) : undefined);
}
}
@@ -987,7 +977,7 @@ class DirectDebugAdapter extends AbstractDebugAdapter implements IDapTransport {
// AbstractDebugAdapter
startSession(): Promise<void> {
return Promise.resolve(void 0);
return Promise.resolve(undefined);
}
// AbstractDebugAdapter
@@ -999,7 +989,7 @@ class DirectDebugAdapter extends AbstractDebugAdapter implements IDapTransport {
// AbstractDebugAdapter
stopSession(): Promise<void> {
this.stop();
return Promise.resolve(void 0);
return Promise.resolve(undefined);
}
// IDapTransport

View File

@@ -8,10 +8,11 @@ import { URI } from 'vs/base/common/uri';
import { MainContext, IMainContext, ExtHostDecorationsShape, MainThreadDecorationsShape, DecorationData, DecorationRequest, DecorationReply } from 'vs/workbench/api/node/extHost.protocol';
import { Disposable } from 'vs/workbench/api/node/extHostTypes';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
interface ProviderData {
provider: vscode.DecorationProvider;
extensionId: string;
extensionId: ExtensionIdentifier;
}
export class ExtHostDecorations implements ExtHostDecorationsShape {
@@ -25,10 +26,10 @@ export class ExtHostDecorations implements ExtHostDecorationsShape {
this._proxy = mainContext.getProxy(MainContext.MainThreadDecorations);
}
registerDecorationProvider(provider: vscode.DecorationProvider, extensionId: string): vscode.Disposable {
registerDecorationProvider(provider: vscode.DecorationProvider, extensionId: ExtensionIdentifier): vscode.Disposable {
const handle = ExtHostDecorations._handlePool++;
this._provider.set(handle, { provider, extensionId });
this._proxy.$registerDecorationProvider(handle, extensionId);
this._proxy.$registerDecorationProvider(handle, extensionId.value);
const listener = provider.onDidChangeDecorations(e => {
this._proxy.$onDidChange(handle, !e ? null : Array.isArray(e) ? e : [e]);
@@ -41,18 +42,18 @@ export class ExtHostDecorations implements ExtHostDecorationsShape {
});
}
$provideDecorations(requests: DecorationRequest[], token: CancellationToken): Thenable<DecorationReply> {
$provideDecorations(requests: DecorationRequest[], token: CancellationToken): Promise<DecorationReply> {
const result: DecorationReply = Object.create(null);
return Promise.all(requests.map(request => {
const { handle, uri, id } = request;
if (!this._provider.has(handle)) {
// might have been unregistered in the meantime
return void 0;
return undefined;
}
const { provider, extensionId } = this._provider.get(handle);
return Promise.resolve(provider.provideDecoration(URI.revive(uri), token)).then(data => {
if (data && data.letter && data.letter.length !== 1) {
console.warn(`INVALID decoration from extension '${extensionId}'. The 'letter' must be set and be one character, not '${data.letter}'.`);
console.warn(`INVALID decoration from extension '${extensionId.value}'. The 'letter' must be set and be one character, not '${data.letter}'.`);
}
result[id] = data && <DecorationData>[data.priority, data.bubble, data.title, data.letter, data.color, data.source];
}, err => {

View File

@@ -11,7 +11,7 @@ import { MainContext, MainThreadDiagnosticsShape, ExtHostDiagnosticsShape, IMain
import { DiagnosticSeverity, Diagnostic } from './extHostTypes';
import * as converter from './extHostTypeConverters';
import { mergeSort, equals } from 'vs/base/common/arrays';
import { Event, Emitter, debounceEvent, mapEvent } from 'vs/base/common/event';
import { Event, Emitter } from 'vs/base/common/event';
import { keys } from 'vs/base/common/map';
export class DiagnosticCollection implements vscode.DiagnosticCollection {
@@ -249,7 +249,7 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
return { uris };
}
readonly onDidChangeDiagnostics: Event<vscode.DiagnosticChangeEvent> = mapEvent(debounceEvent(this._onDidChangeDiagnostics.event, ExtHostDiagnostics._debouncer, 50), ExtHostDiagnostics._mapper);
readonly onDidChangeDiagnostics: Event<vscode.DiagnosticChangeEvent> = Event.map(Event.debounce(this._onDidChangeDiagnostics.event, ExtHostDiagnostics._debouncer, 50), ExtHostDiagnostics._mapper);
constructor(mainContext: IMainContext) {
this._proxy = mainContext.getProxy(MainContext.MainThreadDiagnostics);

View File

@@ -15,13 +15,13 @@ export class ExtHostDialogs {
this._proxy = mainContext.getProxy(MainContext.MainThreadDialogs);
}
showOpenDialog(options: vscode.OpenDialogOptions): Thenable<URI[]> {
showOpenDialog(options: vscode.OpenDialogOptions): Promise<URI[]> {
return this._proxy.$showOpenDialog(options).then(filepaths => {
return filepaths && filepaths.map(URI.revive);
});
}
showSaveDialog(options: vscode.SaveDialogOptions): Thenable<URI> {
showSaveDialog(options: vscode.SaveDialogOptions): Promise<URI> {
return this._proxy.$showSaveDialog(options).then(filepath => {
return filepath && URI.revive(filepath);
});

View File

@@ -97,7 +97,7 @@ export class ExtHostDocumentData extends MirrorTextModel {
this._isDirty = isDirty;
}
private _save(): Thenable<boolean> {
private _save(): Promise<boolean> {
if (this._isDisposed) {
return Promise.reject(new Error('Document has been closed'));
}

View File

@@ -5,7 +5,7 @@
import { Event } from 'vs/base/common/event';
import { URI, UriComponents } from 'vs/base/common/uri';
import { sequence, always } from 'vs/base/common/async';
import { sequence } from 'vs/base/common/async';
import { illegalState } from 'vs/base/common/errors';
import { ExtHostDocumentSaveParticipantShape, MainThreadTextEditorsShape, ResourceTextEditDto } from 'vs/workbench/api/node/extHost.protocol';
import { TextEdit } from 'vs/workbench/api/node/extHostTypes';
@@ -48,7 +48,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
};
}
$participateInSave(data: UriComponents, reason: SaveReason): Thenable<boolean[]> {
$participateInSave(data: UriComponents, reason: SaveReason): Promise<boolean[]> {
const resource = URI.revive(data);
const entries = this._callbacks.toArray();
@@ -67,7 +67,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
return this._deliverEventAsyncAndBlameBadListeners(listener, <any>{ document, reason: TextDocumentSaveReason.to(reason) });
};
}));
return always(promise, () => clearTimeout(didTimeoutHandle));
return promise.finally(() => clearTimeout(didTimeoutHandle));
}
private _deliverEventAsyncAndBlameBadListeners([listener, thisArg, extension]: Listener, stubEvent: vscode.TextDocumentWillSaveEvent): Promise<any> {
@@ -83,7 +83,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
}, err => {
this._logService.error(`onWillSaveTextDocument-listener from extension '${extension.id}' threw ERROR`);
this._logService.error(`onWillSaveTextDocument-listener from extension '${extension.identifier.value}' threw ERROR`);
this._logService.error(err);
if (!(err instanceof Error) || (<Error>err).message !== 'concurrent_edits') {
@@ -91,7 +91,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
this._badListeners.set(listener, !errors ? 1 : errors + 1);
if (errors > this._thresholds.errors) {
this._logService.info(`onWillSaveTextDocument-listener from extension '${extension.id}' will now be IGNORED because of timeouts and/or errors`);
this._logService.info(`onWillSaveTextDocument-listener from extension '${extension.identifier.value}' will now be IGNORED because of timeouts and/or errors`);
}
}
return false;
@@ -109,7 +109,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
const event = Object.freeze(<vscode.TextDocumentWillSaveEvent>{
document,
reason,
waitUntil(p: Thenable<any | vscode.TextEdit[]>) {
waitUntil(p: Promise<any | vscode.TextEdit[]>) {
if (Object.isFrozen(promises)) {
throw illegalState('waitUntil can not be called async');
}
@@ -132,7 +132,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
const handle = setTimeout(() => reject(new Error('timeout')), this._thresholds.timeout);
return Promise.all(promises).then(edits => {
this._logService.debug(`onWillSaveTextDocument-listener from extension '${extension.id}' finished after ${(Date.now() - t1)}ms`);
this._logService.debug(`onWillSaveTextDocument-listener from extension '${extension.identifier.value}' finished after ${(Date.now() - t1)}ms`);
clearTimeout(handle);
resolve(edits);
}).catch(err => {

View File

@@ -28,7 +28,7 @@ export class ExtHostDocuments implements ExtHostDocumentsShape {
private _toDispose: IDisposable[];
private _proxy: MainThreadDocumentsShape;
private _documentsAndEditors: ExtHostDocumentsAndEditors;
private _documentLoader = new Map<string, Thenable<ExtHostDocumentData>>();
private _documentLoader = new Map<string, Promise<ExtHostDocumentData>>();
constructor(mainContext: IMainContext, documentsAndEditors: ExtHostDocumentsAndEditors) {
this._proxy = mainContext.getProxy(MainContext.MainThreadDocuments);
@@ -67,7 +67,7 @@ export class ExtHostDocuments implements ExtHostDocumentsShape {
return undefined;
}
public ensureDocumentData(uri: URI): Thenable<ExtHostDocumentData> {
public ensureDocumentData(uri: URI): Promise<ExtHostDocumentData> {
let cached = this._documentsAndEditors.getDocument(uri.toString());
if (cached) {
@@ -89,7 +89,7 @@ export class ExtHostDocuments implements ExtHostDocumentsShape {
return promise;
}
public createDocumentData(options?: { language?: string; content?: string }): Thenable<URI> {
public createDocumentData(options?: { language?: string; content?: string }): Promise<URI> {
return this._proxy.$tryCreateDocument(options).then(data => URI.revive(data));
}

View File

@@ -8,13 +8,13 @@ import { IDisposable } from 'vs/base/common/lifecycle';
import Severity from 'vs/base/common/severity';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
const hasOwnProperty = Object.hasOwnProperty;
const NO_OP_VOID_PROMISE = Promise.resolve<void>(void 0);
const NO_OP_VOID_PROMISE = Promise.resolve<void>(undefined);
export interface IExtensionMemento {
get<T>(key: string, defaultValue: T): T;
update(key: string, value: any): Thenable<boolean>;
update(key: string, value: any): Promise<boolean>;
}
export interface IExtensionContext {
@@ -191,31 +191,39 @@ export type ExtensionActivationReason = ExtensionActivatedByEvent | ExtensionAct
export class ExtensionsActivator {
private readonly _registry: ExtensionDescriptionRegistry;
private readonly _resolvedExtensionsSet: Set<string>;
private readonly _host: IExtensionsActivatorHost;
private readonly _activatingExtensions: { [extensionId: string]: Promise<void>; };
private readonly _activatedExtensions: { [extensionId: string]: ActivatedExtension; };
private readonly _activatingExtensions: Map<string, Promise<void>>;
private readonly _activatedExtensions: Map<string, ActivatedExtension>;
/**
* A map of already activated events to speed things up if the same activation event is triggered multiple times.
*/
private readonly _alreadyActivatedEvents: { [activationEvent: string]: boolean; };
constructor(registry: ExtensionDescriptionRegistry, host: IExtensionsActivatorHost) {
constructor(registry: ExtensionDescriptionRegistry, resolvedExtensions: ExtensionIdentifier[], host: IExtensionsActivatorHost) {
this._registry = registry;
this._resolvedExtensionsSet = new Set<string>();
resolvedExtensions.forEach((extensionId) => this._resolvedExtensionsSet.add(ExtensionIdentifier.toKey(extensionId)));
this._host = host;
this._activatingExtensions = {};
this._activatedExtensions = {};
this._activatingExtensions = new Map<string, Promise<void>>();
this._activatedExtensions = new Map<string, ActivatedExtension>();
this._alreadyActivatedEvents = Object.create(null);
}
public isActivated(extensionId: string): boolean {
return hasOwnProperty.call(this._activatedExtensions, extensionId);
public isActivated(extensionId: ExtensionIdentifier): boolean {
const extensionKey = ExtensionIdentifier.toKey(extensionId);
return this._activatedExtensions.has(extensionKey);
}
public getActivatedExtension(extensionId: string): ActivatedExtension {
if (!hasOwnProperty.call(this._activatedExtensions, extensionId)) {
throw new Error('Extension `' + extensionId + '` is not known or not activated');
public getActivatedExtension(extensionId: ExtensionIdentifier): ActivatedExtension {
const extensionKey = ExtensionIdentifier.toKey(extensionId);
const activatedExtension = this._activatedExtensions.get(extensionKey);
if (!activatedExtension) {
throw new Error('Extension `' + extensionId.value + '` is not known or not activated');
}
return this._activatedExtensions[extensionId];
return activatedExtension;
}
public activateByEvent(activationEvent: string, reason: ExtensionActivationReason): Promise<void> {
@@ -228,7 +236,7 @@ export class ExtensionsActivator {
});
}
public activateById(extensionId: string, reason: ExtensionActivationReason): Promise<void> {
public activateById(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void> {
let desc = this._registry.getExtensionDescription(extensionId);
if (!desc) {
throw new Error('Extension `' + extensionId + '` is not known');
@@ -246,36 +254,42 @@ export class ExtensionsActivator {
let currentExtensionGetsGreenLight = true;
for (let j = 0, lenJ = depIds.length; j < lenJ; j++) {
let depId = depIds[j];
let depDesc = this._registry.getExtensionDescription(depId);
const depId = depIds[j];
if (this._resolvedExtensionsSet.has(ExtensionIdentifier.toKey(depId))) {
// This dependency is already resolved
continue;
}
const depDesc = this._registry.getExtensionDescription(depId);
if (!depDesc) {
// Error condition 1: unknown dependency
this._host.showMessage(Severity.Error, nls.localize('unknownDep', "Cannot activate extension '{0}' as the depending extension '{1}' is not found. Please install or enable the depending extension and reload the window.", currentExtension.displayName || currentExtension.id, depId));
this._host.showMessage(Severity.Error, nls.localize('unknownDep', "Cannot activate extension '{0}' because it depends on extension '{1}', which is not installed or disabled. Please install or enable '{1}' and reload the window.", currentExtension.displayName || currentExtension.identifier.value, depId));
const error = new Error(`Unknown dependency '${depId}'`);
this._activatedExtensions[currentExtension.id] = new FailedExtension(error);
this._activatedExtensions.set(ExtensionIdentifier.toKey(currentExtension.identifier), new FailedExtension(error));
return;
}
if (hasOwnProperty.call(this._activatedExtensions, depId)) {
let dep = this._activatedExtensions[depId];
const dep = this._activatedExtensions.get(ExtensionIdentifier.toKey(depId));
if (dep) {
if (dep.activationFailed) {
// Error condition 2: a dependency has already failed activation
this._host.showMessage(Severity.Error, nls.localize('failedDep1', "Cannot activate extension '{0}' as the depending extension '{1}' is failed to activate.", currentExtension.displayName || currentExtension.id, depId));
this._host.showMessage(Severity.Error, nls.localize('failedDep1', "Cannot activate extension '{0}' because it depends on extension '{1}', which failed to activate.", currentExtension.displayName || currentExtension.identifier.value, depId));
const error = new Error(`Dependency ${depId} failed to activate`);
(<any>error).detail = dep.activationFailedError;
this._activatedExtensions[currentExtension.id] = new FailedExtension(error);
this._activatedExtensions.set(ExtensionIdentifier.toKey(currentExtension.identifier), new FailedExtension(error));
return;
}
} else {
// must first wait for the dependency to activate
currentExtensionGetsGreenLight = false;
greenExtensions[depId] = depDesc;
greenExtensions[ExtensionIdentifier.toKey(depId)] = depDesc;
}
}
if (currentExtensionGetsGreenLight) {
greenExtensions[currentExtension.id] = currentExtension;
greenExtensions[ExtensionIdentifier.toKey(currentExtension.identifier)] = currentExtension;
} else {
redExtensions.push(currentExtension);
}
@@ -284,23 +298,23 @@ export class ExtensionsActivator {
private _activateExtensions(extensionDescriptions: IExtensionDescription[], reason: ExtensionActivationReason, recursionLevel: number): Promise<void> {
// console.log(recursionLevel, '_activateExtensions: ', extensionDescriptions.map(p => p.id));
if (extensionDescriptions.length === 0) {
return Promise.resolve(void 0);
return Promise.resolve(undefined);
}
extensionDescriptions = extensionDescriptions.filter((p) => !hasOwnProperty.call(this._activatedExtensions, p.id));
extensionDescriptions = extensionDescriptions.filter((p) => !this._activatedExtensions.has(ExtensionIdentifier.toKey(p.identifier)));
if (extensionDescriptions.length === 0) {
return Promise.resolve(void 0);
return Promise.resolve(undefined);
}
if (recursionLevel > 10) {
// More than 10 dependencies deep => most likely a dependency loop
for (let i = 0, len = extensionDescriptions.length; i < len; i++) {
// Error condition 3: dependency loop
this._host.showMessage(Severity.Error, nls.localize('failedDep2', "Extension '{0}' failed to activate. Reason: more than 10 levels of dependencies (most likely a dependency loop).", extensionDescriptions[i].id));
this._host.showMessage(Severity.Error, nls.localize('failedDep2', "Extension '{0}' failed to activate. Reason: more than 10 levels of dependencies (most likely a dependency loop).", extensionDescriptions[i].identifier.value));
const error = new Error('More than 10 levels of dependencies (most likely a dependency loop)');
this._activatedExtensions[extensionDescriptions[i].id] = new FailedExtension(error);
this._activatedExtensions.set(ExtensionIdentifier.toKey(extensionDescriptions[i].identifier), new FailedExtension(error));
}
return Promise.resolve(void 0);
return Promise.resolve(undefined);
}
let greenMap: { [id: string]: IExtensionDescription; } = Object.create(null),
@@ -312,8 +326,9 @@ export class ExtensionsActivator {
// Make sure no red is also green
for (let i = 0, len = red.length; i < len; i++) {
if (greenMap[red[i].id]) {
delete greenMap[red[i].id];
const redExtensionKey = ExtensionIdentifier.toKey(red[i].identifier);
if (greenMap[redExtensionKey]) {
delete greenMap[redExtensionKey];
}
}
@@ -324,7 +339,7 @@ export class ExtensionsActivator {
if (red.length === 0) {
// Finally reached only leafs!
return Promise.all(green.map((p) => this._activateExtension(p, reason))).then(_ => void 0);
return Promise.all(green.map((p) => this._activateExtension(p, reason))).then(_ => undefined);
}
return this._activateExtensions(green, reason, recursionLevel + 1).then(_ => {
@@ -333,25 +348,29 @@ export class ExtensionsActivator {
}
private _activateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise<void> {
if (hasOwnProperty.call(this._activatedExtensions, extensionDescription.id)) {
return Promise.resolve(void 0);
const extensionKey = ExtensionIdentifier.toKey(extensionDescription.identifier);
if (this._activatedExtensions.has(extensionKey)) {
return Promise.resolve(undefined);
}
if (hasOwnProperty.call(this._activatingExtensions, extensionDescription.id)) {
return this._activatingExtensions[extensionDescription.id];
const currentlyActivatingExtension = this._activatingExtensions.get(extensionKey);
if (currentlyActivatingExtension) {
return currentlyActivatingExtension;
}
this._activatingExtensions[extensionDescription.id] = this._host.actualActivateExtension(extensionDescription, reason).then(null, (err) => {
this._host.showMessage(Severity.Error, nls.localize('activationError', "Activating extension '{0}' failed: {1}.", extensionDescription.id, err.message));
console.error('Activating extension `' + extensionDescription.id + '` failed: ', err.message);
const newlyActivatingExtension = this._host.actualActivateExtension(extensionDescription, reason).then(undefined, (err) => {
this._host.showMessage(Severity.Error, nls.localize('activationError', "Activating extension '{0}' failed: {1}.", extensionDescription.identifier.value, err.message));
console.error('Activating extension `' + extensionDescription.identifier.value + '` failed: ', err.message);
console.log('Here is the error stack: ', err.stack);
// Treat the extension as being empty
return new FailedExtension(err);
}).then((x: ActivatedExtension) => {
this._activatedExtensions[extensionDescription.id] = x;
delete this._activatingExtensions[extensionDescription.id];
this._activatedExtensions.set(extensionKey, x);
this._activatingExtensions.delete(extensionKey);
});
return this._activatingExtensions[extensionDescription.id];
this._activatingExtensions.set(extensionKey, newlyActivatingExtension);
return newlyActivatingExtension;
}
}

View File

@@ -21,12 +21,13 @@ import { ActivatedExtension, EmptyExtension, ExtensionActivatedByAPI, ExtensionA
import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService';
import { ExtHostStorage } from 'vs/workbench/api/node/extHostStorage';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { IExtensionDescription, checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry';
import { connectProxyResolver } from 'vs/workbench/node/proxyResolver';
import { connectProxyResolver } from 'vs/workbench/services/extensions/node/proxyResolver';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import * as errors from 'vs/base/common/errors';
import { ResolvedAuthority } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
class ExtensionMemento implements IExtensionMemento {
@@ -34,7 +35,7 @@ class ExtensionMemento implements IExtensionMemento {
private readonly _shared: boolean;
private readonly _storage: ExtHostStorage;
private readonly _init: Thenable<ExtensionMemento>;
private readonly _init: Promise<ExtensionMemento>;
private _value: { [n: string]: any; };
private readonly _storageListener: IDisposable;
@@ -55,7 +56,7 @@ class ExtensionMemento implements IExtensionMemento {
});
}
get whenReady(): Thenable<ExtensionMemento> {
get whenReady(): Promise<ExtensionMemento> {
return this._init;
}
@@ -67,7 +68,7 @@ class ExtensionMemento implements IExtensionMemento {
return value;
}
update(key: string, value: any): Thenable<boolean> {
update(key: string, value: any): Promise<boolean> {
this._value[key] = value;
return this._storage
.setValue(this._shared, this._id, this._value)
@@ -99,13 +100,13 @@ class ExtensionStoragePath {
workspaceValue(extension: IExtensionDescription): string {
if (this._value) {
return path.join(this._value, extension.id);
return path.join(this._value, extension.identifier.value);
}
return undefined;
}
globalValue(extension: IExtensionDescription): string {
return path.join(this._environment.globalStorageHome.fsPath, extension.id);
return path.join(this._environment.globalStorageHome.fsPath, extension.identifier.value.toLowerCase());
}
private async _getOrCreateWorkspaceStoragePath(): Promise<string> {
@@ -194,7 +195,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
this._registry = new ExtensionDescriptionRegistry(initData.extensions);
this._storage = new ExtHostStorage(this._extHostContext);
this._storagePath = new ExtensionStoragePath(initData.workspace, initData.environment);
this._activator = new ExtensionsActivator(this._registry, {
this._activator = new ExtensionsActivator(this._registry, initData.resolvedExtensions, {
showMessage: (severity: Severity, message: string): void => {
this._mainThreadExtensionsProxy.$localShowMessage(severity, message);
@@ -221,23 +222,30 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
this._started = false;
initializeExtensionApi(this, this._extensionApiFactory, this._registry).then(() => {
// Do this when extension service exists, but extensions are not being activated yet.
return connectProxyResolver(this._extHostWorkspace, this._extHostConfiguration, this, this._extHostLogService, this._mainThreadTelemetryProxy);
}).then(() => {
this._barrier.open();
});
this._initialize();
if (this._initData.autoStart) {
this._startExtensionHost();
}
}
private async _initialize(): Promise<void> {
try {
const configProvider = await this._extHostConfiguration.getConfigProvider();
await initializeExtensionApi(this, this._extensionApiFactory, this._registry, configProvider);
// Do this when extension service exists, but extensions are not being activated yet.
await connectProxyResolver(this._extHostWorkspace, configProvider, this, this._extHostLogService, this._mainThreadTelemetryProxy);
this._barrier.open();
} catch (err) {
errors.onUnexpectedError(err);
}
}
public async deactivateAll(): Promise<void> {
let allPromises: Thenable<void>[] = [];
let allPromises: Promise<void>[] = [];
try {
const allExtensions = this._registry.getAllExtensionDescriptions();
const allExtensionsIds = allExtensions.map(ext => ext.id);
const allExtensionsIds = allExtensions.map(ext => ext.identifier);
const activatedExtensions = allExtensionsIds.filter(id => this.isActivated(id));
allPromises = activatedExtensions.map((extensionId) => {
@@ -249,30 +257,30 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
await allPromises;
}
public isActivated(extensionId: string): boolean {
public isActivated(extensionId: ExtensionIdentifier): boolean {
if (this._barrier.isOpen()) {
return this._activator.isActivated(extensionId);
}
return false;
}
private _activateByEvent(activationEvent: string, startup: boolean): Thenable<void> {
private _activateByEvent(activationEvent: string, startup: boolean): Promise<void> {
const reason = new ExtensionActivatedByEvent(startup, activationEvent);
return this._activator.activateByEvent(activationEvent, reason);
}
private _activateById(extensionId: string, reason: ExtensionActivationReason): Thenable<void> {
private _activateById(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void> {
return this._activator.activateById(extensionId, reason);
}
public activateByIdWithErrors(extensionId: string, reason: ExtensionActivationReason): Thenable<void> {
public activateByIdWithErrors(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void> {
return this._activateById(extensionId, reason).then(() => {
const extension = this._activator.getActivatedExtension(extensionId);
if (extension.activationFailed) {
// activation failed => bubble up the error as the promise result
return Promise.reject(extension.activationFailedError);
}
return void 0;
return undefined;
});
}
@@ -280,7 +288,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
return this._barrier.wait().then(_ => this._registry);
}
public getExtensionExports(extensionId: string): IExtensionAPI {
public getExtensionExports(extensionId: ExtensionIdentifier): IExtensionAPI {
if (this._barrier.isOpen()) {
return this._activator.getActivatedExtension(extensionId).exports;
} else {
@@ -303,8 +311,8 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
return this._extensionPathIndex;
}
private _deactivate(extensionId: string): Thenable<void> {
let result = Promise.resolve(void 0);
private _deactivate(extensionId: ExtensionIdentifier): Promise<void> {
let result = Promise.resolve(undefined);
if (!this._barrier.isOpen()) {
return result;
@@ -322,9 +330,9 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
// call deactivate if available
try {
if (typeof extension.module.deactivate === 'function') {
result = Promise.resolve(extension.module.deactivate()).then(null, (err) => {
result = Promise.resolve(extension.module.deactivate()).then(undefined, (err) => {
// TODO: Do something with err if this is not the shutdown case
return Promise.resolve(void 0);
return Promise.resolve(undefined);
});
}
} catch (err) {
@@ -341,21 +349,22 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
return result;
}
public addMessage(extensionId: string, severity: Severity, message: string): void {
public addMessage(extensionId: ExtensionIdentifier, severity: Severity, message: string): void {
this._mainThreadExtensionsProxy.$addMessage(extensionId, severity, message);
}
// --- impl
private _activateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise<ActivatedExtension> {
this._mainThreadExtensionsProxy.$onWillActivateExtension(extensionDescription.identifier);
return this._doActivateExtension(extensionDescription, reason).then((activatedExtension) => {
const activationTimes = activatedExtension.activationTimes;
let activationEvent = (reason instanceof ExtensionActivatedByEvent ? reason.activationEvent : null);
this._mainThreadExtensionsProxy.$onExtensionActivated(extensionDescription.id, activationTimes.startup, activationTimes.codeLoadingTime, activationTimes.activateCallTime, activationTimes.activateResolvedTime, activationEvent);
this._mainThreadExtensionsProxy.$onDidActivateExtension(extensionDescription.identifier, activationTimes.startup, activationTimes.codeLoadingTime, activationTimes.activateCallTime, activationTimes.activateResolvedTime, activationEvent);
this._logExtensionActivationTimes(extensionDescription, reason, 'success', activationTimes);
return activatedExtension;
}, (err) => {
this._mainThreadExtensionsProxy.$onExtensionActivationFailed(extensionDescription.id);
this._mainThreadExtensionsProxy.$onExtensionActivationFailed(extensionDescription.identifier);
this._logExtensionActivationTimes(extensionDescription, reason, 'failure');
throw err;
});
@@ -394,23 +403,23 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
return Promise.resolve(new EmptyExtension(ExtensionActivationTimes.NONE));
}
this._extHostLogService.info(`ExtensionService#_doActivateExtension ${extensionDescription.id} ${JSON.stringify(reason)}`);
this._extHostLogService.info(`ExtensionService#_doActivateExtension ${extensionDescription.identifier.value} ${JSON.stringify(reason)}`);
const activationTimesBuilder = new ExtensionActivationTimesBuilder(reason.startup);
return Promise.all<any>([
loadCommonJSModule(this._extHostLogService, extensionDescription.main, activationTimesBuilder),
this._loadExtensionContext(extensionDescription)
]).then(values => {
return ExtHostExtensionService._callActivate(this._extHostLogService, extensionDescription.id, <IExtensionModule>values[0], <IExtensionContext>values[1], activationTimesBuilder);
return ExtHostExtensionService._callActivate(this._extHostLogService, extensionDescription.identifier, <IExtensionModule>values[0], <IExtensionContext>values[1], activationTimesBuilder);
});
}
private _loadExtensionContext(extensionDescription: IExtensionDescription): Promise<IExtensionContext> {
let globalState = new ExtensionMemento(extensionDescription.id, true, this._storage);
let workspaceState = new ExtensionMemento(extensionDescription.id, false, this._storage);
let globalState = new ExtensionMemento(extensionDescription.identifier.value, true, this._storage);
let workspaceState = new ExtensionMemento(extensionDescription.identifier.value, false, this._storage);
this._extHostLogService.trace(`ExtensionService#loadExtensionContext ${extensionDescription.id}`);
this._extHostLogService.trace(`ExtensionService#loadExtensionContext ${extensionDescription.identifier.value}`);
return Promise.all([
globalState.whenReady,
workspaceState.whenReady,
@@ -423,14 +432,14 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
subscriptions: [],
get extensionPath() { return extensionDescription.extensionLocation.fsPath; },
storagePath: this._storagePath.workspaceValue(extensionDescription),
get globalStoragePath(): string { checkProposedApiEnabled(extensionDescription); return that._storagePath.globalValue(extensionDescription); },
globalStoragePath: this._storagePath.globalValue(extensionDescription),
asAbsolutePath: (relativePath: string) => { return path.join(extensionDescription.extensionLocation.fsPath, relativePath); },
logPath: that._extHostLogService.getLogDirectory(extensionDescription.id)
logPath: that._extHostLogService.getLogDirectory(extensionDescription.identifier)
});
});
}
private static _callActivate(logService: ILogService, extensionId: string, extensionModule: IExtensionModule, context: IExtensionContext, activationTimesBuilder: ExtensionActivationTimesBuilder): Thenable<ActivatedExtension> {
private static _callActivate(logService: ILogService, extensionId: ExtensionIdentifier, extensionModule: IExtensionModule, context: IExtensionContext, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<ActivatedExtension> {
// Make sure the extension's surface is not undefined
extensionModule = extensionModule || {
activate: undefined,
@@ -442,12 +451,12 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
});
}
private static _callActivateOptional(logService: ILogService, extensionId: string, extensionModule: IExtensionModule, context: IExtensionContext, activationTimesBuilder: ExtensionActivationTimesBuilder): Thenable<IExtensionAPI> {
private static _callActivateOptional(logService: ILogService, extensionId: ExtensionIdentifier, extensionModule: IExtensionModule, context: IExtensionContext, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<IExtensionAPI> {
if (typeof extensionModule.activate === 'function') {
try {
activationTimesBuilder.activateCallStart();
logService.trace(`ExtensionService#_callActivateOptional ${extensionId}`);
const activateResult: Thenable<IExtensionAPI> = extensionModule.activate.apply(global, [context]);
logService.trace(`ExtensionService#_callActivateOptional ${extensionId.value}`);
const activateResult: Promise<IExtensionAPI> = extensionModule.activate.apply(global, [context]);
activationTimesBuilder.activateCallStop();
activationTimesBuilder.activateResolveStart();
@@ -468,7 +477,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
// Handle "eager" activation extensions
private _handleEagerExtensions(): Promise<void> {
this._activateByEvent('*', true).then(null, (err) => {
this._activateByEvent('*', true).then(undefined, (err) => {
console.error(err);
});
@@ -477,7 +486,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
private _handleWorkspaceContainsEagerExtensions(workspace: IWorkspaceData): Promise<void> {
if (!workspace || workspace.folders.length === 0) {
return Promise.resolve(null);
return Promise.resolve(undefined);
}
return Promise.all(
@@ -490,15 +499,15 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
private _handleWorkspaceContainsEagerExtension(workspace: IWorkspaceData, desc: IExtensionDescription): Promise<void> {
const activationEvents = desc.activationEvents;
if (!activationEvents) {
return Promise.resolve(void 0);
return Promise.resolve(undefined);
}
const fileNames: string[] = [];
const globPatterns: string[] = [];
for (let i = 0; i < activationEvents.length; i++) {
if (/^workspaceContains:/.test(activationEvents[i])) {
const fileNameOrGlob = activationEvents[i].substr('workspaceContains:'.length);
for (const activationEvent of activationEvents) {
if (/^workspaceContains:/.test(activationEvent)) {
const fileNameOrGlob = activationEvent.substr('workspaceContains:'.length);
if (fileNameOrGlob.indexOf('*') >= 0 || fileNameOrGlob.indexOf('?') >= 0) {
globPatterns.push(fileNameOrGlob);
} else {
@@ -508,16 +517,16 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
}
if (fileNames.length === 0 && globPatterns.length === 0) {
return Promise.resolve(void 0);
return Promise.resolve(undefined);
}
const fileNamePromise = Promise.all(fileNames.map((fileName) => this._activateIfFileName(workspace, desc.id, fileName))).then(() => { });
const globPatternPromise = this._activateIfGlobPatterns(desc.id, globPatterns);
const fileNamePromise = Promise.all(fileNames.map((fileName) => this._activateIfFileName(workspace, desc.identifier, fileName))).then(() => { });
const globPatternPromise = this._activateIfGlobPatterns(desc.identifier, globPatterns);
return Promise.all([fileNamePromise, globPatternPromise]).then(() => { });
}
private async _activateIfFileName(workspace: IWorkspaceData, extensionId: string, fileName: string): Promise<void> {
private async _activateIfFileName(workspace: IWorkspaceData, extensionId: ExtensionIdentifier, fileName: string): Promise<void> {
// find exact path
for (const { uri } of workspace.folders) {
@@ -525,7 +534,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
// the file was found
return (
this._activateById(extensionId, new ExtensionActivatedByEvent(true, `workspaceContains:${fileName}`))
.then(null, err => console.error(err))
.then(undefined, err => console.error(err))
);
}
}
@@ -533,11 +542,11 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
return undefined;
}
private async _activateIfGlobPatterns(extensionId: string, globPatterns: string[]): Promise<void> {
this._extHostLogService.trace(`extensionHostMain#activateIfGlobPatterns: fileSearch, extension: ${extensionId}, entryPoint: workspaceContains`);
private async _activateIfGlobPatterns(extensionId: ExtensionIdentifier, globPatterns: string[]): Promise<void> {
this._extHostLogService.trace(`extensionHostMain#activateIfGlobPatterns: fileSearch, extension: ${extensionId.value}, entryPoint: workspaceContains`);
if (globPatterns.length === 0) {
return Promise.resolve(void 0);
return Promise.resolve(undefined);
}
const tokenSource = new CancellationTokenSource();
@@ -546,7 +555,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
const timer = setTimeout(async () => {
tokenSource.cancel();
this._activateById(extensionId, new ExtensionActivatedByEvent(true, `workspaceContainsTimeout:${globPatterns.join(',')}`))
.then(null, err => console.error(err));
.then(undefined, err => console.error(err));
}, ExtHostExtensionService.WORKSPACE_CONTAINS_TIMEOUT);
let exists: boolean;
@@ -565,16 +574,28 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
// a file was found matching one of the glob patterns
return (
this._activateById(extensionId, new ExtensionActivatedByEvent(true, `workspaceContains:${globPatterns.join(',')}`))
.then(null, err => console.error(err))
.then(undefined, err => console.error(err))
);
}
return Promise.resolve(void 0);
return Promise.resolve(undefined);
}
private _handleExtensionTests(): Promise<void> {
return this._doHandleExtensionTests().then(undefined, error => {
console.error(error); // ensure any error message makes it onto the console
return Promise.reject(error);
});
}
private _doHandleExtensionTests(): Promise<void> {
if (!this._initData.environment.extensionTestsPath || !this._initData.environment.extensionDevelopmentLocationURI) {
return Promise.resolve(null);
return Promise.resolve(undefined);
}
if (this._initData.autoStart) {
return Promise.resolve(undefined); // https://github.com/Microsoft/vscode/issues/66936
}
// Require the test runner via node require from the provided path
@@ -593,11 +614,11 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
if (error) {
e(error.toString());
} else {
c(null);
c(undefined);
}
// after tests have run, we shutdown the host
this._gracefulExit(failures && failures > 0 ? 1 /* ERROR */ : 0 /* OK */);
this._gracefulExit(error || (typeof failures === 'number' && failures > 0) ? 1 /* ERROR */ : 0 /* OK */);
});
});
}
@@ -616,7 +637,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
setTimeout(() => this._nativeExit(code), 500);
}
private _startExtensionHost(): Thenable<void> {
private _startExtensionHost(): Promise<void> {
if (this._started) {
throw new Error(`Extension host is already started!`);
}
@@ -636,17 +657,61 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
throw new Error(`Not implemented`);
}
public $startExtensionHost(enabledExtensionIds: string[]): Thenable<void> {
public $startExtensionHost(enabledExtensionIds: ExtensionIdentifier[]): Promise<void> {
this._registry.keepOnly(enabledExtensionIds);
return this._startExtensionHost();
}
public $activateByEvent(activationEvent: string): Thenable<void> {
public $activateByEvent(activationEvent: string): Promise<void> {
return (
this._barrier.wait()
.then(_ => this._activateByEvent(activationEvent, false))
);
}
public $activate(extensionId: ExtensionIdentifier, activationEvent: string): Promise<void> {
return (
this._barrier.wait()
.then(_ => this._activateById(extensionId, new ExtensionActivatedByEvent(false, activationEvent)))
);
}
public async $deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise<void> {
toAdd.forEach((extension) => (<any>extension).extensionLocation = URI.revive(extension.extensionLocation));
const trie = await this.getExtensionPathIndex();
await Promise.all(toRemove.map(async (extensionId) => {
const extensionDescription = this._registry.getExtensionDescription(extensionId);
if (!extensionDescription) {
return;
}
const realpath = await pfs.realpath(extensionDescription.extensionLocation.fsPath);
trie.delete(URI.file(realpath).fsPath);
}));
await Promise.all(toAdd.map(async (extensionDescription) => {
const realpath = await pfs.realpath(extensionDescription.extensionLocation.fsPath);
trie.set(URI.file(realpath).fsPath, extensionDescription);
}));
this._registry.deltaExtensions(toAdd, toRemove);
return Promise.resolve(undefined);
}
public async $test_latency(n: number): Promise<number> {
return n;
}
public async $test_up(b: Buffer): Promise<number> {
return b.length;
}
public async $test_down(size: number): Promise<Buffer> {
let b = Buffer.alloc(size, Math.random() % 256);
return b;
}
}
function loadCommonJSModule<T>(logService: ILogService, modulePath: string, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<T> {
@@ -680,7 +745,7 @@ function getTelemetryActivationEvent(extensionDescription: IExtensionDescription
}
*/
let event = {
id: extensionDescription.id,
id: extensionDescription.identifier.value,
name: extensionDescription.name,
extensionVersion: extensionDescription.version,
publisherDisplayName: extensionDescription.publisher,
@@ -690,4 +755,4 @@ function getTelemetryActivationEvent(extensionDescription: IExtensionDescription
};
return event;
}
}

View File

@@ -12,7 +12,7 @@ import { FileChangeType, DocumentLink } from 'vs/workbench/api/node/extHostTypes
import * as typeConverter from 'vs/workbench/api/node/extHostTypeConverters';
import { ExtHostLanguageFeatures } from 'vs/workbench/api/node/extHostLanguageFeatures';
import { Schemas } from 'vs/base/common/network';
import { LabelRules } from 'vs/platform/label/common/label';
import { ResourceLabelFormatter } from 'vs/platform/label/common/label';
import { State, StateMachine, LinkComputer } from 'vs/editor/common/modes/linkComputer';
import { commonPrefixLength } from 'vs/base/common/strings';
import { CharCode } from 'vs/base/common/charCode';
@@ -127,6 +127,7 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
this._usedSchemes.add(Schemas.https);
this._usedSchemes.add(Schemas.mailto);
this._usedSchemes.add(Schemas.data);
this._usedSchemes.add(Schemas.command);
}
dispose(): void {
@@ -205,8 +206,8 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
});
}
setUriFormatter(scheme: string, formatter: LabelRules): void {
this._proxy.$setUriFormatter(scheme, formatter);
setUriFormatter(formatter: ResourceLabelFormatter): void {
this._proxy.$setUriFormatter(formatter);
}
private static _asIStat(stat: vscode.FileStat): files.IStat {
@@ -279,9 +280,9 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
}
}
$open(handle: number, resource: UriComponents): Promise<number> {
$open(handle: number, resource: UriComponents, opts: files.FileOpenOptions): Promise<number> {
this._checkProviderExists(handle);
return Promise.resolve(this._fsProvider.get(handle).open(URI.revive(resource)));
return Promise.resolve(this._fsProvider.get(handle).open(URI.revive(resource), opts));
}
$close(handle: number, fd: number): Promise<void> {
@@ -289,14 +290,17 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
return Promise.resolve(this._fsProvider.get(handle).close(fd));
}
$read(handle: number, fd: number, pos: number, data: Buffer, offset: number, length: number): Promise<number> {
$read(handle: number, fd: number, pos: number, length: number): Promise<Buffer> {
this._checkProviderExists(handle);
return Promise.resolve(this._fsProvider.get(handle).read(fd, pos, data, offset, length));
const data = Buffer.allocUnsafe(length);
return Promise.resolve(this._fsProvider.get(handle).read(fd, pos, data, 0, length)).then(read => {
return data.slice(0, read); // don't send zeros
});
}
$write(handle: number, fd: number, pos: number, data: Buffer, offset: number, length: number): Promise<number> {
$write(handle: number, fd: number, pos: number, data: Buffer): Promise<number> {
this._checkProviderExists(handle);
return Promise.resolve(this._fsProvider.get(handle).write(fd, pos, data, offset, length));
return Promise.resolve(this._fsProvider.get(handle).write(fd, pos, data, 0, data.length));
}
}

View File

@@ -131,15 +131,15 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ
getOnWillRenameFileEvent(extension: IExtensionDescription): Event<vscode.FileWillRenameEvent> {
return (listener, thisArg, disposables) => {
let wrappedListener = <WillRenameListener><any>function () {
listener.apply(thisArg, arguments);
};
const wrappedListener: WillRenameListener = <any>((e: vscode.FileWillRenameEvent) => {
listener.call(thisArg, e);
});
wrappedListener.extension = extension;
return this._onWillRenameFile.event(wrappedListener, undefined, disposables);
};
}
$onWillRename(oldUriDto: UriComponents, newUriDto: UriComponents): Thenable<any> {
$onWillRename(oldUriDto: UriComponents, newUriDto: UriComponents): Promise<any> {
const oldUri = URI.revive(oldUriDto);
const newUri = URI.revive(newUriDto);
@@ -148,7 +148,7 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ
return {
oldUri,
newUri,
waitUntil: (thenable: Thenable<vscode.WorkspaceEdit>): void => {
waitUntil: (thenable: Promise<vscode.WorkspaceEdit>): void => {
if (Object.isFrozen(bucket)) {
throw new TypeError('waitUntil cannot be called async');
}
@@ -169,7 +169,7 @@ export class ExtHostFileSystemEventService implements ExtHostFileSystemEventServ
}
// flatten all WorkspaceEdits collected via waitUntil-call
// and apply them in one go.
let allEdits = new Array<(ResourceFileEditDto | ResourceTextEditDto)[]>();
let allEdits = new Array<Array<ResourceFileEditDto | ResourceTextEditDto>>();
for (let edit of edits) {
if (edit) { // sparse array
let { edits } = typeConverter.WorkspaceEdit.from(edit, this._extHostDocumentsAndEditors);

View File

@@ -14,9 +14,9 @@ import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService';
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands';
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
import { asThenable } from 'vs/base/common/async';
import { asPromise } from 'vs/base/common/async';
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, WorkspaceSymbolDto, SuggestResultDto, WorkspaceSymbolsDto, SuggestionDto, CodeActionDto, ISerializedDocumentFilter, WorkspaceEditDto, ISerializedSignatureHelpProviderMetadata } from './extHost.protocol';
import { regExpLeadsToEndlessLoop } from 'vs/base/common/strings';
import { regExpLeadsToEndlessLoop, regExpFlags } from 'vs/base/common/strings';
import { IPosition } from 'vs/editor/common/core/position';
import { IRange, Range as EditorRange } from 'vs/editor/common/core/range';
import { isFalsyOrEmpty, isNonEmptyArray } from 'vs/base/common/arrays';
@@ -25,10 +25,11 @@ import { ISelection, Selection } from 'vs/editor/common/core/selection';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { ILogService } from 'vs/platform/log/common/log';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
// --- adapter
class OutlineAdapter {
class DocumentSymbolAdapter {
private _documents: ExtHostDocuments;
private _provider: vscode.DocumentSymbolProvider;
@@ -38,24 +39,23 @@ class OutlineAdapter {
this._provider = provider;
}
provideDocumentSymbols(resource: URI, token: CancellationToken): Thenable<modes.DocumentSymbol[]> {
provideDocumentSymbols(resource: URI, token: CancellationToken): Promise<modes.DocumentSymbol[]> {
let doc = this._documents.getDocumentData(resource).document;
return asThenable(() => this._provider.provideDocumentSymbols(doc, token)).then(value => {
return asPromise(() => this._provider.provideDocumentSymbols(doc, token)).then(value => {
if (isFalsyOrEmpty(value)) {
return undefined;
}
if (value[0] instanceof DocumentSymbol) {
} else if (value[0] instanceof DocumentSymbol) {
return (<DocumentSymbol[]>value).map(typeConvert.DocumentSymbol.from);
} else {
return OutlineAdapter._asDocumentSymbolTree(resource, <SymbolInformation[]>value);
return DocumentSymbolAdapter._asDocumentSymbolTree(<SymbolInformation[]>value);
}
});
}
private static _asDocumentSymbolTree(resource: URI, info: SymbolInformation[]): modes.DocumentSymbol[] {
private static _asDocumentSymbolTree(infos: SymbolInformation[]): modes.DocumentSymbol[] {
// first sort by start (and end) and then loop over all elements
// and build a tree based on containment.
info = info.slice(0).sort((a, b) => {
infos = infos.slice(0).sort((a, b) => {
let res = a.location.range.start.compareTo(b.location.range.start);
if (res === 0) {
res = b.location.range.end.compareTo(a.location.range.end);
@@ -64,13 +64,13 @@ class OutlineAdapter {
});
let res: modes.DocumentSymbol[] = [];
let parentStack: modes.DocumentSymbol[] = [];
for (let i = 0; i < info.length; i++) {
for (const info of infos) {
let element = <modes.DocumentSymbol>{
name: info[i].name,
kind: typeConvert.SymbolKind.from(info[i].kind),
containerName: info[i].containerName,
range: typeConvert.Range.from(info[i].location.range),
selectionRange: typeConvert.Range.from(info[i].location.range),
name: info.name || '!!MISSING: name!!',
kind: typeConvert.SymbolKind.from(info.kind),
containerName: info.containerName,
range: typeConvert.Range.from(info.location.range),
selectionRange: typeConvert.Range.from(info.location.range),
children: []
};
@@ -95,7 +95,7 @@ class OutlineAdapter {
class CodeLensAdapter {
private static _badCmd: vscode.Command = { command: 'missing', title: '<<MISSING COMMAND>>' };
private static _badCmd: vscode.Command = { command: 'missing', title: '!!MISSING: command!!' };
constructor(
private readonly _documents: ExtHostDocuments,
@@ -104,10 +104,10 @@ class CodeLensAdapter {
private readonly _provider: vscode.CodeLensProvider
) { }
provideCodeLenses(resource: URI, token: CancellationToken): Thenable<modes.ICodeLensSymbol[]> {
provideCodeLenses(resource: URI, token: CancellationToken): Promise<modes.ICodeLensSymbol[]> {
const doc = this._documents.getDocumentData(resource).document;
return asThenable(() => this._provider.provideCodeLenses(doc, token)).then(lenses => {
return asPromise(() => this._provider.provideCodeLenses(doc, token)).then(lenses => {
if (Array.isArray(lenses)) {
return lenses.map(lens => {
const id = this._heapService.keep(lens);
@@ -121,18 +121,18 @@ class CodeLensAdapter {
});
}
resolveCodeLens(resource: URI, symbol: modes.ICodeLensSymbol, token: CancellationToken): Thenable<modes.ICodeLensSymbol> {
resolveCodeLens(resource: URI, symbol: modes.ICodeLensSymbol, token: CancellationToken): Promise<modes.ICodeLensSymbol> {
const lens = this._heapService.get<vscode.CodeLens>(ObjectIdentifier.of(symbol));
if (!lens) {
return undefined;
}
let resolve: Thenable<vscode.CodeLens>;
let resolve: Promise<vscode.CodeLens>;
if (typeof this._provider.resolveCodeLens !== 'function' || lens.isResolved) {
resolve = Promise.resolve(lens);
} else {
resolve = asThenable(() => this._provider.resolveCodeLens(lens, token));
resolve = asPromise(() => this._provider.resolveCodeLens(lens, token));
}
return resolve.then(newLens => {
@@ -143,7 +143,7 @@ class CodeLensAdapter {
}
}
function convertToDefinitionLinks(value: vscode.Definition): modes.DefinitionLink[] {
function convertToLocationLinks(value: vscode.Definition): modes.LocationLink[] {
if (Array.isArray(value)) {
return (value as (vscode.DefinitionLink | vscode.Location)[]).map(typeConvert.DefinitionLink.from);
} else if (value) {
@@ -159,10 +159,10 @@ class DefinitionAdapter {
private readonly _provider: vscode.DefinitionProvider
) { }
provideDefinition(resource: URI, position: IPosition, token: CancellationToken): Thenable<modes.DefinitionLink[]> {
provideDefinition(resource: URI, position: IPosition, token: CancellationToken): Promise<modes.LocationLink[]> {
let doc = this._documents.getDocumentData(resource).document;
let pos = typeConvert.Position.to(position);
return asThenable(() => this._provider.provideDefinition(doc, pos, token)).then(convertToDefinitionLinks);
return asPromise(() => this._provider.provideDefinition(doc, pos, token)).then(convertToLocationLinks);
}
}
@@ -173,10 +173,10 @@ class DeclarationAdapter {
private readonly _provider: vscode.DeclarationProvider
) { }
provideDeclaration(resource: URI, position: IPosition, token: CancellationToken): Thenable<modes.DefinitionLink[]> {
provideDeclaration(resource: URI, position: IPosition, token: CancellationToken): Promise<modes.LocationLink[]> {
let doc = this._documents.getDocumentData(resource).document;
let pos = typeConvert.Position.to(position);
return asThenable(() => this._provider.provideDeclaration(doc, pos, token)).then(convertToDefinitionLinks);
return asPromise(() => this._provider.provideDeclaration(doc, pos, token)).then(convertToLocationLinks);
}
}
@@ -187,10 +187,10 @@ class ImplementationAdapter {
private readonly _provider: vscode.ImplementationProvider
) { }
provideImplementation(resource: URI, position: IPosition, token: CancellationToken): Thenable<modes.DefinitionLink[]> {
provideImplementation(resource: URI, position: IPosition, token: CancellationToken): Promise<modes.LocationLink[]> {
let doc = this._documents.getDocumentData(resource).document;
let pos = typeConvert.Position.to(position);
return asThenable(() => this._provider.provideImplementation(doc, pos, token)).then(convertToDefinitionLinks);
return asPromise(() => this._provider.provideImplementation(doc, pos, token)).then(convertToLocationLinks);
}
}
@@ -201,10 +201,10 @@ class TypeDefinitionAdapter {
private readonly _provider: vscode.TypeDefinitionProvider
) { }
provideTypeDefinition(resource: URI, position: IPosition, token: CancellationToken): Thenable<modes.DefinitionLink[]> {
provideTypeDefinition(resource: URI, position: IPosition, token: CancellationToken): Promise<modes.LocationLink[]> {
const doc = this._documents.getDocumentData(resource).document;
const pos = typeConvert.Position.to(position);
return asThenable(() => this._provider.provideTypeDefinition(doc, pos, token)).then(convertToDefinitionLinks);
return asPromise(() => this._provider.provideTypeDefinition(doc, pos, token)).then(convertToLocationLinks);
}
}
@@ -215,12 +215,12 @@ class HoverAdapter {
private readonly _provider: vscode.HoverProvider,
) { }
public provideHover(resource: URI, position: IPosition, token: CancellationToken): Thenable<modes.Hover> {
public provideHover(resource: URI, position: IPosition, token: CancellationToken): Promise<modes.Hover> {
let doc = this._documents.getDocumentData(resource).document;
let pos = typeConvert.Position.to(position);
return asThenable(() => this._provider.provideHover(doc, pos, token)).then(value => {
return asPromise(() => this._provider.provideHover(doc, pos, token)).then(value => {
if (!value || isFalsyOrEmpty(value.contents)) {
return undefined;
}
@@ -243,12 +243,12 @@ class DocumentHighlightAdapter {
private readonly _provider: vscode.DocumentHighlightProvider
) { }
provideDocumentHighlights(resource: URI, position: IPosition, token: CancellationToken): Thenable<modes.DocumentHighlight[]> {
provideDocumentHighlights(resource: URI, position: IPosition, token: CancellationToken): Promise<modes.DocumentHighlight[]> {
let doc = this._documents.getDocumentData(resource).document;
let pos = typeConvert.Position.to(position);
return asThenable(() => this._provider.provideDocumentHighlights(doc, pos, token)).then(value => {
return asPromise(() => this._provider.provideDocumentHighlights(doc, pos, token)).then(value => {
if (Array.isArray(value)) {
return value.map(typeConvert.DocumentHighlight.from);
}
@@ -264,11 +264,11 @@ class ReferenceAdapter {
private readonly _provider: vscode.ReferenceProvider
) { }
provideReferences(resource: URI, position: IPosition, context: modes.ReferenceContext, token: CancellationToken): Thenable<modes.Location[]> {
provideReferences(resource: URI, position: IPosition, context: modes.ReferenceContext, token: CancellationToken): Promise<modes.Location[]> {
let doc = this._documents.getDocumentData(resource).document;
let pos = typeConvert.Position.to(position);
return asThenable(() => this._provider.provideReferences(doc, pos, context, token)).then(value => {
return asPromise(() => this._provider.provideReferences(doc, pos, context, token)).then(value => {
if (Array.isArray(value)) {
return value.map(typeConvert.location.from);
}
@@ -282,6 +282,7 @@ export interface CustomCodeAction extends CodeActionDto {
}
class CodeActionAdapter {
private static readonly _maxCodeActionsPerFile: number = 1000;
constructor(
private readonly _documents: ExtHostDocuments,
@@ -289,10 +290,10 @@ class CodeActionAdapter {
private readonly _diagnostics: ExtHostDiagnostics,
private readonly _provider: vscode.CodeActionProvider,
private readonly _logService: ILogService,
private readonly _extensionId: string
private readonly _extensionId: ExtensionIdentifier
) { }
provideCodeActions(resource: URI, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Thenable<CodeActionDto[]> {
provideCodeActions(resource: URI, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise<CodeActionDto[]> {
const doc = this._documents.getDocumentData(resource).document;
const ran = Selection.isISelection(rangeOrSelection)
@@ -302,7 +303,10 @@ class CodeActionAdapter {
for (const diagnostic of this._diagnostics.getDiagnostics(resource)) {
if (ran.intersection(diagnostic.range)) {
allDiagnostics.push(diagnostic);
const newLen = allDiagnostics.push(diagnostic);
if (newLen > CodeActionAdapter._maxCodeActionsPerFile) {
break;
}
}
}
@@ -311,7 +315,7 @@ class CodeActionAdapter {
only: context.only ? new CodeActionKind(context.only) : undefined
};
return asThenable(() => this._provider.provideCodeActions(doc, ran, codeActionContext, token)).then(commandsOrActions => {
return asPromise(() => this._provider.provideCodeActions(doc, ran, codeActionContext, token)).then(commandsOrActions => {
if (isFalsyOrEmpty(commandsOrActions)) {
return undefined;
}
@@ -330,9 +334,9 @@ class CodeActionAdapter {
} else {
if (codeActionContext.only) {
if (!candidate.kind) {
this._logService.warn(`${this._extensionId} - Code actions of kind '${codeActionContext.only.value} 'requested but returned code action does not have a 'kind'. Code action will be dropped. Please set 'CodeAction.kind'.`);
this._logService.warn(`${this._extensionId.value} - Code actions of kind '${codeActionContext.only.value} 'requested but returned code action does not have a 'kind'. Code action will be dropped. Please set 'CodeAction.kind'.`);
} else if (!codeActionContext.only.contains(candidate.kind)) {
this._logService.warn(`${this._extensionId} -Code actions of kind '${codeActionContext.only.value} 'requested but returned code action is of kind '${candidate.kind.value}'. Code action will be dropped. Please check 'CodeActionContext.only' to only return requested code actions.`);
this._logService.warn(`${this._extensionId.value} -Code actions of kind '${codeActionContext.only.value} 'requested but returned code action is of kind '${candidate.kind.value}'. Code action will be dropped. Please check 'CodeActionContext.only' to only return requested code actions.`);
}
}
@@ -342,7 +346,8 @@ class CodeActionAdapter {
command: candidate.command && this._commands.toInternal(candidate.command),
diagnostics: candidate.diagnostics && candidate.diagnostics.map(typeConvert.Diagnostic.from),
edit: candidate.edit && typeConvert.WorkspaceEdit.from(candidate.edit),
kind: candidate.kind && candidate.kind.value
kind: candidate.kind && candidate.kind.value,
isPreferred: candidate.isPreferred,
});
}
}
@@ -363,11 +368,11 @@ class DocumentFormattingAdapter {
private readonly _provider: vscode.DocumentFormattingEditProvider
) { }
provideDocumentFormattingEdits(resource: URI, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> {
provideDocumentFormattingEdits(resource: URI, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]> {
const { document } = this._documents.getDocumentData(resource);
return asThenable(() => this._provider.provideDocumentFormattingEdits(document, <any>options, token)).then(value => {
return asPromise(() => this._provider.provideDocumentFormattingEdits(document, <any>options, token)).then(value => {
if (Array.isArray(value)) {
return value.map(typeConvert.TextEdit.from);
}
@@ -383,12 +388,12 @@ class RangeFormattingAdapter {
private readonly _provider: vscode.DocumentRangeFormattingEditProvider
) { }
provideDocumentRangeFormattingEdits(resource: URI, range: IRange, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> {
provideDocumentRangeFormattingEdits(resource: URI, range: IRange, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]> {
const { document } = this._documents.getDocumentData(resource);
const ran = typeConvert.Range.to(range);
return asThenable(() => this._provider.provideDocumentRangeFormattingEdits(document, ran, <any>options, token)).then(value => {
return asPromise(() => this._provider.provideDocumentRangeFormattingEdits(document, ran, <any>options, token)).then(value => {
if (Array.isArray(value)) {
return value.map(typeConvert.TextEdit.from);
}
@@ -406,12 +411,12 @@ class OnTypeFormattingAdapter {
autoFormatTriggerCharacters: string[] = []; // not here
provideOnTypeFormattingEdits(resource: URI, position: IPosition, ch: string, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> {
provideOnTypeFormattingEdits(resource: URI, position: IPosition, ch: string, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]> {
const { document } = this._documents.getDocumentData(resource);
const pos = typeConvert.Position.to(position);
return asThenable(() => this._provider.provideOnTypeFormattingEdits(document, pos, ch, <any>options, token)).then(value => {
return asPromise(() => this._provider.provideOnTypeFormattingEdits(document, pos, ch, <any>options, token)).then(value => {
if (Array.isArray(value)) {
return value.map(typeConvert.TextEdit.from);
}
@@ -430,9 +435,9 @@ class NavigateTypeAdapter {
this._provider = provider;
}
provideWorkspaceSymbols(search: string, token: CancellationToken): Thenable<WorkspaceSymbolsDto> {
provideWorkspaceSymbols(search: string, token: CancellationToken): Promise<WorkspaceSymbolsDto> {
const result: WorkspaceSymbolsDto = IdObject.mixin({ symbols: [] });
return asThenable(() => this._provider.provideWorkspaceSymbols(search, token)).then(value => {
return asPromise(() => this._provider.provideWorkspaceSymbols(search, token)).then(value => {
if (isNonEmptyArray(value)) {
for (const item of value) {
if (!item) {
@@ -456,7 +461,7 @@ class NavigateTypeAdapter {
});
}
resolveWorkspaceSymbol(symbol: WorkspaceSymbolDto, token: CancellationToken): Thenable<WorkspaceSymbolDto> {
resolveWorkspaceSymbol(symbol: WorkspaceSymbolDto, token: CancellationToken): Promise<WorkspaceSymbolDto> {
if (typeof this._provider.resolveWorkspaceSymbol !== 'function') {
return Promise.resolve(symbol);
@@ -464,7 +469,7 @@ class NavigateTypeAdapter {
const item = this._symbolCache[symbol._id];
if (item) {
return asThenable(() => this._provider.resolveWorkspaceSymbol(item, token)).then(value => {
return asPromise(() => this._provider.resolveWorkspaceSymbol(item, token)).then(value => {
return value && mixin(symbol, typeConvert.WorkspaceSymbol.from(value), true);
});
}
@@ -493,12 +498,12 @@ class RenameAdapter {
private readonly _provider: vscode.RenameProvider
) { }
provideRenameEdits(resource: URI, position: IPosition, newName: string, token: CancellationToken): Thenable<WorkspaceEditDto> {
provideRenameEdits(resource: URI, position: IPosition, newName: string, token: CancellationToken): Promise<WorkspaceEditDto> {
let doc = this._documents.getDocumentData(resource).document;
let pos = typeConvert.Position.to(position);
return asThenable(() => this._provider.provideRenameEdits(doc, pos, newName, token)).then(value => {
return asPromise(() => this._provider.provideRenameEdits(doc, pos, newName, token)).then(value => {
if (!value) {
return undefined;
}
@@ -514,7 +519,7 @@ class RenameAdapter {
});
}
resolveRenameLocation(resource: URI, position: IPosition, token: CancellationToken): Thenable<modes.RenameLocation & modes.Rejection> {
resolveRenameLocation(resource: URI, position: IPosition, token: CancellationToken): Promise<modes.RenameLocation & modes.Rejection> {
if (typeof this._provider.prepareRename !== 'function') {
return Promise.resolve(undefined);
}
@@ -522,7 +527,7 @@ class RenameAdapter {
let doc = this._documents.getDocumentData(resource).document;
let pos = typeConvert.Position.to(position);
return asThenable(() => this._provider.prepareRename(doc, pos, token)).then(rangeOrLocation => {
return asPromise(() => this._provider.prepareRename(doc, pos, token)).then(rangeOrLocation => {
let range: vscode.Range;
let text: string;
@@ -583,12 +588,12 @@ class SuggestAdapter {
this._provider = provider;
}
provideCompletionItems(resource: URI, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Thenable<SuggestResultDto> {
provideCompletionItems(resource: URI, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise<SuggestResultDto> {
const doc = this._documents.getDocumentData(resource).document;
const pos = typeConvert.Position.to(position);
return asThenable<vscode.CompletionItem[] | vscode.CompletionList>(
return asPromise<vscode.CompletionItem[] | vscode.CompletionList>(
() => this._provider.provideCompletionItems(doc, pos, token, typeConvert.CompletionContext.to(context))
).then(value => {
@@ -630,7 +635,7 @@ class SuggestAdapter {
});
}
resolveCompletionItem(resource: URI, position: IPosition, suggestion: modes.CompletionItem, token: CancellationToken): Thenable<modes.CompletionItem> {
resolveCompletionItem(resource: URI, position: IPosition, suggestion: modes.CompletionItem, token: CancellationToken): Promise<modes.CompletionItem> {
if (typeof this._provider.resolveCompletionItem !== 'function') {
return Promise.resolve(suggestion);
@@ -642,7 +647,7 @@ class SuggestAdapter {
return Promise.resolve(suggestion);
}
return asThenable(() => this._provider.resolveCompletionItem(item, token)).then(resolvedItem => {
return asPromise(() => this._provider.resolveCompletionItem(item, token)).then(resolvedItem => {
if (!resolvedItem) {
return suggestion;
@@ -688,11 +693,7 @@ class SuggestAdapter {
insertTextRules: item.keepWhitespace ? modes.CompletionItemInsertTextRule.KeepWhitespace : 0,
additionalTextEdits: item.additionalTextEdits && item.additionalTextEdits.map(typeConvert.TextEdit.from),
command: this._commands.toInternal(item.command),
commitCharacters: item.commitCharacters,
// help with perf
_labelLow: item.label.toLowerCase(),
_filterTextLow: item.filterText && item.filterText.toLowerCase(),
_sortTextLow: item.sortText && item.sortText.toLowerCase()
commitCharacters: item.commitCharacters
};
// 'insertText'-logic
@@ -734,21 +735,39 @@ class SignatureHelpAdapter {
constructor(
private readonly _documents: ExtHostDocuments,
private readonly _provider: vscode.SignatureHelpProvider
private readonly _provider: vscode.SignatureHelpProvider,
private readonly _heap: ExtHostHeapService,
) { }
provideSignatureHelp(resource: URI, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Thenable<modes.SignatureHelp> {
provideSignatureHelp(resource: URI, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise<modes.SignatureHelp> {
const doc = this._documents.getDocumentData(resource).document;
const pos = typeConvert.Position.to(position);
const vscodeContext = this.reviveContext(context);
return asThenable(() => this._provider.provideSignatureHelp(doc, pos, token, context)).then(value => {
return asPromise(() => this._provider.provideSignatureHelp(doc, pos, token, vscodeContext)).then(value => {
if (value) {
return typeConvert.SignatureHelp.from(value);
const id = this._heap.keep(value);
return ObjectIdentifier.mixin(typeConvert.SignatureHelp.from(value), id);
}
return undefined;
});
}
private reviveContext(context: modes.SignatureHelpContext): vscode.SignatureHelpContext {
let activeSignatureHelp: vscode.SignatureHelp | undefined = undefined;
if (context.activeSignatureHelp) {
const revivedSignatureHelp = typeConvert.SignatureHelp.to(context.activeSignatureHelp);
const saved = this._heap.get<vscode.SignatureHelp>(ObjectIdentifier.of(context.activeSignatureHelp));
if (saved) {
activeSignatureHelp = saved;
activeSignatureHelp.activeSignature = revivedSignatureHelp.activeSignature;
activeSignatureHelp.activeParameter = revivedSignatureHelp.activeParameter;
} else {
activeSignatureHelp = revivedSignatureHelp;
}
}
return { ...context, activeSignatureHelp };
}
}
class LinkProviderAdapter {
@@ -759,10 +778,10 @@ class LinkProviderAdapter {
private readonly _provider: vscode.DocumentLinkProvider
) { }
provideLinks(resource: URI, token: CancellationToken): Thenable<modes.ILink[]> {
provideLinks(resource: URI, token: CancellationToken): Promise<modes.ILink[]> {
const doc = this._documents.getDocumentData(resource).document;
return asThenable(() => this._provider.provideDocumentLinks(doc, token)).then(links => {
return asPromise(() => this._provider.provideDocumentLinks(doc, token)).then(links => {
if (!Array.isArray(links)) {
return undefined;
}
@@ -777,7 +796,7 @@ class LinkProviderAdapter {
});
}
resolveLink(link: modes.ILink, token: CancellationToken): Thenable<modes.ILink> {
resolveLink(link: modes.ILink, token: CancellationToken): Promise<modes.ILink> {
if (typeof this._provider.resolveDocumentLink !== 'function') {
return undefined;
}
@@ -788,7 +807,7 @@ class LinkProviderAdapter {
return undefined;
}
return asThenable(() => this._provider.resolveDocumentLink(item, token)).then(value => {
return asPromise(() => this._provider.resolveDocumentLink(item, token)).then(value => {
if (value) {
return typeConvert.DocumentLink.from(value);
}
@@ -804,9 +823,9 @@ class ColorProviderAdapter {
private _provider: vscode.DocumentColorProvider
) { }
provideColors(resource: URI, token: CancellationToken): Thenable<IRawColorInfo[]> {
provideColors(resource: URI, token: CancellationToken): Promise<IRawColorInfo[]> {
const doc = this._documents.getDocumentData(resource).document;
return asThenable(() => this._provider.provideDocumentColors(doc, token)).then(colors => {
return asPromise(() => this._provider.provideDocumentColors(doc, token)).then(colors => {
if (!Array.isArray(colors)) {
return [];
}
@@ -822,11 +841,11 @@ class ColorProviderAdapter {
});
}
provideColorPresentations(resource: URI, raw: IRawColorInfo, token: CancellationToken): Thenable<modes.IColorPresentation[]> {
provideColorPresentations(resource: URI, raw: IRawColorInfo, token: CancellationToken): Promise<modes.IColorPresentation[]> {
const document = this._documents.getDocumentData(resource).document;
const range = typeConvert.Range.to(raw.range);
const color = typeConvert.Color.to(raw.color);
return asThenable(() => this._provider.provideColorPresentations(color, { document, range }, token)).then(value => {
return asPromise(() => this._provider.provideColorPresentations(color, { document, range }, token)).then(value => {
return value.map(typeConvert.ColorPresentation.from);
});
}
@@ -839,11 +858,11 @@ class FoldingProviderAdapter {
private _provider: vscode.FoldingRangeProvider
) { }
provideFoldingRanges(resource: URI, context: modes.FoldingContext, token: CancellationToken): Thenable<modes.FoldingRange[]> {
provideFoldingRanges(resource: URI, context: modes.FoldingContext, token: CancellationToken): Promise<modes.FoldingRange[]> {
const doc = this._documents.getDocumentData(resource).document;
return asThenable(() => this._provider.provideFoldingRanges(doc, context, token)).then(ranges => {
return asPromise(() => this._provider.provideFoldingRanges(doc, context, token)).then(ranges => {
if (!Array.isArray(ranges)) {
return void 0;
return undefined;
}
return ranges.map(typeConvert.FoldingRange.from);
});
@@ -857,28 +876,28 @@ class SelectionRangeAdapter {
private readonly _provider: vscode.SelectionRangeProvider
) { }
provideSelectionRanges(resource: URI, position: IPosition, token: CancellationToken): Promise<IRange[]> {
provideSelectionRanges(resource: URI, position: IPosition, token: CancellationToken): Promise<modes.SelectionRange[]> {
const { document } = this._documents.getDocumentData(resource);
const pos = typeConvert.Position.to(position);
return asThenable(() => this._provider.provideSelectionRanges(document, pos, token)).then(ranges => {
if (isFalsyOrEmpty(ranges)) {
return asPromise(() => this._provider.provideSelectionRanges(document, pos, token)).then(selectionRanges => {
if (isFalsyOrEmpty(selectionRanges)) {
return undefined;
}
let result: IRange[] = [];
let result: modes.SelectionRange[] = [];
let last: vscode.Position | vscode.Range = pos;
for (const range of ranges) {
if (!range.contains(last)) {
for (const sel of selectionRanges) {
if (!sel.range.contains(last)) {
throw new Error('INVALID selection range, must contain the previous range');
}
result.push(typeConvert.Range.from(range));
last = range;
result.push(typeConvert.SelectionRange.from(sel));
last = sel.range;
}
return result;
});
}
}
type Adapter = OutlineAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter
type Adapter = DocumentSymbolAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter
| DocumentHighlightAdapter | ReferenceAdapter | CodeActionAdapter | DocumentFormattingAdapter
| RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter
| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter | TypeDefinitionAdapter
@@ -973,20 +992,20 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return ExtHostLanguageFeatures._handlePool++;
}
private _withAdapter<A, R>(handle: number, ctor: { new(...args: any[]): A }, callback: (adapter: A) => Thenable<R>): Thenable<R> {
private _withAdapter<A, R>(handle: number, ctor: { new(...args: any[]): A }, callback: (adapter: A) => Promise<R>): Promise<R> {
let data = this._adapter.get(handle);
if (data.adapter instanceof ctor) {
let t1: number;
if (data.extension) {
t1 = Date.now();
this._logService.trace(`[${data.extension.id}] INVOKE provider '${(ctor as any).name}'`);
this._logService.trace(`[${data.extension.identifier.value}] INVOKE provider '${(ctor as any).name}'`);
}
let p = callback(data.adapter);
if (data.extension) {
Promise.resolve(p).then(
() => this._logService.trace(`[${data.extension.id}] provider DONE after ${Date.now() - t1}ms`),
() => this._logService.trace(`[${data.extension.identifier.value}] provider DONE after ${Date.now() - t1}ms`),
err => {
this._logService.error(`[${data.extension.id}] provider FAILED`);
this._logService.error(`[${data.extension.identifier.value}] provider FAILED`);
this._logService.error(err);
}
);
@@ -1002,17 +1021,21 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return handle;
}
private static _extLabel(ext: IExtensionDescription): string {
return ext.displayName || ext.name;
}
// --- outline
registerDocumentSymbolProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider, metadata?: vscode.DocumentSymbolProviderMetadata): vscode.Disposable {
const handle = this._addNewAdapter(new OutlineAdapter(this._documents, provider), extension);
const displayName = (metadata && metadata.label) || (extension && (extension.displayName || extension.name)) || undefined;
this._proxy.$registerOutlineSupport(handle, this._transformDocumentSelector(selector), displayName);
const handle = this._addNewAdapter(new DocumentSymbolAdapter(this._documents, provider), extension);
const displayName = (metadata && metadata.label) || ExtHostLanguageFeatures._extLabel(extension);
this._proxy.$registerDocumentSymbolProvider(handle, this._transformDocumentSelector(selector), displayName);
return this._createDisposable(handle);
}
$provideDocumentSymbols(handle: number, resource: UriComponents, token: CancellationToken): Thenable<modes.DocumentSymbol[]> {
return this._withAdapter(handle, OutlineAdapter, adapter => adapter.provideDocumentSymbols(URI.revive(resource), token));
$provideDocumentSymbols(handle: number, resource: UriComponents, token: CancellationToken): Promise<modes.DocumentSymbol[]> {
return this._withAdapter(handle, DocumentSymbolAdapter, adapter => adapter.provideDocumentSymbols(URI.revive(resource), token));
}
// --- code lens
@@ -1033,11 +1056,11 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return result;
}
$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Thenable<modes.ICodeLensSymbol[]> {
$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Promise<modes.ICodeLensSymbol[]> {
return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.provideCodeLenses(URI.revive(resource), token));
}
$resolveCodeLens(handle: number, resource: UriComponents, symbol: modes.ICodeLensSymbol, token: CancellationToken): Thenable<modes.ICodeLensSymbol> {
$resolveCodeLens(handle: number, resource: UriComponents, symbol: modes.ICodeLensSymbol, token: CancellationToken): Promise<modes.ICodeLensSymbol> {
return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.resolveCodeLens(URI.revive(resource), symbol, token));
}
@@ -1049,7 +1072,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideDefinition(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Thenable<modes.DefinitionLink[]> {
$provideDefinition(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.LocationLink[]> {
return this._withAdapter(handle, DefinitionAdapter, adapter => adapter.provideDefinition(URI.revive(resource), position, token));
}
@@ -1059,7 +1082,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideDeclaration(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Thenable<modes.DefinitionLink[]> {
$provideDeclaration(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.LocationLink[]> {
return this._withAdapter(handle, DeclarationAdapter, adapter => adapter.provideDeclaration(URI.revive(resource), position, token));
}
@@ -1069,7 +1092,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideImplementation(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Thenable<modes.DefinitionLink[]> {
$provideImplementation(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.LocationLink[]> {
return this._withAdapter(handle, ImplementationAdapter, adapter => adapter.provideImplementation(URI.revive(resource), position, token));
}
@@ -1079,19 +1102,19 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideTypeDefinition(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Thenable<modes.DefinitionLink[]> {
$provideTypeDefinition(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.LocationLink[]> {
return this._withAdapter(handle, TypeDefinitionAdapter, adapter => adapter.provideTypeDefinition(URI.revive(resource), position, token));
}
// --- extra info
registerHoverProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.HoverProvider, extensionId?: string): vscode.Disposable {
registerHoverProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.HoverProvider, extensionId?: ExtensionIdentifier): vscode.Disposable {
const handle = this._addNewAdapter(new HoverAdapter(this._documents, provider), extension);
this._proxy.$registerHoverProvider(handle, this._transformDocumentSelector(selector));
return this._createDisposable(handle);
}
$provideHover(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Thenable<modes.Hover> {
$provideHover(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.Hover> {
return this._withAdapter(handle, HoverAdapter, adapter => adapter.provideHover(URI.revive(resource), position, token));
}
@@ -1103,7 +1126,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideDocumentHighlights(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Thenable<modes.DocumentHighlight[]> {
$provideDocumentHighlights(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.DocumentHighlight[]> {
return this._withAdapter(handle, DocumentHighlightAdapter, adapter => adapter.provideDocumentHighlights(URI.revive(resource), position, token));
}
@@ -1115,20 +1138,20 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideReferences(handle: number, resource: UriComponents, position: IPosition, context: modes.ReferenceContext, token: CancellationToken): Thenable<modes.Location[]> {
$provideReferences(handle: number, resource: UriComponents, position: IPosition, context: modes.ReferenceContext, token: CancellationToken): Promise<modes.Location[]> {
return this._withAdapter(handle, ReferenceAdapter, adapter => adapter.provideReferences(URI.revive(resource), position, context, token));
}
// --- quick fix
registerCodeActionProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider, metadata?: vscode.CodeActionProviderMetadata): vscode.Disposable {
const handle = this._addNewAdapter(new CodeActionAdapter(this._documents, this._commands.converter, this._diagnostics, provider, this._logService, extension.id), extension);
const handle = this._addNewAdapter(new CodeActionAdapter(this._documents, this._commands.converter, this._diagnostics, provider, this._logService, extension.identifier), extension);
this._proxy.$registerQuickFixSupport(handle, this._transformDocumentSelector(selector), metadata && metadata.providedCodeActionKinds ? metadata.providedCodeActionKinds.map(kind => kind.value) : undefined);
return this._createDisposable(handle);
}
$provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Thenable<CodeActionDto[]> {
$provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise<CodeActionDto[]> {
return this._withAdapter(handle, CodeActionAdapter, adapter => adapter.provideCodeActions(URI.revive(resource), rangeOrSelection, context, token));
}
@@ -1136,21 +1159,21 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerDocumentFormattingEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable {
const handle = this._addNewAdapter(new DocumentFormattingAdapter(this._documents, provider), extension);
this._proxy.$registerDocumentFormattingSupport(handle, this._transformDocumentSelector(selector));
this._proxy.$registerDocumentFormattingSupport(handle, this._transformDocumentSelector(selector), ExtHostLanguageFeatures._extLabel(extension));
return this._createDisposable(handle);
}
$provideDocumentFormattingEdits(handle: number, resource: UriComponents, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> {
$provideDocumentFormattingEdits(handle: number, resource: UriComponents, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]> {
return this._withAdapter(handle, DocumentFormattingAdapter, adapter => adapter.provideDocumentFormattingEdits(URI.revive(resource), options, token));
}
registerDocumentRangeFormattingEditProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable {
const handle = this._addNewAdapter(new RangeFormattingAdapter(this._documents, provider), extension);
this._proxy.$registerRangeFormattingSupport(handle, this._transformDocumentSelector(selector));
this._proxy.$registerRangeFormattingSupport(handle, this._transformDocumentSelector(selector), ExtHostLanguageFeatures._extLabel(extension));
return this._createDisposable(handle);
}
$provideDocumentRangeFormattingEdits(handle: number, resource: UriComponents, range: IRange, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> {
$provideDocumentRangeFormattingEdits(handle: number, resource: UriComponents, range: IRange, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]> {
return this._withAdapter(handle, RangeFormattingAdapter, adapter => adapter.provideDocumentRangeFormattingEdits(URI.revive(resource), range, options, token));
}
@@ -1160,7 +1183,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideOnTypeFormattingEdits(handle: number, resource: UriComponents, position: IPosition, ch: string, options: modes.FormattingOptions, token: CancellationToken): Thenable<ISingleEditOperation[]> {
$provideOnTypeFormattingEdits(handle: number, resource: UriComponents, position: IPosition, ch: string, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]> {
return this._withAdapter(handle, OnTypeFormattingAdapter, adapter => adapter.provideOnTypeFormattingEdits(URI.revive(resource), position, ch, options, token));
}
@@ -1172,11 +1195,11 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideWorkspaceSymbols(handle: number, search: string, token: CancellationToken): Thenable<WorkspaceSymbolsDto> {
$provideWorkspaceSymbols(handle: number, search: string, token: CancellationToken): Promise<WorkspaceSymbolsDto> {
return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.provideWorkspaceSymbols(search, token));
}
$resolveWorkspaceSymbol(handle: number, symbol: WorkspaceSymbolDto, token: CancellationToken): Thenable<WorkspaceSymbolDto> {
$resolveWorkspaceSymbol(handle: number, symbol: WorkspaceSymbolDto, token: CancellationToken): Promise<WorkspaceSymbolDto> {
return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.resolveWorkspaceSymbol(symbol, token));
}
@@ -1192,11 +1215,11 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string, token: CancellationToken): Thenable<WorkspaceEditDto> {
$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string, token: CancellationToken): Promise<WorkspaceEditDto> {
return this._withAdapter(handle, RenameAdapter, adapter => adapter.provideRenameEdits(URI.revive(resource), position, newName, token));
}
$resolveRenameLocation(handle: number, resource: URI, position: IPosition, token: CancellationToken): Thenable<modes.RenameLocation> {
$resolveRenameLocation(handle: number, resource: URI, position: IPosition, token: CancellationToken): Promise<modes.RenameLocation> {
return this._withAdapter(handle, RenameAdapter, adapter => adapter.resolveRenameLocation(URI.revive(resource), position, token));
}
@@ -1208,11 +1231,11 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Thenable<SuggestResultDto> {
$provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise<SuggestResultDto> {
return this._withAdapter(handle, SuggestAdapter, adapter => adapter.provideCompletionItems(URI.revive(resource), position, context, token));
}
$resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, suggestion: modes.CompletionItem, token: CancellationToken): Thenable<modes.CompletionItem> {
$resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, suggestion: modes.CompletionItem, token: CancellationToken): Promise<modes.CompletionItem> {
return this._withAdapter(handle, SuggestAdapter, adapter => adapter.resolveCompletionItem(URI.revive(resource), position, suggestion, token));
}
@@ -1227,12 +1250,12 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
? { triggerCharacters: metadataOrTriggerChars, retriggerCharacters: [] }
: metadataOrTriggerChars;
const handle = this._addNewAdapter(new SignatureHelpAdapter(this._documents, provider), extension);
const handle = this._addNewAdapter(new SignatureHelpAdapter(this._documents, provider, this._heapService), extension);
this._proxy.$registerSignatureHelpProvider(handle, this._transformDocumentSelector(selector), metadata);
return this._createDisposable(handle);
}
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Thenable<modes.SignatureHelp> {
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise<modes.SignatureHelp> {
return this._withAdapter(handle, SignatureHelpAdapter, adapter => adapter.provideSignatureHelp(URI.revive(resource), position, context, token));
}
@@ -1244,11 +1267,11 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideDocumentLinks(handle: number, resource: UriComponents, token: CancellationToken): Thenable<modes.ILink[]> {
$provideDocumentLinks(handle: number, resource: UriComponents, token: CancellationToken): Promise<modes.ILink[]> {
return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.provideLinks(URI.revive(resource), token));
}
$resolveDocumentLink(handle: number, link: modes.ILink, token: CancellationToken): Thenable<modes.ILink> {
$resolveDocumentLink(handle: number, link: modes.ILink, token: CancellationToken): Promise<modes.ILink> {
return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.resolveLink(link, token));
}
@@ -1258,11 +1281,11 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideDocumentColors(handle: number, resource: UriComponents, token: CancellationToken): Thenable<IRawColorInfo[]> {
$provideDocumentColors(handle: number, resource: UriComponents, token: CancellationToken): Promise<IRawColorInfo[]> {
return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColors(URI.revive(resource), token));
}
$provideColorPresentations(handle: number, resource: UriComponents, colorInfo: IRawColorInfo, token: CancellationToken): Thenable<modes.IColorPresentation[]> {
$provideColorPresentations(handle: number, resource: UriComponents, colorInfo: IRawColorInfo, token: CancellationToken): Promise<modes.IColorPresentation[]> {
return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColorPresentations(URI.revive(resource), colorInfo, token));
}
@@ -1272,7 +1295,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideFoldingRanges(handle: number, resource: UriComponents, context: vscode.FoldingContext, token: CancellationToken): Thenable<modes.FoldingRange[]> {
$provideFoldingRanges(handle: number, resource: UriComponents, context: vscode.FoldingContext, token: CancellationToken): Promise<modes.FoldingRange[]> {
return this._withAdapter(handle, FoldingProviderAdapter, adapter => adapter.provideFoldingRanges(URI.revive(resource), context, token));
}
@@ -1284,7 +1307,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideSelectionRanges(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Thenable<IRange[]> {
$provideSelectionRanges(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.SelectionRange[]> {
return this._withAdapter(handle, SelectionRangeAdapter, adapter => adapter.provideSelectionRanges(URI.revive(resource), position, token));
}
@@ -1299,7 +1322,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
}
return {
pattern: regExp.source,
flags: (regExp.global ? 'g' : '') + (regExp.ignoreCase ? 'i' : '') + (regExp.multiline ? 'm' : ''),
flags: regExpFlags(regExp),
};
}

View File

@@ -20,11 +20,11 @@ export class ExtHostLanguages {
this._documents = documents;
}
getLanguages(): Thenable<string[]> {
getLanguages(): Promise<string[]> {
return this._proxy.$getLanguages();
}
changeLanguage(uri: vscode.Uri, languageId: string): Thenable<vscode.TextDocument> {
changeLanguage(uri: vscode.Uri, languageId: string): Promise<vscode.TextDocument> {
return this._proxy.$changeLanguage(uri, languageId).then(() => {
return this._documents.getDocumentData(uri).document;
});

View File

@@ -9,6 +9,7 @@ import { createSpdLogService } from 'vs/platform/log/node/spdlogService';
import { ExtHostLogServiceShape } from 'vs/workbench/api/node/extHost.protocol';
import { ExtensionHostLogFileName } from 'vs/workbench/services/extensions/common/extensions';
import { URI } from 'vs/base/common/uri';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
export class ExtHostLogService extends DelegatedLogService implements ILogService, ExtHostLogServiceShape {
@@ -29,7 +30,7 @@ export class ExtHostLogService extends DelegatedLogService implements ILogServic
this.setLevel(level);
}
getLogDirectory(extensionID: string): string {
return join(this._logsPath, extensionID);
getLogDirectory(extensionID: ExtensionIdentifier): string {
return join(this._logsPath, extensionID.value);
}
}

View File

@@ -20,9 +20,9 @@ export class ExtHostMessageService {
this._proxy = mainContext.getProxy(MainContext.MainThreadMessageService);
}
showMessage(extension: IExtensionDescription, severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | string, rest: string[]): Thenable<string | undefined>;
showMessage(extension: IExtensionDescription, severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | vscode.MessageItem, rest: vscode.MessageItem[]): Thenable<vscode.MessageItem | undefined>;
showMessage(extension: IExtensionDescription, severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | string | vscode.MessageItem, rest: (string | vscode.MessageItem)[]): Thenable<string | vscode.MessageItem | undefined> {
showMessage(extension: IExtensionDescription, severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | string, rest: string[]): Promise<string | undefined>;
showMessage(extension: IExtensionDescription, severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | vscode.MessageItem, rest: vscode.MessageItem[]): Promise<vscode.MessageItem | undefined>;
showMessage(extension: IExtensionDescription, severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | string | vscode.MessageItem, rest: (string | vscode.MessageItem)[]): Promise<string | vscode.MessageItem | undefined> {
let options: MainThreadMessageOptions = { extension };
let items: (string | vscode.MessageItem)[];

View File

@@ -14,7 +14,7 @@ import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
export abstract class AbstractExtHostOutputChannel extends Disposable implements vscode.OutputChannel {
readonly _id: Thenable<string>;
readonly _id: Promise<string>;
private readonly _name: string;
protected readonly _proxy: MainThreadOutputServiceShape;
private _disposed: boolean;

View File

@@ -89,4 +89,4 @@ class ProgressCallback extends Progress<IProgressStep> {
throttledReport(p: IProgressStep): void {
this._proxy.$progressReport(this._handle, p);
}
}
}

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { asThenable } from 'vs/base/common/async';
import { asPromise } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation';
import { Emitter } from 'vs/base/common/event';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
@@ -14,6 +14,7 @@ import { ExtHostQuickOpenShape, IMainContext, MainContext, MainThreadQuickOpenSh
import { URI } from 'vs/base/common/uri';
import { ThemeIcon, QuickInputButtons } from 'vs/workbench/api/node/extHostTypes';
import { isPromiseCanceledError } from 'vs/base/common/errors';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
export type Item = string | QuickPickItem;
@@ -36,10 +37,10 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
this._commands = commands;
}
showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Thenable<QuickPickItem[]>, enableProposedApi: boolean, options: QuickPickOptions & { canPickMany: true; }, token?: CancellationToken): Thenable<QuickPickItem[] | undefined>;
showQuickPick(itemsOrItemsPromise: string[] | Thenable<string[]>, enableProposedApi: boolean, options?: QuickPickOptions, token?: CancellationToken): Thenable<string | undefined>;
showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Thenable<QuickPickItem[]>, enableProposedApi: boolean, options?: QuickPickOptions, token?: CancellationToken): Thenable<QuickPickItem | undefined>;
showQuickPick(itemsOrItemsPromise: Item[] | Thenable<Item[]>, enableProposedApi: boolean, options?: QuickPickOptions, token: CancellationToken = CancellationToken.None): Thenable<Item | Item[] | undefined> {
showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Promise<QuickPickItem[]>, enableProposedApi: boolean, options: QuickPickOptions & { canPickMany: true; }, token?: CancellationToken): Promise<QuickPickItem[] | undefined>;
showQuickPick(itemsOrItemsPromise: string[] | Promise<string[]>, enableProposedApi: boolean, options?: QuickPickOptions, token?: CancellationToken): Promise<string | undefined>;
showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Promise<QuickPickItem[]>, enableProposedApi: boolean, options?: QuickPickOptions, token?: CancellationToken): Promise<QuickPickItem | undefined>;
showQuickPick(itemsOrItemsPromise: Item[] | Promise<Item[]>, enableProposedApi: boolean, options?: QuickPickOptions, token: CancellationToken = CancellationToken.None): Promise<Item | Item[] | undefined> {
// clear state from last invocation
this._onDidSelectItem = undefined;
@@ -114,7 +115,7 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
return undefined;
});
});
}).then(null, err => {
}).then(undefined, err => {
if (isPromiseCanceledError(err)) {
return undefined;
}
@@ -133,13 +134,13 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
// ---- input
showInput(options?: InputBoxOptions, token: CancellationToken = CancellationToken.None): Thenable<string> {
showInput(options?: InputBoxOptions, token: CancellationToken = CancellationToken.None): Promise<string> {
// global validate fn used in callback below
this._validateInput = options && options.validateInput;
return this._proxy.$input(options, typeof this._validateInput === 'function', token)
.then(null, err => {
.then(undefined, err => {
if (isPromiseCanceledError(err)) {
return undefined;
}
@@ -148,16 +149,16 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
});
}
$validateInput(input: string): Thenable<string> {
$validateInput(input: string): Promise<string> {
if (this._validateInput) {
return asThenable(() => this._validateInput(input));
return asPromise(() => this._validateInput(input));
}
return undefined;
}
// ---- workspace folder picker
showWorkspaceFolderPick(options?: WorkspaceFolderPickOptions, token = CancellationToken.None): Thenable<WorkspaceFolder> {
showWorkspaceFolderPick(options?: WorkspaceFolderPickOptions, token = CancellationToken.None): Promise<WorkspaceFolder> {
return this._commands.executeCommand('_workbench.pickWorkspaceFolder', [options]).then((selectedFolder: WorkspaceFolder) => {
if (!selectedFolder) {
return undefined;
@@ -169,13 +170,13 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
// ---- QuickInput
createQuickPick<T extends QuickPickItem>(extensionId: string, enableProposedApi: boolean): QuickPick<T> {
createQuickPick<T extends QuickPickItem>(extensionId: ExtensionIdentifier, enableProposedApi: boolean): QuickPick<T> {
const session = new ExtHostQuickPick(this._proxy, extensionId, enableProposedApi, () => this._sessions.delete(session._id));
this._sessions.set(session._id, session);
return session;
}
createInputBox(extensionId: string): InputBox {
createInputBox(extensionId: ExtensionIdentifier): InputBox {
const session = new ExtHostInputBox(this._proxy, extensionId, () => this._sessions.delete(session._id));
this._sessions.set(session._id, session);
return session;
@@ -256,7 +257,7 @@ class ExtHostQuickInput implements QuickInput {
this._onDidChangeValueEmitter
];
constructor(protected _proxy: MainThreadQuickOpenShape, protected _extensionId: string, private _onDidDispose: () => void) {
constructor(protected _proxy: MainThreadQuickOpenShape, protected _extensionId: ExtensionIdentifier, private _onDidDispose: () => void) {
}
get title() {
@@ -479,7 +480,7 @@ class ExtHostQuickPick<T extends QuickPickItem> extends ExtHostQuickInput implem
private _selectedItems: T[] = [];
private _onDidChangeSelectionEmitter = new Emitter<T[]>();
constructor(proxy: MainThreadQuickOpenShape, extensionId: string, enableProposedApi: boolean, onDispose: () => void) {
constructor(proxy: MainThreadQuickOpenShape, extensionId: ExtensionIdentifier, enableProposedApi: boolean, onDispose: () => void) {
super(proxy, extensionId, onDispose);
this._disposables.push(
this._onDidChangeActiveEmitter,
@@ -580,7 +581,7 @@ class ExtHostInputBox extends ExtHostQuickInput implements InputBox {
private _prompt: string;
private _validationMessage: string;
constructor(proxy: MainThreadQuickOpenShape, extensionId: string, onDispose: () => void) {
constructor(proxy: MainThreadQuickOpenShape, extensionId: ExtensionIdentifier, onDispose: () => void) {
super(proxy, extensionId, onDispose);
this.update({ type: 'inputBox' });
}

View File

@@ -4,10 +4,10 @@
*--------------------------------------------------------------------------------------------*/
import { URI, UriComponents } from 'vs/base/common/uri';
import { Event, Emitter, once } from 'vs/base/common/event';
import { Event, Emitter } from 'vs/base/common/event';
import { debounce } from 'vs/base/common/decorators';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { asThenable } from 'vs/base/common/async';
import { asPromise } from 'vs/base/common/async';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
import { MainContext, MainThreadSCMShape, SCMRawResource, SCMRawResourceSplice, SCMRawResourceSplices, IMainContext, ExtHostSCMShape } from './extHost.protocol';
@@ -17,6 +17,7 @@ import * as vscode from 'vscode';
import { ISplice } from 'vs/base/common/sequence';
import { ILogService } from 'vs/platform/log/common/log';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
type ProviderHandle = number;
type GroupHandle = number;
@@ -178,7 +179,7 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox {
get validateInput(): IValidateInput {
if (!this._extension.enableProposedApi) {
throw new Error(`[${this._extension.id}]: Proposed API is only available when running out of dev or with the following command line switch: --enable-proposed-api ${this._extension.id}`);
throw new Error(`[${this._extension.identifier.value}]: Proposed API is only available when running out of dev or with the following command line switch: --enable-proposed-api ${this._extension.identifier.value}`);
}
return this._validateInput;
@@ -186,7 +187,7 @@ export class ExtHostSCMInputBox implements vscode.SourceControlInputBox {
set validateInput(fn: IValidateInput) {
if (!this._extension.enableProposedApi) {
throw new Error(`[${this._extension.id}]: Proposed API is only available when running out of dev or with the following command line switch: --enable-proposed-api ${this._extension.id}`);
throw new Error(`[${this._extension.identifier.value}]: Proposed API is only available when running out of dev or with the following command line switch: --enable-proposed-api ${this._extension.identifier.value}`);
}
if (fn && typeof fn !== 'function') {
@@ -279,14 +280,14 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG
return this._resourceStatesMap.get(handle);
}
$executeResourceCommand(handle: number): Thenable<void> {
$executeResourceCommand(handle: number): Promise<void> {
const command = this._resourceStatesCommandsMap.get(handle);
if (!command) {
return Promise.resolve(null);
return Promise.resolve(undefined);
}
return asThenable(() => this._commands.executeCommand(command.command, ...command.arguments));
return asPromise(() => this._commands.executeCommand(command.command, ...command.arguments));
}
_takeResourceStateSnapshot(): SCMRawResourceSplice[] {
@@ -478,7 +479,7 @@ class ExtHostSourceControl implements vscode.SourceControl {
this.eventuallyUpdateResourceStates();
});
once(group.onDidDispose)(() => {
Event.once(group.onDidDispose)(() => {
this.updatedResourceGroups.delete(group);
updateListener.dispose();
this._groups.delete(group.handle);
@@ -540,7 +541,7 @@ export class ExtHostSCM implements ExtHostSCMShape {
constructor(
mainContext: IMainContext,
private _commands: ExtHostCommands,
@ILogService private logService: ILogService
@ILogService private readonly logService: ILogService
) {
this._proxy = mainContext.getProxy(MainContext.MainThreadSCM);
@@ -584,31 +585,31 @@ export class ExtHostSCM implements ExtHostSCMShape {
}
createSourceControl(extension: IExtensionDescription, id: string, label: string, rootUri: vscode.Uri | undefined): vscode.SourceControl {
this.logService.trace('ExtHostSCM#createSourceControl', extension.id, id, label, rootUri);
this.logService.trace('ExtHostSCM#createSourceControl', extension.identifier.value, id, label, rootUri);
const handle = ExtHostSCM._handlePool++;
const sourceControl = new ExtHostSourceControl(extension, this._proxy, this._commands, id, label, rootUri);
this._sourceControls.set(handle, sourceControl);
const sourceControls = this._sourceControlsByExtension.get(extension.id) || [];
const sourceControls = this._sourceControlsByExtension.get(ExtensionIdentifier.toKey(extension.identifier)) || [];
sourceControls.push(sourceControl);
this._sourceControlsByExtension.set(extension.id, sourceControls);
this._sourceControlsByExtension.set(ExtensionIdentifier.toKey(extension.identifier), sourceControls);
return sourceControl;
}
// Deprecated
getLastInputBox(extension: IExtensionDescription): ExtHostSCMInputBox {
this.logService.trace('ExtHostSCM#getLastInputBox', extension.id);
this.logService.trace('ExtHostSCM#getLastInputBox', extension.identifier.value);
const sourceControls = this._sourceControlsByExtension.get(extension.id);
const sourceControls = this._sourceControlsByExtension.get(ExtensionIdentifier.toKey(extension.identifier));
const sourceControl = sourceControls && sourceControls[sourceControls.length - 1];
const inputBox = sourceControl && sourceControl.inputBox;
return inputBox;
}
$provideOriginalResource(sourceControlHandle: number, uriComponents: UriComponents, token: CancellationToken): Thenable<UriComponents> {
$provideOriginalResource(sourceControlHandle: number, uriComponents: UriComponents, token: CancellationToken): Promise<UriComponents | null> {
const uri = URI.revive(uriComponents);
this.logService.trace('ExtHostSCM#$provideOriginalResource', sourceControlHandle, uri.toString());
@@ -618,7 +619,7 @@ export class ExtHostSCM implements ExtHostSCMShape {
return Promise.resolve(null);
}
return asThenable(() => sourceControl.quickDiffProvider.provideOriginalResource(uri, token));
return asPromise(() => sourceControl.quickDiffProvider.provideOriginalResource(uri, token));
}
$onInputBoxValueChange(sourceControlHandle: number, value: string): Promise<void> {
@@ -627,32 +628,32 @@ export class ExtHostSCM implements ExtHostSCMShape {
const sourceControl = this._sourceControls.get(sourceControlHandle);
if (!sourceControl) {
return Promise.resolve(null);
return Promise.resolve(undefined);
}
sourceControl.inputBox.$onInputBoxValueChange(value);
return Promise.resolve(null);
return Promise.resolve(undefined);
}
$executeResourceCommand(sourceControlHandle: number, groupHandle: number, handle: number): Thenable<void> {
$executeResourceCommand(sourceControlHandle: number, groupHandle: number, handle: number): Promise<void> {
this.logService.trace('ExtHostSCM#$executeResourceCommand', sourceControlHandle, groupHandle, handle);
const sourceControl = this._sourceControls.get(sourceControlHandle);
if (!sourceControl) {
return Promise.resolve(null);
return Promise.resolve(undefined);
}
const group = sourceControl.getResourceGroup(groupHandle);
if (!group) {
return Promise.resolve(null);
return Promise.resolve(undefined);
}
return group.$executeResourceCommand(handle);
}
$validateInput(sourceControlHandle: number, value: string, cursorPosition: number): Thenable<[string, number] | undefined> {
$validateInput(sourceControlHandle: number, value: string, cursorPosition: number): Promise<[string, number] | undefined> {
this.logService.trace('ExtHostSCM#$validateInput', sourceControlHandle);
const sourceControl = this._sourceControls.get(sourceControlHandle);
@@ -665,7 +666,7 @@ export class ExtHostSCM implements ExtHostSCMShape {
return Promise.resolve(undefined);
}
return asThenable(() => sourceControl.inputBox.validateInput(value, cursorPosition)).then(result => {
return asPromise(() => sourceControl.inputBox.validateInput(value, cursorPosition)).then(result => {
if (!result) {
return Promise.resolve(undefined);
}
@@ -674,7 +675,7 @@ export class ExtHostSCM implements ExtHostSCMShape {
});
}
$setSelectedSourceControls(selectedSourceControlHandles: number[]): Thenable<void> {
$setSelectedSourceControls(selectedSourceControlHandles: number[]): Promise<void> {
this.logService.trace('ExtHostSCM#$setSelectedSourceControls', selectedSourceControlHandles);
const set = new Set<number>();
@@ -708,6 +709,6 @@ export class ExtHostSCM implements ExtHostSCMShape {
});
this._selectedSourceControlHandles = set;
return Promise.resolve(null);
return Promise.resolve(undefined);
}
}

View File

@@ -26,10 +26,10 @@ interface IInternalSearchComplete<T = IFileSearchStats> {
}
export class FileIndexSearchEngine {
private filePattern: string;
private filePattern?: string;
private normalizedFilePatternLowercase: string;
private includePattern: glob.ParsedExpression;
private maxResults: number;
private includePattern?: glob.ParsedExpression;
private maxResults: number | null;
private exists: boolean;
private isLimitHit: boolean;
private resultCount: number;
@@ -40,13 +40,13 @@ export class FileIndexSearchEngine {
private activeCancellationTokens: Set<CancellationTokenSource>;
private globalExcludePattern: glob.ParsedExpression;
private globalExcludePattern?: glob.ParsedExpression;
constructor(private config: IFileQuery, private provider: vscode.FileIndexProvider) {
this.filePattern = config.filePattern;
this.includePattern = config.includePattern && glob.parse(config.includePattern);
this.maxResults = config.maxResults || null;
this.exists = config.exists;
this.exists = !!config.exists;
this.resultCount = 0;
this.isLimitHit = false;
this.activeCancellationTokens = new Set<CancellationTokenSource>();
@@ -109,7 +109,7 @@ export class FileIndexSearchEngine {
errs = [errs];
}
errs = errs.filter(e => !!e);
errs = arrays.coalesce(errs);
return Promise.reject(errs[0]);
});
});
@@ -159,7 +159,7 @@ export class FileIndexSearchEngine {
return null;
}
results.forEach(onProviderResult);
results!.forEach(onProviderResult);
this.matchDirectoryTree(tree, queryTester, onResult);
fileWalkTime = postProcessSW.elapsed();
@@ -268,7 +268,7 @@ export class FileIndexSearchEngine {
}
private matchFile(onResult: (result: IInternalFileMatch) => void, candidate: IInternalFileMatch): void {
if (this.isFilePatternMatch(candidate.relativePath) && (!this.includePattern || this.includePattern(candidate.relativePath, candidate.basename))) {
if (this.isFilePatternMatch(candidate.relativePath!) && (!this.includePattern || this.includePattern(candidate.relativePath!, candidate.basename))) {
if (this.exists || (this.maxResults && this.resultCount >= this.maxResults)) {
this.isLimitHit = true;
this.cancel();
@@ -314,7 +314,7 @@ export class FileIndexSearchManager {
} :
config;
const engine = new FileIndexSearchEngine(engineConfig, provider);
const engine = new FileIndexSearchEngine(<any>engineConfig, provider);
sortedSearch = this.doSortedSearch(engine, config, token);
}
@@ -343,18 +343,18 @@ export class FileIndexSearchManager {
private getFolderCacheKey(config: IFileQuery): string {
const uri = config.folderQueries[0].folder.toString();
const folderCacheKey = config.cacheKey && `${uri}_${config.cacheKey}`;
if (!this.folderCacheKeys.get(config.cacheKey)) {
this.folderCacheKeys.set(config.cacheKey, new Set());
if (!this.folderCacheKeys.get(config.cacheKey!)) {
this.folderCacheKeys.set(config.cacheKey!, new Set());
}
this.folderCacheKeys.get(config.cacheKey).add(folderCacheKey);
this.folderCacheKeys.get(config.cacheKey!)!.add(folderCacheKey!);
return folderCacheKey;
return folderCacheKey!;
}
private rawMatchToSearchItem(match: IInternalFileMatch): IFileMatch {
return {
resource: match.original || resources.joinPath(match.base, match.relativePath)
resource: match.original || resources.joinPath(match.base, match.relativePath!)
};
}
@@ -371,11 +371,11 @@ export class FileIndexSearchManager {
promise: allResultsPromise,
resolved: false
};
cache.resultsToSearchCache[config.filePattern] = cacheRow;
cache.resultsToSearchCache[config.filePattern!] = cacheRow;
allResultsPromise.then(() => {
cacheRow.resolved = true;
}, err => {
delete cache.resultsToSearchCache[config.filePattern];
delete cache.resultsToSearchCache[config.filePattern!];
});
allResultsPromise = this.preventCancellation(allResultsPromise);
}
@@ -412,14 +412,14 @@ export class FileIndexSearchManager {
return this.caches[cacheKey] = new Cache();
}
private trySortedSearchFromCache(config: IFileQuery, token: CancellationToken): Promise<IInternalSearchComplete> {
private trySortedSearchFromCache(config: IFileQuery, token: CancellationToken): Promise<IInternalSearchComplete> | undefined {
const folderCacheKey = this.getFolderCacheKey(config);
const cache = folderCacheKey && this.caches[folderCacheKey];
if (!cache) {
return undefined;
}
const cached = this.getResultsFromCache(cache, config.filePattern, token);
const cached = this.getResultsFromCache(cache, config.filePattern!, token);
if (cached) {
return cached.then(complete => {
const sortSW = StopWatch.create();
@@ -451,10 +451,10 @@ export class FileIndexSearchManager {
// this is very important because we are also limiting the number of results by config.maxResults
// and as such we want the top items to be included in this result set if the number of items
// exceeds config.maxResults.
const query = prepareQuery(config.filePattern);
const query = prepareQuery(config.filePattern!);
const compare = (matchA: IInternalFileMatch, matchB: IInternalFileMatch) => compareItemsByScore(matchA, matchB, query, true, FileMatchItemAccessor, scorerCache);
return arrays.topAsync(results, compare, config.maxResults, 10000, token);
return arrays.topAsync(results, compare, config.maxResults!, 10000, token);
}
private sendAsBatches(rawMatches: IInternalFileMatch[], onBatch: (batch: IFileMatch[]) => void, batchSize: number) {
@@ -468,7 +468,7 @@ export class FileIndexSearchManager {
}
}
private getResultsFromCache(cache: Cache, searchValue: string, token: CancellationToken): Promise<IInternalSearchComplete<ICachedSearchStats>> {
private getResultsFromCache(cache: Cache, searchValue: string, token: CancellationToken): Promise<IInternalSearchComplete<ICachedSearchStats>> | null {
const cacheLookupSW = StopWatch.create();
if (path.isAbsolute(searchValue)) {
@@ -477,7 +477,7 @@ export class FileIndexSearchManager {
// Find cache entries by prefix of search value
const hasPathSep = searchValue.indexOf(path.sep) >= 0;
let cacheRow: ICacheRow;
let cacheRow: ICacheRow | undefined;
for (let previousSearch in cache.resultsToSearchCache) {
// If we narrow down, we might be able to reuse the cached results
@@ -505,7 +505,7 @@ export class FileIndexSearchManager {
return new Promise<IInternalSearchComplete<ICachedSearchStats>>((c, e) => {
token.onCancellationRequested(() => e(canceled()));
cacheRow.promise.then(complete => {
cacheRow!.promise.then(complete => {
if (token && token.isCancellationRequested) {
e(canceled());
}
@@ -517,7 +517,7 @@ export class FileIndexSearchManager {
let entry = complete.results[i];
// Check if this entry is a match for the search value
if (!strings.fuzzyContains(entry.relativePath, normalizedSearchValueLowercase)) {
if (!strings.fuzzyContains(entry.relativePath!, normalizedSearchValueLowercase)) {
continue;
}
@@ -528,7 +528,7 @@ export class FileIndexSearchManager {
limitHit: complete.limitHit,
results,
stats: {
cacheWasResolved: cacheRow.resolved,
cacheWasResolved: cacheRow!.resolved,
cacheLookupTime,
cacheFilterTime: cacheFilterSW.elapsed(),
cacheEntryCount: complete.results.length
@@ -553,11 +553,11 @@ export class FileIndexSearchManager {
}
public clearCache(cacheKey: string): void {
if (!this.folderCacheKeys.has(cacheKey)) {
const expandedKeys = this.folderCacheKeys.get(cacheKey);
if (!expandedKeys) {
return undefined;
}
const expandedKeys = this.folderCacheKeys.get(cacheKey);
expandedKeys.forEach(key => delete this.caches[key]);
this.folderCacheKeys.delete(cacheKey);
@@ -576,6 +576,9 @@ export class FileIndexSearchManager {
catch(reject?) {
return this.then(undefined, reject);
}
finally(onFinally) {
return promise.finally(onFinally);
}
};
}
}
@@ -599,10 +602,10 @@ const FileMatchItemAccessor = new class implements IItemAccessor<IInternalFileMa
}
public getItemDescription(match: IInternalFileMatch): string {
return match.relativePath.substr(0, match.relativePath.length - match.basename.length - 1); // e.g. some/path/to/file
return match.relativePath!.substr(0, match.relativePath!.length - match.basename.length - 1); // e.g. some/path/to/file
}
public getItemPath(match: IInternalFileMatch): string {
return match.relativePath; // e.g. some/path/to/file/myFile.txt
return match.relativePath!; // e.g. some/path/to/file/myFile.txt
}
};

View File

@@ -9,7 +9,6 @@ import { URI, UriComponents } from 'vs/base/common/uri';
import * as extfs from 'vs/base/node/extfs';
import { ILogService } from 'vs/platform/log/common/log';
import { IFileQuery, IFolderQuery, IRawFileQuery, IRawQuery, IRawTextQuery, ISearchCompleteStats, ITextQuery } from 'vs/platform/search/common/search';
import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration';
import { FileIndexSearchManager } from 'vs/workbench/api/node/extHostSearch.fileIndex';
import { FileSearchManager } from 'vs/workbench/services/search/node/fileSearchManager';
import { SearchService } from 'vs/workbench/services/search/node/rawSearchService';
@@ -41,12 +40,10 @@ export class ExtHostSearch implements ExtHostSearchShape {
private _fileSearchManager: FileSearchManager;
private _fileIndexSearchManager: FileIndexSearchManager;
constructor(mainContext: IMainContext, private _schemeTransformer: ISchemeTransformer, private _logService: ILogService, configService: ExtHostConfiguration, private _extfs = extfs) {
constructor(mainContext: IMainContext, private _schemeTransformer: ISchemeTransformer, private _logService: ILogService, private _extfs = extfs) {
this._proxy = mainContext.getProxy(MainContext.MainThreadSearch);
this._fileSearchManager = new FileSearchManager();
this._fileIndexSearchManager = new FileIndexSearchManager();
registerEHProviders(this, _logService, configService);
}
private _transformScheme(scheme: string): string {
@@ -58,7 +55,7 @@ export class ExtHostSearch implements ExtHostSearchShape {
registerTextSearchProvider(scheme: string, provider: vscode.TextSearchProvider): IDisposable {
if (this._textSearchUsedSchemes.has(scheme)) {
throw new Error(`a provider for the scheme '${scheme}' is already registered`);
throw new Error(`a text search provider for the scheme '${scheme}' is already registered`);
}
this._textSearchUsedSchemes.add(scheme);
@@ -74,7 +71,7 @@ export class ExtHostSearch implements ExtHostSearchShape {
registerFileSearchProvider(scheme: string, provider: vscode.FileSearchProvider): IDisposable {
if (this._fileSearchUsedSchemes.has(scheme)) {
throw new Error(`a provider for the scheme '${scheme}' is already registered`);
throw new Error(`a file search provider for the scheme '${scheme}' is already registered`);
}
this._fileSearchUsedSchemes.add(scheme);
@@ -115,7 +112,7 @@ export class ExtHostSearch implements ExtHostSearchShape {
});
}
$provideFileSearchResults(handle: number, session: number, rawQuery: IRawFileQuery, token: CancellationToken): Thenable<ISearchCompleteStats> {
$provideFileSearchResults(handle: number, session: number, rawQuery: IRawFileQuery, token: CancellationToken): Promise<ISearchCompleteStats> {
const query = reviveQuery(rawQuery);
if (handle === this._internalFileSearchHandle) {
return this.doInternalFileSearch(handle, session, query, token);
@@ -134,7 +131,7 @@ export class ExtHostSearch implements ExtHostSearchShape {
}
}
private doInternalFileSearch(handle: number, session: number, rawQuery: IFileQuery, token: CancellationToken): Thenable<ISearchCompleteStats> {
private doInternalFileSearch(handle: number, session: number, rawQuery: IFileQuery, token: CancellationToken): Promise<ISearchCompleteStats> {
const onResult = (ev) => {
if (isSerializedFileMatch(ev)) {
ev = [ev];
@@ -153,7 +150,7 @@ export class ExtHostSearch implements ExtHostSearchShape {
return this._internalFileSearchProvider.doFileSearch(rawQuery, onResult, token);
}
$clearCache(cacheKey: string): Thenable<void> {
$clearCache(cacheKey: string): Promise<void> {
if (this._internalFileSearchProvider) {
this._internalFileSearchProvider.clearCache(cacheKey);
}
@@ -164,7 +161,7 @@ export class ExtHostSearch implements ExtHostSearchShape {
return Promise.resolve(undefined);
}
$provideTextSearchResults(handle: number, session: number, rawQuery: IRawTextQuery, token: CancellationToken): Thenable<ISearchCompleteStats> {
$provideTextSearchResults(handle: number, session: number, rawQuery: IRawTextQuery, token: CancellationToken): Promise<ISearchCompleteStats> {
const provider = this._textSearchProvider.get(handle);
if (!provider.provideTextSearchResults) {
return Promise.resolve(undefined);
@@ -176,13 +173,10 @@ export class ExtHostSearch implements ExtHostSearchShape {
}
}
function registerEHProviders(extHostSearch: ExtHostSearch, logService: ILogService, configService: ExtHostConfiguration) {
if (configService.getConfiguration('searchRipgrep').enable || configService.getConfiguration('search').runInExtensionHost) {
const outputChannel = new OutputChannel(logService);
extHostSearch.registerTextSearchProvider('file', new RipgrepSearchProvider(outputChannel));
extHostSearch.registerInternalFileSearchProvider('file', new SearchService());
}
export function registerEHSearchProviders(extHostSearch: ExtHostSearch, logService: ILogService): void {
const outputChannel = new OutputChannel(logService);
extHostSearch.registerTextSearchProvider('file', new RipgrepSearchProvider(outputChannel));
extHostSearch.registerInternalFileSearchProvider('file', new SearchService());
}
function reviveQuery<U extends IRawQuery>(rawQuery: U): U extends IRawTextQuery ? ITextQuery : IFileQuery {

View File

@@ -7,6 +7,7 @@ import { StatusbarAlignment as MainThreadStatusBarAlignment } from 'vs/platform/
import { StatusBarAlignment as ExtHostStatusBarAlignment, Disposable, ThemeColor } from './extHostTypes';
import { StatusBarItem, StatusBarAlignment } from 'vscode';
import { MainContext, MainThreadStatusBarShape, IMainContext } from './extHost.protocol';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
export class ExtHostStatusBarEntry implements StatusBarItem {
private static ID_GEN = 0;
@@ -25,9 +26,9 @@ export class ExtHostStatusBarEntry implements StatusBarItem {
private _timeoutHandle: any;
private _proxy: MainThreadStatusBarShape;
private _extensionId: string;
private _extensionId: ExtensionIdentifier;
constructor(proxy: MainThreadStatusBarShape, extensionId: string, alignment: ExtHostStatusBarAlignment = ExtHostStatusBarAlignment.Left, priority?: number) {
constructor(proxy: MainThreadStatusBarShape, extensionId: ExtensionIdentifier, alignment: ExtHostStatusBarAlignment = ExtHostStatusBarAlignment.Left, priority?: number) {
this._id = ExtHostStatusBarEntry.ID_GEN++;
this._proxy = proxy;
this._alignment = alignment;
@@ -124,7 +125,7 @@ class StatusBarMessage {
private _messages: { message: string }[] = [];
constructor(statusBar: ExtHostStatusBar) {
this._item = statusBar.createStatusBarEntry(void 0, ExtHostStatusBarAlignment.Left, Number.MIN_VALUE);
this._item = statusBar.createStatusBarEntry(undefined, ExtHostStatusBarAlignment.Left, Number.MIN_VALUE);
}
dispose() {
@@ -166,7 +167,7 @@ export class ExtHostStatusBar {
this._statusMessage = new StatusBarMessage(this);
}
createStatusBarEntry(extensionId: string, alignment?: ExtHostStatusBarAlignment, priority?: number): StatusBarItem {
createStatusBarEntry(extensionId: ExtensionIdentifier, alignment?: ExtHostStatusBarAlignment, priority?: number): StatusBarItem {
return new ExtHostStatusBarEntry(this._proxy, extensionId, alignment, priority);
}

View File

@@ -23,11 +23,11 @@ export class ExtHostStorage implements ExtHostStorageShape {
this._proxy = mainContext.getProxy(MainContext.MainThreadStorage);
}
getValue<T>(shared: boolean, key: string, defaultValue?: T): Thenable<T> {
getValue<T>(shared: boolean, key: string, defaultValue?: T): Promise<T> {
return this._proxy.$getValue<T>(shared, key).then(value => value || defaultValue);
}
setValue(shared: boolean, key: string, value: object): Thenable<void> {
setValue(shared: boolean, key: string, value: object): Promise<void> {
return this._proxy.$setValue(shared, key, value);
}

View File

@@ -6,14 +6,12 @@
import * as path from 'path';
import { URI, UriComponents } from 'vs/base/common/uri';
import * as nls from 'vs/nls';
import * as Objects from 'vs/base/common/objects';
import { asThenable } from 'vs/base/common/async';
import { asPromise } from 'vs/base/common/async';
import { Event, Emitter } from 'vs/base/common/event';
import { win32 } from 'vs/base/node/processes';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import * as tasks from 'vs/workbench/parts/tasks/common/tasks';
import { MainContext, MainThreadTaskShape, ExtHostTaskShape, IMainContext } from 'vs/workbench/api/node/extHost.protocol';
@@ -22,7 +20,7 @@ import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import * as vscode from 'vscode';
import {
TaskDefinitionDTO, TaskExecutionDTO, TaskPresentationOptionsDTO, ProcessExecutionOptionsDTO, ProcessExecutionDTO,
ShellExecutionOptionsDTO, ShellExecutionDTO, TaskDTO, TaskHandleDTO, TaskFilterDTO, TaskProcessStartedDTO, TaskProcessEndedDTO, TaskSystemInfoDTO
ShellExecutionOptionsDTO, ShellExecutionDTO, TaskDTO, TaskHandleDTO, TaskFilterDTO, TaskProcessStartedDTO, TaskProcessEndedDTO, TaskSystemInfoDTO, TaskSetDTO
} from '../shared/tasks';
// {{SQL CARBON EDIT}}
@@ -33,443 +31,15 @@ import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { CancellationToken } from 'vs/base/common/cancellation';
/*
namespace ProblemPattern {
export function from(value: vscode.ProblemPattern | vscode.MultiLineProblemPattern): Problems.ProblemPattern | Problems.MultiLineProblemPattern {
if (value === void 0 || value === null) {
return undefined;
}
if (Array.isArray(value)) {
let result: Problems.ProblemPattern[] = [];
for (let pattern of value) {
let converted = fromSingle(pattern);
if (!converted) {
return undefined;
}
result.push(converted);
}
return result;
} else {
return fromSingle(value);
}
}
function copyProperty(target: Problems.ProblemPattern, source: vscode.ProblemPattern, tk: keyof Problems.ProblemPattern) {
let sk: keyof vscode.ProblemPattern = tk;
let value = source[sk];
if (typeof value === 'number') {
target[tk] = value;
}
}
function getValue(value: number, defaultValue: number): number {
if (value !== void 0 && value === null) {
return value;
}
return defaultValue;
}
function fromSingle(problemPattern: vscode.ProblemPattern): Problems.ProblemPattern {
if (problemPattern === void 0 || problemPattern === null || !(problemPattern.regexp instanceof RegExp)) {
return undefined;
}
let result: Problems.ProblemPattern = {
regexp: problemPattern.regexp
};
copyProperty(result, problemPattern, 'file');
copyProperty(result, problemPattern, 'location');
copyProperty(result, problemPattern, 'line');
copyProperty(result, problemPattern, 'character');
copyProperty(result, problemPattern, 'endLine');
copyProperty(result, problemPattern, 'endCharacter');
copyProperty(result, problemPattern, 'severity');
copyProperty(result, problemPattern, 'code');
copyProperty(result, problemPattern, 'message');
if (problemPattern.loop === true || problemPattern.loop === false) {
result.loop = problemPattern.loop;
}
if (result.location) {
result.file = getValue(result.file, 1);
result.message = getValue(result.message, 0);
} else {
result.file = getValue(result.file, 1);
result.line = getValue(result.line, 2);
result.character = getValue(result.character, 3);
result.message = getValue(result.message, 0);
}
return result;
}
}
namespace ApplyTo {
export function from(value: vscode.ApplyToKind): Problems.ApplyToKind {
if (value === void 0 || value === null) {
return Problems.ApplyToKind.allDocuments;
}
switch (value) {
case types.ApplyToKind.OpenDocuments:
return Problems.ApplyToKind.openDocuments;
case types.ApplyToKind.ClosedDocuments:
return Problems.ApplyToKind.closedDocuments;
}
return Problems.ApplyToKind.allDocuments;
}
}
namespace FileLocation {
export function from(value: vscode.FileLocationKind | string): { kind: Problems.FileLocationKind; prefix?: string } {
if (value === void 0 || value === null) {
return { kind: Problems.FileLocationKind.Auto };
}
if (typeof value === 'string') {
return { kind: Problems.FileLocationKind.Relative, prefix: value };
}
switch (value) {
case types.FileLocationKind.Absolute:
return { kind: Problems.FileLocationKind.Absolute };
case types.FileLocationKind.Relative:
return { kind: Problems.FileLocationKind.Relative, prefix: '${workspaceFolder}' };
}
return { kind: Problems.FileLocationKind.Auto };
}
}
namespace WatchingPattern {
export function from(value: RegExp | vscode.BackgroundPattern): Problems.WatchingPattern {
if (value === void 0 || value === null) {
return undefined;
}
if (value instanceof RegExp) {
return { regexp: value };
}
if (!(value.regexp instanceof RegExp)) {
return undefined;
}
let result: Problems.WatchingPattern = {
regexp: value.regexp
};
if (typeof value.file === 'number') {
result.file = value.file;
}
return result;
}
}
namespace BackgroundMonitor {
export function from(value: vscode.BackgroundMonitor): Problems.WatchingMatcher {
if (value === void 0 || value === null) {
return undefined;
}
let result: Problems.WatchingMatcher = {
activeOnStart: !!value.activeOnStart,
beginsPattern: WatchingPattern.from(value.beginsPattern),
endsPattern: WatchingPattern.from(value.endsPattern)
};
return result;
}
}
namespace ProblemMatcher {
export function from(values: (string | vscode.ProblemMatcher)[]): (string | Problems.ProblemMatcher)[] {
if (values === void 0 || values === null) {
return undefined;
}
let result: (string | Problems.ProblemMatcher)[] = [];
for (let value of values) {
let converted = typeof value === 'string' ? value : fromSingle(value);
if (converted) {
result.push(converted);
}
}
return result;
}
function fromSingle(problemMatcher: vscode.ProblemMatcher): Problems.ProblemMatcher {
if (problemMatcher === void 0 || problemMatcher === null) {
return undefined;
}
let location = FileLocation.from(problemMatcher.fileLocation);
let result: Problems.ProblemMatcher = {
owner: typeof problemMatcher.owner === 'string' ? problemMatcher.owner : UUID.generateUuid(),
applyTo: ApplyTo.from(problemMatcher.applyTo),
fileLocation: location.kind,
filePrefix: location.prefix,
pattern: ProblemPattern.from(problemMatcher.pattern),
severity: fromDiagnosticSeverity(problemMatcher.severity),
};
return result;
}
}
*/
namespace TaskRevealKind {
export function from(value: vscode.TaskRevealKind): tasks.RevealKind {
if (value === void 0 || value === null) {
return tasks.RevealKind.Always;
}
switch (value) {
case types.TaskRevealKind.Silent:
return tasks.RevealKind.Silent;
case types.TaskRevealKind.Never:
return tasks.RevealKind.Never;
}
return tasks.RevealKind.Always;
}
}
namespace TaskPanelKind {
export function from(value: vscode.TaskPanelKind): tasks.PanelKind {
if (value === void 0 || value === null) {
return tasks.PanelKind.Shared;
}
switch (value) {
case types.TaskPanelKind.Dedicated:
return tasks.PanelKind.Dedicated;
case types.TaskPanelKind.New:
return tasks.PanelKind.New;
default:
return tasks.PanelKind.Shared;
}
}
}
namespace PresentationOptions {
export function from(value: vscode.TaskPresentationOptions): tasks.PresentationOptions {
if (value === void 0 || value === null) {
return { reveal: tasks.RevealKind.Always, echo: true, focus: false, panel: tasks.PanelKind.Shared, showReuseMessage: true, clear: false };
}
return {
reveal: TaskRevealKind.from(value.reveal),
echo: value.echo === void 0 ? true : !!value.echo,
focus: !!value.focus,
panel: TaskPanelKind.from(value.panel),
showReuseMessage: value.showReuseMessage === void 0 ? true : !!value.showReuseMessage,
clear: value.clear === void 0 ? false : !!value.clear,
};
}
}
namespace Strings {
export function from(value: string[]): string[] {
if (value === void 0 || value === null) {
return undefined;
}
for (let element of value) {
if (typeof element !== 'string') {
return [];
}
}
return value;
}
}
namespace CommandOptions {
function isShellConfiguration(value: any): value is { executable: string; shellArgs?: string[] } {
return value && typeof value.executable === 'string';
}
export function from(value: vscode.ShellExecutionOptions | vscode.ProcessExecutionOptions): tasks.CommandOptions {
if (value === void 0 || value === null) {
return undefined;
}
let result: tasks.CommandOptions = {
};
if (typeof value.cwd === 'string') {
result.cwd = value.cwd;
}
if (value.env) {
result.env = Object.create(null);
Object.keys(value.env).forEach(key => {
let envValue = value.env[key];
if (typeof envValue === 'string') {
result.env[key] = envValue;
}
});
}
if (isShellConfiguration(value)) {
result.shell = ShellConfiguration.from(value);
}
return result;
}
}
namespace ShellQuoteOptions {
export function from(value: vscode.ShellQuotingOptions): tasks.ShellQuotingOptions {
if (value === void 0 || value === null) {
return undefined;
}
return {
escape: value.escape,
strong: value.strong,
weak: value.strong
};
}
}
namespace ShellConfiguration {
export function from(value: { executable?: string, shellArgs?: string[], quotes?: vscode.ShellQuotingOptions }): tasks.ShellConfiguration {
if (value === void 0 || value === null || !value.executable) {
return undefined;
}
let result: tasks.ShellConfiguration = {
executable: value.executable,
args: Strings.from(value.shellArgs),
quoting: ShellQuoteOptions.from(value.quotes)
};
return result;
}
}
namespace ShellString {
export function from(value: (string | vscode.ShellQuotedString)[]): tasks.CommandString[] {
if (value === void 0 || value === null) {
return undefined;
}
return value.slice(0);
}
}
namespace Tasks {
export function from(tasks: vscode.Task[], rootFolder: vscode.WorkspaceFolder, extension: IExtensionDescription): tasks.ContributedTask[] {
if (tasks === void 0 || tasks === null) {
return [];
}
let result: tasks.ContributedTask[] = [];
for (let task of tasks) {
let converted = fromSingle(task, rootFolder, extension);
if (converted) {
result.push(converted);
}
}
return result;
}
function fromSingle(task: vscode.Task, rootFolder: vscode.WorkspaceFolder, extension: IExtensionDescription): tasks.ContributedTask {
if (typeof task.name !== 'string') {
return undefined;
}
let command: tasks.CommandConfiguration;
let execution = task.execution;
if (execution instanceof types.ProcessExecution) {
command = getProcessCommand(execution);
} else if (execution instanceof types.ShellExecution) {
command = getShellCommand(execution);
} else {
return undefined;
}
if (command === void 0) {
return undefined;
}
command.presentation = PresentationOptions.from(task.presentationOptions);
let taskScope: types.TaskScope.Global | types.TaskScope.Workspace | vscode.WorkspaceFolder | undefined = task.scope;
let workspaceFolder: vscode.WorkspaceFolder | undefined;
let scope: tasks.TaskScope;
// For backwards compatibility
if (taskScope === void 0) {
scope = tasks.TaskScope.Folder;
workspaceFolder = rootFolder;
} else if (taskScope === types.TaskScope.Global) {
scope = tasks.TaskScope.Global;
} else if (taskScope === types.TaskScope.Workspace) {
scope = tasks.TaskScope.Workspace;
} else {
scope = tasks.TaskScope.Folder;
workspaceFolder = taskScope;
}
let source: tasks.ExtensionTaskSource = {
kind: tasks.TaskSourceKind.Extension,
label: typeof task.source === 'string' ? task.source : extension.name,
extension: extension.id,
scope: scope,
workspaceFolder: undefined
};
// We can't transfer a workspace folder object from the extension host to main since they differ
// in shape and we don't have backwards converting function. So transfer the URI and resolve the
// workspace folder on the main side.
(source as any as tasks.ExtensionTaskSourceTransfer).__workspaceFolder = workspaceFolder ? workspaceFolder.uri as URI : undefined;
(source as any as tasks.ExtensionTaskSourceTransfer).__definition = task.definition;
let label = nls.localize('task.label', '{0}: {1}', source.label, task.name);
// The definition id will be prefix on the main side since we compute it there.
let id = `${extension.id}`;
let result: tasks.ContributedTask = {
_id: id,
_source: source,
_label: label,
type: task.definition.type,
defines: undefined,
name: task.name,
identifier: label,
group: task.group ? (task.group as types.TaskGroup).id : undefined,
command: command,
isBackground: !!task.isBackground,
problemMatchers: task.problemMatchers.slice(),
hasDefinedMatchers: (task as types.Task).hasDefinedMatchers,
runOptions: (<vscode.Task>task).runOptions ? (<vscode.Task>task).runOptions : { reevaluateOnRerun: true },
};
return result;
}
function getProcessCommand(value: vscode.ProcessExecution): tasks.CommandConfiguration {
if (typeof value.process !== 'string') {
return undefined;
}
let result: tasks.CommandConfiguration = {
name: value.process,
args: Strings.from(value.args),
runtime: tasks.RuntimeType.Process,
suppressTaskName: true,
presentation: undefined
};
if (value.options) {
result.options = CommandOptions.from(value.options);
}
return result;
}
function getShellCommand(value: vscode.ShellExecution): tasks.CommandConfiguration {
if (value.args) {
if (typeof value.command !== 'string' && typeof value.command.value !== 'string') {
return undefined;
}
let result: tasks.CommandConfiguration = {
name: value.command,
args: ShellString.from(value.args),
runtime: tasks.RuntimeType.Shell,
presentation: undefined
};
if (value.options) {
result.options = CommandOptions.from(value.options);
}
return result;
} else {
if (typeof value.commandLine !== 'string') {
return undefined;
}
let result: tasks.CommandConfiguration = {
name: value.commandLine,
runtime: tasks.RuntimeType.Shell,
presentation: undefined
};
if (value.options) {
result.options = CommandOptions.from(value.options);
}
return result;
}
}
}
namespace TaskDefinitionDTO {
export function from(value: vscode.TaskDefinition): TaskDefinitionDTO {
if (value === void 0 || value === null) {
if (value === undefined || value === null) {
return undefined;
}
return value;
}
export function to(value: TaskDefinitionDTO): vscode.TaskDefinition {
if (value === void 0 || value === null) {
if (value === undefined || value === null) {
return undefined;
}
return value;
@@ -478,13 +48,13 @@ namespace TaskDefinitionDTO {
namespace TaskPresentationOptionsDTO {
export function from(value: vscode.TaskPresentationOptions): TaskPresentationOptionsDTO {
if (value === void 0 || value === null) {
if (value === undefined || value === null) {
return undefined;
}
return value;
}
export function to(value: TaskPresentationOptionsDTO): vscode.TaskPresentationOptions {
if (value === void 0 || value === null) {
if (value === undefined || value === null) {
return undefined;
}
return value;
@@ -493,13 +63,13 @@ namespace TaskPresentationOptionsDTO {
namespace ProcessExecutionOptionsDTO {
export function from(value: vscode.ProcessExecutionOptions): ProcessExecutionOptionsDTO {
if (value === void 0 || value === null) {
if (value === undefined || value === null) {
return undefined;
}
return value;
}
export function to(value: ProcessExecutionOptionsDTO): vscode.ProcessExecutionOptions {
if (value === void 0 || value === null) {
if (value === undefined || value === null) {
return undefined;
}
return value;
@@ -512,7 +82,7 @@ namespace ProcessExecutionDTO {
return candidate && !!candidate.process;
}
export function from(value: vscode.ProcessExecution): ProcessExecutionDTO {
if (value === void 0 || value === null) {
if (value === undefined || value === null) {
return undefined;
}
let result: ProcessExecutionDTO = {
@@ -525,7 +95,7 @@ namespace ProcessExecutionDTO {
return result;
}
export function to(value: ProcessExecutionDTO): types.ProcessExecution {
if (value === void 0 || value === null) {
if (value === undefined || value === null) {
return undefined;
}
return new types.ProcessExecution(value.process, value.args, value.options);
@@ -534,13 +104,13 @@ namespace ProcessExecutionDTO {
namespace ShellExecutionOptionsDTO {
export function from(value: vscode.ShellExecutionOptions): ShellExecutionOptionsDTO {
if (value === void 0 || value === null) {
if (value === undefined || value === null) {
return undefined;
}
return value;
}
export function to(value: ShellExecutionOptionsDTO): vscode.ShellExecutionOptions {
if (value === void 0 || value === null) {
if (value === undefined || value === null) {
return undefined;
}
return value;
@@ -553,12 +123,12 @@ namespace ShellExecutionDTO {
return candidate && (!!candidate.commandLine || !!candidate.command);
}
export function from(value: vscode.ShellExecution): ShellExecutionDTO {
if (value === void 0 || value === null) {
if (value === undefined || value === null) {
return undefined;
}
let result: ShellExecutionDTO = {
};
if (value.commandLine !== void 0) {
if (value.commandLine !== undefined) {
result.commandLine = value.commandLine;
} else {
result.command = value.command;
@@ -570,7 +140,7 @@ namespace ShellExecutionDTO {
return result;
}
export function to(value: ShellExecutionDTO): types.ShellExecution {
if (value === void 0 || value === null) {
if (value === undefined || value === null) {
return undefined;
}
if (value.commandLine) {
@@ -584,7 +154,7 @@ namespace ShellExecutionDTO {
namespace TaskHandleDTO {
export function from(value: types.Task): TaskHandleDTO {
let folder: UriComponents;
if (value.scope !== void 0 && typeof value.scope !== 'number') {
if (value.scope !== undefined && typeof value.scope !== 'number') {
folder = value.scope.uri;
}
return {
@@ -596,8 +166,22 @@ namespace TaskHandleDTO {
namespace TaskDTO {
export function fromMany(tasks: vscode.Task[], extension: IExtensionDescription): TaskDTO[] {
if (tasks === undefined || tasks === null) {
return [];
}
let result: TaskDTO[] = [];
for (let task of tasks) {
let converted = from(task, extension);
if (converted) {
result.push(converted);
}
}
return result;
}
export function from(value: vscode.Task, extension: IExtensionDescription): TaskDTO {
if (value === void 0 || value === null) {
if (value === undefined || value === null) {
return undefined;
}
let execution: ShellExecutionDTO | ProcessExecutionDTO;
@@ -614,6 +198,9 @@ namespace TaskDTO {
} else {
scope = value.scope.uri;
}
} else {
// To continue to support the deprecated task constructor that doesn't take a scope, we must add a scope here:
scope = types.TaskScope.Workspace;
}
if (!definition || !scope) {
return undefined;
@@ -624,7 +211,7 @@ namespace TaskDTO {
definition,
name: value.name,
source: {
extensionId: extension.id,
extensionId: extension.identifier.value,
label: value.source,
scope: scope
},
@@ -639,7 +226,7 @@ namespace TaskDTO {
return result;
}
export function to(value: TaskDTO, workspace: ExtHostWorkspace): types.Task {
if (value === void 0 || value === null) {
if (value === undefined || value === null) {
return undefined;
}
let execution: types.ShellExecution | types.ProcessExecution;
@@ -651,7 +238,7 @@ namespace TaskDTO {
let definition: vscode.TaskDefinition = TaskDefinitionDTO.to(value.definition);
let scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder;
if (value.source) {
if (value.source.scope !== void 0) {
if (value.source.scope !== undefined) {
if (typeof value.source.scope === 'number') {
scope = value.source.scope;
} else {
@@ -665,10 +252,10 @@ namespace TaskDTO {
return undefined;
}
let result = new types.Task(definition, scope, value.name, value.source.label, execution, value.problemMatchers);
if (value.isBackground !== void 0) {
if (value.isBackground !== undefined) {
result.isBackground = value.isBackground;
}
if (value.group !== void 0) {
if (value.group !== undefined) {
result.group = types.TaskGroup.from(value.group);
}
if (value.presentationOptions) {
@@ -778,7 +365,7 @@ export class ExtHostTask implements ExtHostTaskShape {
this._proxy.$registerTaskSystem(scheme, info);
}
public fetchTasks(filter?: vscode.TaskFilter): Thenable<vscode.Task[]> {
public fetchTasks(filter?: vscode.TaskFilter): Promise<vscode.Task[]> {
return this._proxy.$fetchTasks(TaskFilterDTO.from(filter)).then((values) => {
let result: vscode.Task[] = [];
for (let value of values) {
@@ -791,14 +378,14 @@ export class ExtHostTask implements ExtHostTaskShape {
});
}
public executeTask(extension: IExtensionDescription, task: vscode.Task): Thenable<vscode.TaskExecution> {
public executeTask(extension: IExtensionDescription, task: vscode.Task): Promise<vscode.TaskExecution> {
let tTask = (task as types.Task);
// We have a preserved ID. So the task didn't change.
if (tTask._id !== void 0) {
if (tTask._id !== undefined) {
return this._proxy.$executeTask(TaskHandleDTO.from(tTask)).then(value => this.getTaskExecution(value, task));
} else {
let dto = TaskDTO.from(task, extension);
if (dto === void 0) {
if (dto === undefined) {
return Promise.reject(new Error('Task is not valid'));
}
return this._proxy.$executeTask(dto).then(value => this.getTaskExecution(value, task));
@@ -811,7 +398,7 @@ export class ExtHostTask implements ExtHostTaskShape {
return result;
}
public terminateTask(execution: vscode.TaskExecution): Thenable<void> {
public terminateTask(execution: vscode.TaskExecution): Promise<void> {
if (!(execution instanceof TaskExecutionImpl)) {
throw new Error('No valid task execution provided');
}
@@ -868,12 +455,12 @@ export class ExtHostTask implements ExtHostTaskShape {
}
}
public $provideTasks(handle: number, validTypes: { [key: string]: boolean; }): Thenable<tasks.TaskSet> {
public $provideTasks(handle: number, validTypes: { [key: string]: boolean; }): Thenable<TaskSetDTO> {
let handler = this._handlers.get(handle);
if (!handler) {
return Promise.reject(new Error('no handler found'));
}
return asThenable(() => handler.provider.provideTasks(CancellationToken.None)).then(value => {
return asPromise(() => handler.provider.provideTasks(CancellationToken.None)).then(value => {
let sanitized: vscode.Task[] = [];
for (let task of value) {
if (task.definition && validTypes[task.definition.type] === true) {
@@ -883,23 +470,23 @@ export class ExtHostTask implements ExtHostTaskShape {
console.warn(`The task [${task.source}, ${task.name}] uses an undefined task type. The task will be ignored in the future.`);
}
}
let workspaceFolders = this._workspaceService.getWorkspaceFolders();
return {
tasks: Tasks.from(sanitized, workspaceFolders && workspaceFolders.length > 0 ? workspaceFolders[0] : undefined, handler.extension),
tasks: TaskDTO.fromMany(sanitized, handler.extension),
extension: handler.extension
};
});
}
// {{SQL CARBON EDIT}} disable debug related method
public $resolveVariables(uriComponents: UriComponents, toResolve: { process?: { name: string; cwd?: string; path?: string }, variables: string[] }): Thenable<{ process?: string, variables: { [key: string]: string; } }> {
public async $resolveVariables(uriComponents: UriComponents, toResolve: { process?: { name: string; cwd?: string; path?: string }, variables: string[] }): Promise<{ process?: string, variables: { [key: string]: string; } }> {
// const configProvider = await this._configurationService.getConfigProvider();
// let uri: URI = URI.revive(uriComponents);
// let result = {
// process: undefined as string,
// variables: Object.create(null)
// };
// let workspaceFolder = this._workspaceService.resolveWorkspaceFolder(uri);
// let resolver = new ExtHostVariableResolverService(this._workspaceService, this._editorService, this._configurationService);
// let resolver = new ExtHostVariableResolverService(this._workspaceService, this._editorService, configProvider);
// let ws: IWorkspaceFolder = {
// uri: workspaceFolder.uri,
// name: workspaceFolder.name,
@@ -911,9 +498,9 @@ export class ExtHostTask implements ExtHostTaskShape {
// for (let variable of toResolve.variables) {
// result.variables[variable] = resolver.resolve(ws, variable);
// }
// if (toResolve.process !== void 0) {
// if (toResolve.process !== undefined) {
// let paths: string[] | undefined = undefined;
// if (toResolve.process.path !== void 0) {
// if (toResolve.process.path !== undefined) {
// paths = toResolve.process.path.split(path.delimiter);
// for (let i = 0; i < paths.length; i++) {
// paths[i] = resolver.resolve(ws, paths[i]);
@@ -921,12 +508,12 @@ export class ExtHostTask implements ExtHostTaskShape {
// }
// result.process = win32.findExecutable(
// resolver.resolve(ws, toResolve.process.name),
// toResolve.process.cwd !== void 0 ? resolver.resolve(ws, toResolve.process.cwd) : undefined,
// toResolve.process.cwd !== undefined ? resolver.resolve(ws, toResolve.process.cwd) : undefined,
// paths
// );
// }
// return Promise.resolve(result);
return Promise.resolve(undefined);
// return result;
return undefined;
}
private nextHandle(): number {

View File

@@ -14,6 +14,11 @@ import { ILogService } from 'vs/platform/log/common/log';
import { EXT_HOST_CREATION_DELAY } from 'vs/workbench/parts/terminal/common/terminal';
import { TerminalProcess } from 'vs/workbench/parts/terminal/node/terminalProcess';
import { timeout } from 'vs/base/common/async';
import { generateRandomPipeName } from 'vs/base/parts/ipc/node/ipc.net';
import * as http from 'http';
import * as fs from 'fs';
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
import { sanitizeProcessEnvironment } from 'vs/base/node/processes';
const RENDERER_NO_PROCESS_ID = -1;
@@ -74,7 +79,7 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
private _pidPromise: Promise<number>;
private _pidPromiseComplete: (value: number) => any;
private readonly _onData: Emitter<string> = new Emitter<string>();
private readonly _onData = new Emitter<string>();
public get onDidWriteData(): Event<string> {
// Tell the main side to start sending data if it's not already
this._idPromise.then(c => {
@@ -102,12 +107,14 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
public create(
shellPath?: string,
shellArgs?: string[],
cwd?: string,
cwd?: string | URI,
env?: { [key: string]: string },
waitOnExit?: boolean
waitOnExit?: boolean,
strictEnv?: boolean
): void {
this._proxy.$createTerminal(this._name, shellPath, shellArgs, cwd, env, waitOnExit).then((id) => {
this._runQueuedRequests(id);
this._proxy.$createTerminal(this._name, shellPath, shellArgs, cwd, env, waitOnExit, strictEnv).then(terminal => {
this._name = terminal.name;
this._runQueuedRequests(terminal.id);
});
}
@@ -119,7 +126,7 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
this._name = name;
}
public get processId(): Thenable<number> {
public get processId(): Promise<number> {
return this._pidPromise;
}
@@ -143,6 +150,13 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
if (this._pidPromiseComplete) {
this._pidPromiseComplete(processId);
this._pidPromiseComplete = null;
} else {
// Recreate the promise if this is the nth processId set (eg. reused task terminals)
this._pidPromise.then(pid => {
if (pid !== processId) {
this._pidPromise = Promise.resolve(processId);
}
});
}
}
@@ -159,7 +173,7 @@ export class ExtHostTerminalRenderer extends BaseExtHostTerminal implements vsco
this._queueApiRequest(this._proxy.$terminalRendererSetName, [this._name]);
}
private readonly _onInput: Emitter<string> = new Emitter<string>();
private readonly _onInput = new Emitter<string>();
public get onDidAcceptInput(): Event<string> {
this._checkDisposed();
this._queueApiRequest(this._proxy.$terminalRendererRegisterOnInputListener, [this._id]);
@@ -233,6 +247,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
private _terminalProcesses: { [id: number]: TerminalProcess } = {};
private _terminalRenderers: ExtHostTerminalRenderer[] = [];
private _getTerminalPromises: { [id: number]: Promise<ExtHostTerminal> } = {};
private _cliServer: CLIServer | undefined;
public get activeTerminal(): ExtHostTerminal { return this._activeTerminal; }
public get terminals(): ExtHostTerminal[] { return this._terminals; }
@@ -247,7 +262,8 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
constructor(
mainContext: IMainContext,
private _extHostConfiguration: ExtHostConfiguration,
private _logService: ILogService
private _logService: ILogService,
private _commands: ExtHostCommands
) {
this._proxy = mainContext.getProxy(MainContext.MainThreadTerminalService);
}
@@ -261,7 +277,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
public createTerminalFromOptions(options: vscode.TerminalOptions): vscode.Terminal {
const terminal = new ExtHostTerminal(this._proxy, options.name);
terminal.create(options.shellPath, options.shellArgs, options.cwd, options.env /*, options.waitOnExit*/);
terminal.create(options.shellPath, options.shellArgs, options.cwd, options.env, /*options.waitOnExit*/ undefined, options.strictEnv);
this._terminals.push(terminal);
return terminal;
}
@@ -365,11 +381,11 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
}
}
public $createProcess(id: number, shellLaunchConfig: ShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents, cols: number, rows: number): void {
public async $createProcess(id: number, shellLaunchConfig: ShellLaunchConfigDto, activeWorkspaceRootUriComponents: UriComponents, cols: number, rows: number): Promise<void> {
// TODO: This function duplicates a lot of TerminalProcessManager.createProcess, ideally
// they would be merged into a single implementation.
const terminalConfig = this._extHostConfiguration.getConfiguration('terminal.integrated');
const configProvider = await this._extHostConfiguration.getConfigProvider();
const terminalConfig = configProvider.getConfiguration('terminal.integrated');
if (!shellLaunchConfig.executable) {
// TODO: This duplicates some of TerminalConfigHelper.mergeDefaultShellPathAndArgs and should be merged
@@ -390,29 +406,40 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
// TODO: Pull in and resolve config settings
// // Resolve env vars from config and shell
// const lastActiveWorkspaceRoot = this._workspaceContextService.getWorkspaceFolder(lastActiveWorkspaceRootUri);
// const platformKey = platform.isWindows ? 'windows' : (platform.isMacintosh ? 'osx' : 'linux');
// const envFromConfig = terminalEnvironment.resolveConfigurationVariables(this._configurationResolverService, { ...this._configHelper.config.env[platformKey] }, lastActiveWorkspaceRoot);
const platformKey = platform.isWindows ? 'windows' : (platform.isMacintosh ? 'osx' : 'linux');
// const envFromConfig = terminalEnvironment.resolveConfigurationVariables(this._configurationResolverService, { ...terminalConfig.env[platformKey] }, lastActiveWorkspaceRoot);
const envFromConfig = { ...terminalConfig.env[platformKey] };
// const envFromShell = terminalEnvironment.resolveConfigurationVariables(this._configurationResolverService, { ...shellLaunchConfig.env }, lastActiveWorkspaceRoot);
// Merge process env with the env from config
const env = { ...process.env };
// terminalEnvironment.mergeEnvironments(env, envFromConfig);
terminalEnvironment.mergeEnvironments(env, envFromConfig);
terminalEnvironment.mergeEnvironments(env, shellLaunchConfig.env);
// Sanitize the environment, removing any undesirable VS Code and Electron environment
// variables
sanitizeProcessEnvironment(env);
// Continue env initialization, merging in the env from the launch
// config and adding keys that are needed to create the process
const locale = terminalConfig.get('setLocaleVariables') ? platform.locale : undefined;
terminalEnvironment.addTerminalEnvironmentKeys(env, locale);
terminalEnvironment.addTerminalEnvironmentKeys(env, platform.locale, terminalConfig.get('setLocaleVariables'));
if (!this._cliServer) {
this._cliServer = new CLIServer(this._commands);
}
env['VSCODE_IPC_HOOK_CLI'] = this._cliServer.ipcHandlePath;
// Fork the process and listen for messages
this._logService.debug(`Terminal process launching on ext host`, shellLaunchConfig, initialCwd, cols, rows, env);
this._terminalProcesses[id] = new TerminalProcess(shellLaunchConfig, initialCwd, cols, rows, env);
this._terminalProcesses[id].onProcessIdReady(pid => this._proxy.$sendProcessPid(id, pid));
this._terminalProcesses[id].onProcessTitleChanged(title => this._proxy.$sendProcessTitle(id, title));
this._terminalProcesses[id].onProcessData(data => this._proxy.$sendProcessData(id, data));
this._terminalProcesses[id].onProcessExit((exitCode) => this._onProcessExit(id, exitCode));
const p = new TerminalProcess(shellLaunchConfig, initialCwd, cols, rows, env, terminalConfig.get('windowsEnableConpty'));
p.onProcessIdReady(pid => this._proxy.$sendProcessPid(id, pid));
p.onProcessTitleChanged(title => this._proxy.$sendProcessTitle(id, title));
p.onProcessData(data => this._proxy.$sendProcessData(id, data));
p.onProcessExit((exitCode) => this._onProcessExit(id, exitCode));
this._terminalProcesses[id] = p;
}
public $acceptProcessInput(id: number, data: string): void {
this._terminalProcesses[id].input(data);
}
@@ -432,6 +459,14 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
this._terminalProcesses[id].shutdown(immediate);
}
public $acceptProcessRequestInitialCwd(id: number): void {
this._terminalProcesses[id].getInitialCwd().then(initialCwd => this._proxy.$sendProcessInitialCwd(id, initialCwd));
}
public $acceptProcessRequestCwd(id: number): void {
this._terminalProcesses[id].getCwd().then(cwd => this._proxy.$sendProcessCwd(id, cwd));
}
private _onProcessExit(id: number, exitCode: number): void {
// Remove listeners
this._terminalProcesses[id].dispose();
@@ -441,6 +476,12 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
// Send exit event to main side
this._proxy.$sendProcessExit(id, exitCode);
if (this._cliServer && !Object.keys(this._terminalProcesses).length) {
this._cliServer.dispose();
this._cliServer = undefined;
}
}
private _getTerminalByIdEventually(id: number, retries: number = 5): Promise<ExtHostTerminal> {
@@ -512,3 +553,73 @@ class ApiRequest {
this._callback.apply(proxy, [id].concat(this._args));
}
}
class CLIServer {
private _server: http.Server;
private _ipcHandlePath: string | undefined;
constructor(private _commands: ExtHostCommands) {
this._server = http.createServer((req, res) => this.onRequest(req, res));
this.setup().catch(err => {
console.error(err);
return '';
});
}
public get ipcHandlePath() {
return this._ipcHandlePath;
}
private async setup(): Promise<string> {
this._ipcHandlePath = generateRandomPipeName();
try {
this._server.listen(this.ipcHandlePath);
this._server.on('error', err => console.error(err));
} catch (err) {
console.error('Could not start open from terminal server.');
}
return this.ipcHandlePath;
}
private toURIs(strs: string[]): URI[] {
const result: URI[] = [];
if (Array.isArray(strs)) {
for (const s of strs) {
try {
result.push(URI.parse(s));
} catch (e) {
// ignore
}
}
}
return result;
}
private onRequest(req: http.IncomingMessage, res: http.ServerResponse): void {
const chunks: string[] = [];
req.setEncoding('utf8');
req.on('data', (d: string) => chunks.push(d));
req.on('end', () => {
let { fileURIs, folderURIs, forceNewWindow, diffMode, addMode, forceReuseWindow } = JSON.parse(chunks.join(''));
if (folderURIs && folderURIs.length || fileURIs && fileURIs.length) {
if (folderURIs && folderURIs.length && !forceReuseWindow) {
forceNewWindow = true;
}
this._commands.executeCommand('_files.windowOpen', { folderURIs: this.toURIs(folderURIs), fileURIs: this.toURIs(fileURIs), forceNewWindow, diffMode, addMode, forceReuseWindow });
}
res.writeHead(200);
res.end();
});
}
dispose(): void {
this._server.close();
if (this._ipcHandlePath && process.platform !== 'win32' && fs.existsSync(this._ipcHandlePath)) {
fs.unlinkSync(this._ipcHandlePath);
}
}
}

View File

@@ -482,7 +482,7 @@ export class ExtHostTextEditor implements vscode.TextEditor {
);
}
private _trySetSelection(): Thenable<vscode.TextEditor> {
private _trySetSelection(): Promise<vscode.TextEditor> {
let selection = this._selections.map(TypeConverters.Selection.from);
return this._runOnProxy(() => this._proxy.$trySetSelections(this._id, selection));
}
@@ -494,7 +494,7 @@ export class ExtHostTextEditor implements vscode.TextEditor {
// ---- editing
edit(callback: (edit: TextEditorEdit) => void, options: { undoStopBefore: boolean; undoStopAfter: boolean; } = { undoStopBefore: true, undoStopAfter: true }): Thenable<boolean> {
edit(callback: (edit: TextEditorEdit) => void, options: { undoStopBefore: boolean; undoStopAfter: boolean; } = { undoStopBefore: true, undoStopAfter: true }): Promise<boolean> {
if (this._disposed) {
return Promise.reject(new Error('TextEditor#edit not possible on closed editors'));
}
@@ -503,7 +503,7 @@ export class ExtHostTextEditor implements vscode.TextEditor {
return this._applyEdit(edit);
}
private _applyEdit(editBuilder: TextEditorEdit): Thenable<boolean> {
private _applyEdit(editBuilder: TextEditorEdit): Promise<boolean> {
let editData = editBuilder.finalize();
// return when there is nothing to do
@@ -557,7 +557,7 @@ export class ExtHostTextEditor implements vscode.TextEditor {
});
}
insertSnippet(snippet: SnippetString, where?: Position | Position[] | Range | Range[], options: { undoStopBefore: boolean; undoStopAfter: boolean; } = { undoStopBefore: true, undoStopAfter: true }): Thenable<boolean> {
insertSnippet(snippet: SnippetString, where?: Position | Position[] | Range | Range[], options: { undoStopBefore: boolean; undoStopAfter: boolean; } = { undoStopBefore: true, undoStopAfter: true }): Promise<boolean> {
if (this._disposed) {
return Promise.reject(new Error('TextEditor#insertSnippet not possible on closed editors'));
}
@@ -589,7 +589,7 @@ export class ExtHostTextEditor implements vscode.TextEditor {
// ---- util
private _runOnProxy(callback: () => Thenable<any>): Thenable<ExtHostTextEditor> {
private _runOnProxy(callback: () => Promise<any>): Promise<ExtHostTextEditor> {
if (this._disposed) {
console.warn('TextEditor is closed/disposed');
return Promise.resolve(undefined);
@@ -603,8 +603,8 @@ export class ExtHostTextEditor implements vscode.TextEditor {
}
}
function warnOnError(promise: Thenable<any>): void {
promise.then(null, (err) => {
function warnOnError(promise: Promise<any>): void {
promise.then(undefined, (err) => {
console.warn(err);
});
}

View File

@@ -50,10 +50,10 @@ export class ExtHostEditors implements ExtHostEditorsShape {
return this._extHostDocumentsAndEditors.allEditors();
}
showTextDocument(document: vscode.TextDocument, column: vscode.ViewColumn, preserveFocus: boolean): Thenable<vscode.TextEditor>;
showTextDocument(document: vscode.TextDocument, options: { column: vscode.ViewColumn, preserveFocus: boolean, pinned: boolean }): Thenable<vscode.TextEditor>;
showTextDocument(document: vscode.TextDocument, columnOrOptions: vscode.ViewColumn | vscode.TextDocumentShowOptions, preserveFocus?: boolean): Thenable<vscode.TextEditor>;
showTextDocument(document: vscode.TextDocument, columnOrOptions: vscode.ViewColumn | vscode.TextDocumentShowOptions, preserveFocus?: boolean): Thenable<vscode.TextEditor> {
showTextDocument(document: vscode.TextDocument, column: vscode.ViewColumn, preserveFocus: boolean): Promise<vscode.TextEditor>;
showTextDocument(document: vscode.TextDocument, options: { column: vscode.ViewColumn, preserveFocus: boolean, pinned: boolean }): Promise<vscode.TextEditor>;
showTextDocument(document: vscode.TextDocument, columnOrOptions: vscode.ViewColumn | vscode.TextDocumentShowOptions, preserveFocus?: boolean): Promise<vscode.TextEditor>;
showTextDocument(document: vscode.TextDocument, columnOrOptions: vscode.ViewColumn | vscode.TextDocumentShowOptions, preserveFocus?: boolean): Promise<vscode.TextEditor> {
let options: ITextDocumentShowOptions;
if (typeof columnOrOptions === 'number') {
options = {
@@ -87,7 +87,7 @@ export class ExtHostEditors implements ExtHostEditorsShape {
return new TextEditorDecorationType(this._proxy, options);
}
applyWorkspaceEdit(edit: vscode.WorkspaceEdit): Thenable<boolean> {
applyWorkspaceEdit(edit: vscode.WorkspaceEdit): Promise<boolean> {
const dto = TypeConverters.WorkspaceEdit.from(edit, this._extHostDocumentsAndEditors);
return this._proxy.$tryApplyWorkspaceEdit(dto);
}
@@ -146,7 +146,7 @@ export class ExtHostEditors implements ExtHostEditorsShape {
}
}
getDiffInformation(id: string): Thenable<vscode.LineChange[]> {
getDiffInformation(id: string): Promise<vscode.LineChange[]> {
return Promise.resolve(this._proxy.$getDiffInformation(id));
}
}

View File

@@ -7,15 +7,15 @@ import { localize } from 'vs/nls';
import * as vscode from 'vscode';
import { basename } from 'vs/base/common/paths';
import { URI } from 'vs/base/common/uri';
import { debounceEvent, Emitter, Event } from 'vs/base/common/event';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { ExtHostTreeViewsShape, MainThreadTreeViewsShape } from './extHost.protocol';
import { ITreeItem, TreeViewItemHandleArg, ITreeItemLabel, IRevealOptions } from 'vs/workbench/common/views';
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands';
import { asThenable } from 'vs/base/common/async';
import { asPromise } from 'vs/base/common/async';
import { TreeItemCollapsibleState, ThemeIcon, MarkdownString } from 'vs/workbench/api/node/extHostTypes';
import { isUndefinedOrNull, isString } from 'vs/base/common/types';
import { equals } from 'vs/base/common/arrays';
import { equals, coalesce } from 'vs/base/common/arrays';
import { ILogService } from 'vs/platform/log/common/log';
import { IExtensionDescription, checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import * as typeConvert from 'vs/workbench/api/node/extHostTypeConverters';
@@ -34,15 +34,15 @@ function toTreeItemLabel(label: any, extension: IExtensionDescription): ITreeIte
&& typeof label === 'object'
&& typeof label.label === 'string') {
checkProposedApiEnabled(extension);
let highlights: [number, number][] = void 0;
let highlights: [number, number][] = undefined;
if (Array.isArray(label.highlights)) {
highlights = (<[number, number][]>label.highlights).filter((highlight => highlight.length === 2 && typeof highlight[0] === 'number' && typeof highlight[1] === 'number'));
highlights = highlights.length ? highlights : void 0;
highlights = highlights.length ? highlights : undefined;
}
return { label: label.label, highlights };
}
return void 0;
return undefined;
}
@@ -85,7 +85,7 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
get onDidChangeVisibility() { return treeView.onDidChangeVisibility; },
get message() { return treeView.message; },
set message(message: string | MarkdownString) { checkProposedApiEnabled(extension); treeView.message = message; },
reveal: (element: T, options?: IRevealOptions): Thenable<void> => {
reveal: (element: T, options?: IRevealOptions): Promise<void> => {
return treeView.reveal(element, options);
},
dispose: () => {
@@ -95,7 +95,7 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
};
}
$getChildren(treeViewId: string, treeItemHandle?: string): Thenable<ITreeItem[]> {
$getChildren(treeViewId: string, treeItemHandle?: string): Promise<ITreeItem[]> {
const treeView = this.treeViews.get(treeViewId);
if (!treeView) {
return Promise.reject(new Error(localize('treeView.notRegistered', 'No tree view with id \'{0}\' registered.', treeViewId)));
@@ -188,7 +188,7 @@ export class ExtHostTreeView<T> extends Disposable {
}
if (this.dataProvider.onDidChangeTreeData) {
let refreshingPromise, promiseCallback;
this._register(debounceEvent<T, T[]>(this.dataProvider.onDidChangeTreeData, (last, current) => {
this._register(Event.debounce<T, T[]>(this.dataProvider.onDidChangeTreeData, (last, current) => {
if (!refreshingPromise) {
// New refresh has started
refreshingPromise = new Promise(c => promiseCallback = c);
@@ -203,8 +203,8 @@ export class ExtHostTreeView<T> extends Disposable {
}
}
getChildren(parentHandle?: TreeItemHandle): Thenable<ITreeItem[]> {
const parentElement = parentHandle ? this.getExtensionElement(parentHandle) : void 0;
getChildren(parentHandle?: TreeItemHandle): Promise<ITreeItem[]> {
const parentElement = parentHandle ? this.getExtensionElement(parentHandle) : undefined;
if (parentHandle && !parentElement) {
console.error(`No tree item with id \'${parentHandle}\' found.`);
return Promise.resolve([]);
@@ -270,7 +270,7 @@ export class ExtHostTreeView<T> extends Disposable {
}
// {{SQL CARBON EDIT}}
protected resolveUnknownParentChain(element: T): Thenable<TreeNode[]> {
protected resolveUnknownParentChain(element: T): Promise<TreeNode[]> {
return this.resolveParent(element)
.then((parent) => {
if (!parent) {
@@ -285,21 +285,21 @@ export class ExtHostTreeView<T> extends Disposable {
});
}
private resolveParent(element: T): Thenable<T> {
private resolveParent(element: T): Promise<T> {
const node = this.nodes.get(element);
if (node) {
return Promise.resolve(node.parent ? this.elements.get(node.parent.item.handle) : null);
}
return asThenable(() => this.dataProvider.getParent(element));
return asPromise(() => this.dataProvider.getParent(element));
}
// {{SQL CARBON EDIT}}
protected resolveTreeNode(element: T, parent?: TreeNode): Thenable<TreeNode> {
protected resolveTreeNode(element: T, parent?: TreeNode): Promise<TreeNode> {
const node = this.nodes.get(element);
if (node) {
return Promise.resolve(node);
}
return asThenable(() => this.dataProvider.getTreeItem(element))
return asPromise(() => this.dataProvider.getTreeItem(element))
.then(extTreeItem => this.createHandle(element, extTreeItem, parent, true))
.then(handle => this.getChildren(parent ? parent.item.handle : null)
.then(() => {
@@ -328,21 +328,20 @@ export class ExtHostTreeView<T> extends Disposable {
return this.roots;
}
private fetchChildrenNodes(parentElement?: T): Thenable<TreeNode[]> {
private fetchChildrenNodes(parentElement?: T): Promise<TreeNode[]> {
// clear children cache
this.clearChildren(parentElement);
const parentNode = parentElement ? this.nodes.get(parentElement) : void 0;
return asThenable(() => this.dataProvider.getChildren(parentElement))
const parentNode = parentElement ? this.nodes.get(parentElement) : undefined;
return asPromise(() => this.dataProvider.getChildren(parentElement))
.then(elements => Promise.all(
(elements || [])
.filter(element => !!element)
.map(element => asThenable(() => this.dataProvider.getTreeItem(element))
coalesce(elements || [])
.map(element => asPromise(() => this.dataProvider.getTreeItem(element))
.then(extTreeItem => extTreeItem ? this.createAndRegisterTreeNode(element, extTreeItem, parentNode) : null))))
.then(nodes => nodes.filter(n => !!n));
.then(coalesce);
}
private refresh(elements: T[]): Thenable<void> {
private refresh(elements: T[]): Promise<void> {
const hasRoot = elements.some(element => !element);
if (hasRoot) {
this.clearAll(); // clear cache
@@ -353,7 +352,7 @@ export class ExtHostTreeView<T> extends Disposable {
return this.refreshHandles(handlesToRefresh);
}
}
return Promise.resolve(null);
return Promise.resolve(undefined);
}
// {{SQL CARBON EDIT}}
@@ -401,11 +400,11 @@ export class ExtHostTreeView<T> extends Disposable {
}
// {{SQL CARBON EDIT}}
protected refreshNode(treeItemHandle: TreeItemHandle): Thenable<TreeNode> {
protected refreshNode(treeItemHandle: TreeItemHandle): Promise<TreeNode> {
const extElement = this.getExtensionElement(treeItemHandle);
const existing = this.nodes.get(extElement);
this.clearChildren(extElement); // clear children cache
return asThenable(() => this.dataProvider.getTreeItem(extElement))
return asPromise(() => this.dataProvider.getTreeItem(extElement))
.then(extTreeItem => {
if (extTreeItem) {
const newNode = this.createTreeNode(extElement, extTreeItem, existing.parent);
@@ -431,7 +430,7 @@ export class ExtHostTreeView<T> extends Disposable {
return {
item: this.createTreeItem(element, extensionTreeItem, parent),
parent,
children: void 0
children: undefined
};
}
@@ -442,16 +441,16 @@ export class ExtHostTreeView<T> extends Disposable {
const icon = this.getLightIconPath(extensionTreeItem);
const item = {
handle,
parentHandle: parent ? parent.item.handle : void 0,
parentHandle: parent ? parent.item.handle : undefined,
label: toTreeItemLabel(extensionTreeItem.label, this.extension),
description: extensionTreeItem.description,
resourceUri: extensionTreeItem.resourceUri,
tooltip: typeof extensionTreeItem.tooltip === 'string' ? extensionTreeItem.tooltip : void 0,
command: extensionTreeItem.command ? this.commands.toInternal(extensionTreeItem.command) : void 0,
tooltip: typeof extensionTreeItem.tooltip === 'string' ? extensionTreeItem.tooltip : undefined,
command: extensionTreeItem.command ? this.commands.toInternal(extensionTreeItem.command) : undefined,
contextValue: extensionTreeItem.contextValue,
icon,
iconDark: this.getDarkIconPath(extensionTreeItem) || icon,
themeIcon: extensionTreeItem.iconPath instanceof ThemeIcon ? { id: extensionTreeItem.iconPath.id } : void 0,
themeIcon: extensionTreeItem.iconPath instanceof ThemeIcon ? { id: extensionTreeItem.iconPath.id } : undefined,
collapsibleState: isUndefinedOrNull(extensionTreeItem.collapsibleState) ? TreeItemCollapsibleState.None : extensionTreeItem.collapsibleState,
// {{SQL CARBON EDIT}}
payload: extensionTreeItem.payload,
@@ -470,7 +469,7 @@ export class ExtHostTreeView<T> extends Disposable {
const prefix: string = parent ? parent.item.handle : ExtHostTreeView.LABEL_HANDLE_PREFIX;
let elementId = treeItemLabel ? treeItemLabel.label : resourceUri ? basename(resourceUri.path) : '';
elementId = elementId.indexOf('/') !== -1 ? elementId.replace('/', '//') : elementId;
const existingHandle = this.nodes.has(element) ? this.nodes.get(element).item.handle : void 0;
const existingHandle = this.nodes.has(element) ? this.nodes.get(element).item.handle : undefined;
const childrenNodes = (this.getChildrenNodes(parent) || []);
let handle: TreeItemHandle;
@@ -497,14 +496,14 @@ export class ExtHostTreeView<T> extends Disposable {
}
return this.getIconPath(extensionTreeItem.iconPath['light']);
}
return void 0;
return undefined;
}
private getDarkIconPath(extensionTreeItem: vscode.TreeItem): URI {
if (extensionTreeItem.iconPath && !(extensionTreeItem.iconPath instanceof ThemeIcon) && extensionTreeItem.iconPath['dark']) {
return this.getIconPath(extensionTreeItem.iconPath['dark']);
}
return void 0;
return undefined;
}
private getIconPath(iconPath: string | URI): URI {
@@ -564,7 +563,7 @@ export class ExtHostTreeView<T> extends Disposable {
}
}
}
node.children = void 0;
node.children = undefined;
} else {
this.clearAll();
}

View File

@@ -111,7 +111,7 @@ export namespace Diagnostic {
...Range.from(value.range),
message: value.message,
source: value.source,
code: isString(value.code) || isNumber(value.code) ? String(value.code) : void 0,
code: isString(value.code) || isNumber(value.code) ? String(value.code) : undefined,
severity: DiagnosticSeverity.from(value.severity),
relatedInformation: value.relatedInformation && value.relatedInformation.map(DiagnosticRelatedInformation.from),
tags: Array.isArray(value.tags) ? value.tags.map(DiagnosticTag.from) : undefined,
@@ -543,7 +543,7 @@ export namespace WorkspaceSymbol {
export namespace DocumentSymbol {
export function from(info: vscode.DocumentSymbol): modes.DocumentSymbol {
const result: modes.DocumentSymbol = {
name: info.name,
name: info.name || '!!MISSING: name!!',
detail: info.detail,
range: Range.from(info.range),
selectionRange: Range.from(info.selectionRange),
@@ -583,16 +583,16 @@ export namespace location {
}
export namespace DefinitionLink {
export function from(value: vscode.Location | vscode.DefinitionLink): modes.DefinitionLink {
export function from(value: vscode.Location | vscode.DefinitionLink): modes.LocationLink {
const definitionLink = <vscode.DefinitionLink>value;
const location = <vscode.Location>value;
return {
origin: definitionLink.originSelectionRange
originSelectionRange: definitionLink.originSelectionRange
? Range.from(definitionLink.originSelectionRange)
: undefined,
uri: definitionLink.targetUri ? definitionLink.targetUri : location.uri,
range: Range.from(definitionLink.targetRange ? definitionLink.targetRange : location.range),
selectionRange: definitionLink.targetSelectionRange
targetSelectionRange: definitionLink.targetSelectionRange
? Range.from(definitionLink.targetSelectionRange)
: undefined,
};
@@ -835,6 +835,30 @@ export namespace Color {
}
}
export namespace SelectionRangeKind {
export function from(kind: vscode.SelectionRangeKind): string {
return kind.value;
}
export function to(value: string): vscode.SelectionRangeKind {
return new types.SelectionRangeKind(value);
}
}
export namespace SelectionRange {
export function from(obj: vscode.SelectionRange): modes.SelectionRange {
return {
kind: SelectionRangeKind.from(obj.kind),
range: Range.from(obj.range)
};
}
export function to(obj: modes.SelectionRange): vscode.SelectionRange {
return new types.SelectionRange(Range.to(obj.range), SelectionRangeKind.to(obj.kind));
}
}
export namespace TextDocumentSaveReason {
export function to(reason: SaveReason): vscode.TextDocumentSaveReason {
@@ -905,7 +929,7 @@ export namespace FoldingRangeKind {
return modes.FoldingRangeKind.Region;
}
}
return void 0;
return undefined;
}
}
@@ -984,8 +1008,6 @@ export namespace LogLevel {
return _MainLogLevel.Error;
case types.LogLevel.Critical:
return _MainLogLevel.Critical;
case types.LogLevel.Critical:
return _MainLogLevel.Critical;
case types.LogLevel.Off:
return _MainLogLevel.Off;
}
@@ -1007,8 +1029,6 @@ export namespace LogLevel {
return types.LogLevel.Error;
case _MainLogLevel.Critical:
return types.LogLevel.Critical;
case _MainLogLevel.Critical:
return types.LogLevel.Critical;
case _MainLogLevel.Off:
return types.LogLevel.Off;
}

View File

@@ -4,17 +4,17 @@
*--------------------------------------------------------------------------------------------*/
import * as crypto from 'crypto';
import { URI } from 'vs/base/common/uri';
import { illegalArgument } from 'vs/base/common/errors';
import * as vscode from 'vscode';
import { isMarkdownString } from 'vs/base/common/htmlContent';
import { IRelativePattern } from 'vs/base/common/glob';
import { relative } from 'path';
import { startsWith } from 'vs/base/common/strings';
import { values } from 'vs/base/common/map';
import { coalesce, equals } from 'vs/base/common/arrays';
import { illegalArgument } from 'vs/base/common/errors';
import { IRelativePattern } from 'vs/base/common/glob';
import { isMarkdownString } from 'vs/base/common/htmlContent';
import { values } from 'vs/base/common/map';
import { startsWith } from 'vs/base/common/strings';
import { URI } from 'vs/base/common/uri';
import { generateUuid } from 'vs/base/common/uuid';
import * as vscode from 'vscode';
export class Disposable {
@@ -32,9 +32,9 @@ export class Disposable {
});
}
private _callOnDispose?: Function;
private _callOnDispose?: () => any;
constructor(callOnDispose: Function) {
constructor(callOnDispose: () => any) {
this._callOnDispose = callOnDispose;
}
@@ -1000,7 +1000,7 @@ export class CodeAction {
edit?: WorkspaceEdit;
dianostics?: Diagnostic[];
diagnostics?: Diagnostic[];
kind?: CodeActionKind;
@@ -1022,6 +1022,7 @@ export class CodeActionKind {
public static readonly RefactorRewrite = CodeActionKind.Refactor.append('rewrite');
public static readonly Source = CodeActionKind.Empty.append('source');
public static readonly SourceOrganizeImports = CodeActionKind.Source.append('organizeImports');
public static readonly SourceFixAll = CodeActionKind.Source.append('fixAll');
constructor(
public readonly value: string
@@ -1031,11 +1032,45 @@ export class CodeActionKind {
return new CodeActionKind(this.value ? this.value + CodeActionKind.sep + parts : parts);
}
public intersects(other: CodeActionKind): boolean {
return this.contains(other) || other.contains(this);
}
public contains(other: CodeActionKind): boolean {
return this.value === other.value || startsWith(other.value, this.value + CodeActionKind.sep);
}
}
export class SelectionRangeKind {
private static readonly _sep = '.';
static readonly Empty = new SelectionRangeKind('');
static readonly Statement = SelectionRangeKind.Empty.append('statement');
static readonly Declaration = SelectionRangeKind.Empty.append('declaration');
readonly value: string;
constructor(value: string) {
this.value = value;
}
append(value: string): SelectionRangeKind {
return new SelectionRangeKind(this.value ? this.value + SelectionRangeKind._sep + value : value);
}
}
export class SelectionRange {
kind: SelectionRangeKind;
range: Range;
constructor(range: Range, kind: SelectionRangeKind, ) {
this.range = range;
this.kind = kind;
}
}
export class CodeLens {
@@ -1436,7 +1471,7 @@ export class ProcessExecution implements vscode.ProcessExecution {
throw illegalArgument('process');
}
this._process = process;
if (varg1 !== void 0) {
if (varg1 !== undefined) {
if (Array.isArray(varg1)) {
this._args = varg1;
this._options = varg2;
@@ -1444,7 +1479,7 @@ export class ProcessExecution implements vscode.ProcessExecution {
this._options = varg1;
}
}
if (this._args === void 0) {
if (this._args === undefined) {
this._args = [];
}
}
@@ -1483,7 +1518,7 @@ export class ProcessExecution implements vscode.ProcessExecution {
public computeId(): string {
const hash = crypto.createHash('md5');
hash.update('process');
if (this._process !== void 0) {
if (this._process !== undefined) {
hash.update(this._process);
}
if (this._args && this._args.length > 0) {
@@ -1565,10 +1600,10 @@ export class ShellExecution implements vscode.ShellExecution {
public computeId(): string {
const hash = crypto.createHash('md5');
hash.update('shell');
if (this._commandLine !== void 0) {
if (this._commandLine !== undefined) {
hash.update(this._commandLine);
}
if (this._command !== void 0) {
if (this._command !== undefined) {
hash.update(typeof this._command === 'string' ? this._command : this._command.value);
}
if (this._args && this._args.length > 0) {
@@ -1658,7 +1693,7 @@ export class Task implements vscode.Task {
}
private clear(): void {
if (this.__id === void 0) {
if (this.__id === undefined) {
return;
}
this.__id = undefined;
@@ -1690,7 +1725,7 @@ export class Task implements vscode.Task {
}
set definition(value: vscode.TaskDefinition) {
if (value === void 0 || value === null) {
if (value === undefined || value === null) {
throw illegalArgument('Kind can\'t be undefined or null');
}
this.clear();

View File

@@ -8,6 +8,7 @@ import { MainContext, IMainContext, ExtHostUrlsShape, MainThreadUrlsShape } from
import { URI, UriComponents } from 'vs/base/common/uri';
import { toDisposable } from 'vs/base/common/lifecycle';
import { onUnexpectedError } from 'vs/base/common/errors';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
export class ExtHostUrls implements ExtHostUrlsShape {
@@ -23,28 +24,28 @@ export class ExtHostUrls implements ExtHostUrlsShape {
this._proxy = mainContext.getProxy(MainContext.MainThreadUrls);
}
registerUriHandler(extensionId: string, handler: vscode.UriHandler): vscode.Disposable {
if (this.handles.has(extensionId)) {
registerUriHandler(extensionId: ExtensionIdentifier, handler: vscode.UriHandler): vscode.Disposable {
if (this.handles.has(ExtensionIdentifier.toKey(extensionId))) {
throw new Error(`Protocol handler already registered for extension ${extensionId}`);
}
const handle = ExtHostUrls.HandlePool++;
this.handles.add(extensionId);
this.handles.add(ExtensionIdentifier.toKey(extensionId));
this.handlers.set(handle, handler);
this._proxy.$registerUriHandler(handle, extensionId);
return toDisposable(() => {
this.handles.delete(extensionId);
this.handles.delete(ExtensionIdentifier.toKey(extensionId));
this.handlers.delete(handle);
this._proxy.$unregisterUriHandler(handle);
});
}
$handleExternalUri(handle: number, uri: UriComponents): Thenable<void> {
$handleExternalUri(handle: number, uri: UriComponents): Promise<void> {
const handler = this.handlers.get(handle);
if (!handler) {
return Promise.resolve(null);
return Promise.resolve(undefined);
}
try {
handler.handleUri(URI.revive(uri));
@@ -52,6 +53,6 @@ export class ExtHostUrls implements ExtHostUrlsShape {
onUnexpectedError(err);
}
return Promise.resolve(null);
return Promise.resolve(undefined);
}
}

View File

@@ -62,7 +62,7 @@ export class ExtHostWebview implements vscode.Webview {
this._options = newOptions;
}
public postMessage(message: any): Thenable<boolean> {
public postMessage(message: any): Promise<boolean> {
this.assertNotDisposed();
return this._proxy.$postMessage(this._handle, message);
}
@@ -171,8 +171,13 @@ export class ExtHostWebviewPanel implements vscode.WebviewPanel {
return this._options;
}
get viewColumn(): vscode.ViewColumn {
get viewColumn(): vscode.ViewColumn | undefined {
this.assertNotDisposed();
if (this._viewColumn < 0) {
// We are using a symbolic view column
// Return undefined instead to indicate that the real view column is currently unknown but will be resolved.
return undefined;
}
return this._viewColumn;
}
@@ -201,7 +206,7 @@ export class ExtHostWebviewPanel implements vscode.WebviewPanel {
this._visible = value;
}
public postMessage(message: any): Thenable<boolean> {
public postMessage(message: any): Promise<boolean> {
this.assertNotDisposed();
return this._proxy.$postMessage(this._handle, message);
}
@@ -252,7 +257,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
};
const handle = ExtHostWebviews.newHandle();
this._proxy.$createWebviewPanel(handle, viewType, title, webviewShowOptions, options, extension.id, extension.extensionLocation);
this._proxy.$createWebviewPanel(handle, viewType, title, webviewShowOptions, options, extension.identifier, extension.extensionLocation);
const webview = new ExtHostWebview(handle, this._proxy, options);
const panel = new ExtHostWebviewPanel(handle, this._proxy, viewType, title, viewColumn, options, webview);
@@ -305,13 +310,13 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
}
}
$onDidDisposeWebviewPanel(handle: WebviewPanelHandle): Thenable<void> {
$onDidDisposeWebviewPanel(handle: WebviewPanelHandle): Promise<void> {
const panel = this.getWebviewPanel(handle);
if (panel) {
panel.dispose();
this._webviewPanels.delete(handle);
}
return Promise.resolve(void 0);
return Promise.resolve(undefined);
}
$deserializeWebviewPanel(
@@ -321,7 +326,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
state: any,
position: EditorViewColumn,
options: vscode.WebviewOptions & vscode.WebviewPanelOptions
): Thenable<void> {
): Promise<void> {
const serializer = this._serializers.get(viewType);
if (!serializer) {
return Promise.reject(new Error(`No serializer found for '${viewType}'`));
@@ -330,7 +335,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
const webview = new ExtHostWebview(webviewHandle, this._proxy, options);
const revivedPanel = new ExtHostWebviewPanel(webviewHandle, this._proxy, viewType, title, typeConverters.ViewColumn.to(position), options, webview);
this._webviewPanels.set(webviewHandle, revivedPanel);
return serializer.deserializeWebviewPanel(revivedPanel, state);
return Promise.resolve(serializer.deserializeWebviewPanel(revivedPanel, state));
}
private getWebviewPanel(handle: WebviewPanelHandle): ExtHostWebviewPanel | undefined {

View File

@@ -6,6 +6,9 @@
import { Event, Emitter } from 'vs/base/common/event';
import { ExtHostWindowShape, MainContext, MainThreadWindowShape, IMainContext } from './extHost.protocol';
import { WindowState } from 'vscode';
import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
import { isFalsyOrWhitespace } from 'vs/base/common/strings';
export class ExtHostWindow implements ExtHostWindowShape {
@@ -34,4 +37,13 @@ export class ExtHostWindow implements ExtHostWindowShape {
this._state = { ...this._state, focused };
this._onDidChangeWindowState.fire(this._state);
}
openUri(uri: URI): Promise<boolean> {
if (isFalsyOrWhitespace(uri.scheme)) {
return Promise.reject('Invalid scheme - cannot be empty');
} else if (uri.scheme === Schemas.command) {
return Promise.reject(`Invalid scheme '${uri.scheme}'`);
}
return this._proxy.$openUri(uri);
}
}

View File

@@ -24,6 +24,7 @@ import { ITextQueryBuilderOptions } from 'vs/workbench/parts/search/common/query
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import * as vscode from 'vscode';
import { ExtHostWorkspaceShape, IMainContext, IWorkspaceData, MainContext, MainThreadMessageServiceShape, MainThreadWorkspaceShape } from './extHost.protocol';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
function isFolderEqual(folderA: URI, folderB: URI): boolean {
return isEqual(folderA, folderB, !isLinux);
@@ -232,7 +233,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
// Trigger on main side
if (this._proxy) {
const extName = extension.displayName || extension.name;
this._proxy.$updateWorkspaceFolders(extName, index, deleteCount, validatedDistinctWorkspaceFoldersToAdd).then(null, error => {
this._proxy.$updateWorkspaceFolders(extName, index, deleteCount, validatedDistinctWorkspaceFoldersToAdd).then(undefined, error => {
// in case of an error, make sure to clear out the unconfirmed workspace
// because we cannot expect the acknowledgement from the main side for this
@@ -345,8 +346,8 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
// --- search ---
findFiles(include: string | RelativePattern, exclude: vscode.GlobPattern, maxResults: number, extensionId: string, token: vscode.CancellationToken = CancellationToken.None): Thenable<vscode.Uri[]> {
this._logService.trace(`extHostWorkspace#findFiles: fileSearch, extension: ${extensionId}, entryPoint: findFiles`);
findFiles(include: string | RelativePattern, exclude: vscode.GlobPattern, maxResults: number, extensionId: ExtensionIdentifier, token: vscode.CancellationToken = CancellationToken.None): Promise<vscode.Uri[]> {
this._logService.trace(`extHostWorkspace#findFiles: fileSearch, extension: ${extensionId.value}, entryPoint: findFiles`);
let includePattern: string;
let includeFolder: URI;
@@ -380,8 +381,8 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
.then(data => Array.isArray(data) ? data.map(URI.revive) : []);
}
findTextInFiles(query: vscode.TextSearchQuery, options: vscode.FindTextInFilesOptions, callback: (result: vscode.TextSearchResult) => void, extensionId: string, token: vscode.CancellationToken = CancellationToken.None): Thenable<vscode.TextSearchComplete> {
this._logService.trace(`extHostWorkspace#findTextInFiles: textSearch, extension: ${extensionId}, entryPoint: findTextInFiles`);
findTextInFiles(query: vscode.TextSearchQuery, options: vscode.FindTextInFilesOptions, callback: (result: vscode.TextSearchResult) => void, extensionId: ExtensionIdentifier, token: vscode.CancellationToken = CancellationToken.None): Promise<vscode.TextSearchComplete> {
this._logService.trace(`extHostWorkspace#findTextInFiles: textSearch, extension: ${extensionId.value}, entryPoint: findTextInFiles`);
const requestId = this._requestIdProvider.getNext();
@@ -466,11 +467,11 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
}
}
saveAll(includeUntitled?: boolean): Thenable<boolean> {
saveAll(includeUntitled?: boolean): Promise<boolean> {
return this._proxy.$saveAll(includeUntitled);
}
resolveProxy(url: string): Thenable<string> {
resolveProxy(url: string): Promise<string> {
return this._proxy.$resolveProxy(url);
}
}

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { UriComponents } from 'vs/base/common/uri';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
export interface TaskDefinitionDTO {
type: string;
@@ -17,6 +18,7 @@ export interface TaskPresentationOptionsDTO {
panel?: number;
showReuseMessage?: boolean;
clear?: boolean;
group?: string;
}
export interface RunOptionsDTO {
@@ -60,7 +62,7 @@ export interface ShellQuotedStringDTO {
export interface ShellExecutionDTO {
commandLine?: string;
command?: string | ShellQuotedStringDTO;
args?: (string | ShellQuotedStringDTO)[];
args?: Array<string | ShellQuotedStringDTO>;
options?: ShellExecutionOptionsDTO;
}
@@ -89,6 +91,11 @@ export interface TaskDTO {
runOptions: RunOptionsDTO;
}
export interface TaskSetDTO {
tasks: TaskDTO[];
extension: IExtensionDescription;
}
export interface TaskExecutionDTO {
id: string;
task: TaskDTO;