Merge remote-tracking branch 'upstream/master' into rmacfarlane/review

This commit is contained in:
Peng Lyu
2018-06-04 11:14:31 -07:00
1466 changed files with 34753 additions and 22881 deletions

View File

@@ -17,7 +17,6 @@ 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 { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
@@ -29,7 +28,8 @@ 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';
export interface IUserFriendlyViewsContainerDescriptor {
id: string;
@@ -80,12 +80,11 @@ class ViewsContainersExtensionHandler implements IWorkbenchContribution {
}
private registerTestViewContainer(): void {
const id = 'test';
const title = localize('test', "Test");
const cssClass = `extensionViewlet-${id}`;
const cssClass = `extensionViewlet-test`;
const icon = require.toUrl('./media/test.svg');
this.registerCustomViewlet({ id, title, icon }, TEST_VIEW_CONTAINER_ORDER, cssClass);
this.registerCustomViewlet({ id: ViewLocation.TEST.id, title, icon }, TEST_VIEW_CONTAINER_ORDER, cssClass);
}
private handleAndRegisterCustomViewContainers() {
@@ -139,13 +138,13 @@ class ViewsContainersExtensionHandler implements IWorkbenchContribution {
const cssClass = `extensionViewlet-${descriptor.id}`;
// TODO@extensionLocation
const icon = join(extension.extensionLocation.fsPath, descriptor.icon);
this.registerCustomViewlet({ id: descriptor.id, title: descriptor.title, icon }, TEST_VIEW_CONTAINER_ORDER + index + 1, cssClass);
this.registerCustomViewlet({ id: `workbench.view.extension.${descriptor.id}`, title: descriptor.title, icon }, TEST_VIEW_CONTAINER_ORDER + index + 1, cssClass);
});
}
private registerCustomViewlet(descriptor: IUserFriendlyViewsContainerDescriptor, order: number, cssClass: string): void {
const viewletRegistry = Registry.as<ViewletRegistry>(ViewletExtensions.Viewlets);
const id = `workbench.view.extension.${descriptor.id}`;
const id = descriptor.id;
if (!viewletRegistry.getViewlet(id)) {
@@ -158,7 +157,7 @@ class ViewsContainersExtensionHandler implements IWorkbenchContribution {
@ITelemetryService telemetryService: ITelemetryService,
@IWorkspaceContextService contextService: IWorkspaceContextService,
@IStorageService storageService: IStorageService,
@IWorkbenchEditorService editorService: IWorkbenchEditorService,
@IEditorService editorService: IEditorService,
@IInstantiationService instantiationService: IInstantiationService,
@IContextKeyService contextKeyService: IContextKeyService,
@IThemeService themeService: IThemeService,
@@ -184,9 +183,9 @@ class ViewsContainersExtensionHandler implements IWorkbenchContribution {
constructor(
id: string, label: string,
@IViewletService viewletService: IViewletService,
@IWorkbenchEditorService editorService: IWorkbenchEditorService
@IEditorGroupsService editorGroupService: IEditorGroupsService
) {
super(id, label, id, viewletService, editorService);
super(id, label, id, viewletService, editorGroupService);
}
}
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
@@ -205,4 +204,4 @@ class ViewsContainersExtensionHandler implements IWorkbenchContribution {
}
const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
workbenchRegistry.registerWorkbenchContribution(ViewsContainersExtensionHandler, LifecyclePhase.Starting);
workbenchRegistry.registerWorkbenchContribution(ViewsContainersExtensionHandler, LifecyclePhase.Starting);

View File

@@ -7,22 +7,150 @@
import { localize } from 'vs/nls';
import { forEach } from 'vs/base/common/collections';
import { IJSONSchema } from 'vs/base/common/jsonSchema';
import { ExtensionMessageCollector, ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { ExtensionMessageCollector, ExtensionsRegistry, IExtensionPoint } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { ViewLocation, ViewsRegistry, ICustomViewDescriptor } from 'vs/workbench/common/views';
import { CustomTreeViewPanel } from 'vs/workbench/browser/parts/views/customViewPanel';
import { CustomTreeViewPanel, CustomTreeViewer } 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';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ProgressLocation } from 'vs/platform/progress/common/progress';
namespace schema {
interface IUserFriendlyViewDescriptor {
id: string;
name: string;
when?: string;
}
export interface IUserFriendlyViewDescriptor {
id: string;
name: string;
when?: string;
const viewDescriptor: IJSONSchema = {
type: 'object',
properties: {
id: {
description: localize('vscode.extension.contributes.view.id', 'Identifier of the view. Use this to register a data provider through `vscode.window.registerTreeDataProviderForView` API. Also to trigger activating your extension by registering `onView:${id}` event to `activationEvents`.'),
type: 'string'
},
name: {
description: localize('vscode.extension.contributes.view.name', 'The human-readable name of the view. Will be shown'),
type: 'string'
},
when: {
description: localize('vscode.extension.contributes.view.when', 'Condition which must be true to show this view'),
type: 'string'
},
}
};
const viewsContribution: IJSONSchema = {
description: localize('vscode.extension.contributes.views', "Contributes views to the editor"),
type: 'object',
properties: {
'explorer': {
description: localize('views.explorer', "Contributes views to Explorer container in the Activity bar"),
type: 'array',
items: viewDescriptor,
default: []
},
'debug': {
description: localize('views.debug', "Contributes views to Debug container in the Activity bar"),
type: 'array',
items: viewDescriptor,
default: []
},
'scm': {
description: localize('views.scm', "Contributes views to SCM container in the Activity bar"),
type: 'array',
items: viewDescriptor,
default: []
},
'test': {
description: localize('views.test', "Contributes views to Test container in the Activity bar"),
type: 'array',
items: viewDescriptor,
default: []
}
},
additionalProperties: {
description: localize('views.contributed', "Contributes views to contributed views container"),
type: 'array',
items: viewDescriptor,
default: []
}
};
const viewsExtensionPoint: IExtensionPoint<{ [loc: string]: IUserFriendlyViewDescriptor[] }> = ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: IUserFriendlyViewDescriptor[] }>('views', [viewsContainersExtensionPoint], viewsContribution);
class ViewsContainersExtensionHandler implements IWorkbenchContribution {
constructor(
@IInstantiationService private instantiationService: IInstantiationService
) {
this.handleAndRegisterCustomViews();
}
export function isValidViewDescriptors(viewDescriptors: IUserFriendlyViewDescriptor[], collector: ExtensionMessageCollector): boolean {
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 location = this.getViewLocation(entry.key);
if (!location) {
collector.warn(localize('ViewContainerDoesnotExist', "View container '{0}' does not exist and all views registered to it will be added to 'Explorer'.", entry.key));
location = ViewLocation.Explorer;
}
const registeredViews = ViewsRegistry.getViews(location);
const viewIds = [];
const viewDescriptors = coalesce(entry.value.map(item => {
// validate
if (viewIds.indexOf(item.id) !== -1) {
collector.error(localize('duplicateView1', "Cannot register multiple views with same id `{0}` in the location `{1}`", item.id, location.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 location `{1}`", item.id, location.id));
return null;
}
const viewDescriptor = <ICustomViewDescriptor>{
id: item.id,
name: item.name,
ctor: CustomTreeViewPanel,
location,
when: ContextKeyExpr.deserialize(item.when),
canToggleVisibility: true,
collapsed: this.showCollapsed(location),
treeViewer: this.instantiationService.createInstance(CustomTreeViewer, item.id, this.getProgressLocation(location))
};
viewIds.push(viewDescriptor.id);
return viewDescriptor;
}));
ViewsRegistry.registerViews(viewDescriptors);
});
}
});
}
private getProgressLocation(location: ViewLocation): ProgressLocation {
switch (location.id) {
case ViewLocation.Explorer.id:
return ProgressLocation.Explorer;
case ViewLocation.SCM.id:
return ProgressLocation.Scm;
case ViewLocation.Debug.id:
return null /* No debug progress location yet */;
}
return null;
}
private isValidViewDescriptors(viewDescriptors: IUserFriendlyViewDescriptor[], collector: ExtensionMessageCollector): boolean {
if (!Array.isArray(viewDescriptors)) {
collector.error(localize('requirearray', "views must be an array"));
return false;
@@ -46,114 +174,26 @@ namespace schema {
return true;
}
const viewDescriptor: IJSONSchema = {
type: 'object',
properties: {
id: {
description: localize('vscode.extension.contributes.view.id', 'Identifier of the view. Use this to register a data provider through `vscode.window.registerTreeDataProviderForView` API. Also to trigger activating your extension by registering `onView:${id}` event to `activationEvents`.'),
type: 'string'
},
name: {
description: localize('vscode.extension.contributes.view.name', 'The human-readable name of the view. Will be shown'),
type: 'string'
},
when: {
description: localize('vscode.extension.contributes.view.when', 'Condition which must be true to show this view'),
type: 'string'
},
}
};
export const viewsContribution: IJSONSchema = {
description: localize('vscode.extension.contributes.views', "Contributes views to the editor"),
type: 'object',
properties: {
'explorer': {
description: localize('views.explorer', "Contributes views to Explorer container in the Activity bar"),
type: 'array',
items: viewDescriptor,
default: []
},
'debug': {
description: localize('views.debug', "Contributes views to Debug container in the Activity bar"),
type: 'array',
items: viewDescriptor,
default: []
},
'scm': {
description: localize('views.scm', "Contributes views to SCM container in the Activity bar"),
type: 'array',
items: viewDescriptor,
default: []
},
'test': {
description: localize('views.test', "Contributes views to Test container in the Activity bar"),
type: 'array',
items: viewDescriptor,
default: []
}
},
additionalProperties: {
description: localize('views.contributed', "Contributes views to contributed views container"),
type: 'array',
items: viewDescriptor,
default: []
private getViewLocation(value: string): ViewLocation {
switch (value) {
case 'explorer': return ViewLocation.Explorer;
case 'debug': return ViewLocation.Debug;
case 'scm': return ViewLocation.SCM;
default: return ViewLocation.get(`workbench.view.extension.${value}`);
}
};
}
}
function getViewLocation(value: string): ViewLocation {
switch (value) {
case 'explorer': return ViewLocation.Explorer;
case 'debug': return ViewLocation.Debug;
case 'scm': return ViewLocation.SCM;
default: return ViewLocation.get(`workbench.view.extension.${value}`);
private showCollapsed(location: ViewLocation): boolean {
switch (location) {
case ViewLocation.Explorer:
case ViewLocation.SCM:
case ViewLocation.Debug:
return true;
}
return false;
}
}
ExtensionsRegistry.registerExtensionPoint<{ [loc: string]: schema.IUserFriendlyViewDescriptor[] }>('views', [viewsContainersExtensionPoint], schema.viewsContribution)
.setHandler((extensions) => {
for (let extension of extensions) {
const { value, collector } = extension;
forEach(value, entry => {
if (!schema.isValidViewDescriptors(entry.value, collector)) {
return;
}
let location = getViewLocation(entry.key);
if (!location) {
collector.warn(localize('ViewContainerDoesnotExist', "View container '{0}' does not exist and all views registered to it will be added to 'Explorer'.", entry.key));
location = ViewLocation.Explorer;
}
const registeredViews = ViewsRegistry.getViews(location);
const viewIds = [];
const viewDescriptors = coalesce(entry.value.map(item => {
const viewDescriptor = <ICustomViewDescriptor>{
id: item.id,
name: item.name,
ctor: CustomTreeViewPanel,
location,
when: ContextKeyExpr.deserialize(item.when),
canToggleVisibility: true,
collapsed: true,
treeView: true
};
// validate
if (viewIds.indexOf(viewDescriptor.id) !== -1) {
collector.error(localize('duplicateView1', "Cannot register multiple views with same id `{0}` in the location `{1}`", viewDescriptor.id, viewDescriptor.location.id));
return null;
}
if (registeredViews.some(v => v.id === viewDescriptor.id)) {
collector.error(localize('duplicateView2', "A view with id `{0}` is already registered in the location `{1}`", viewDescriptor.id, viewDescriptor.location.id));
return null;
}
viewIds.push(viewDescriptor.id);
return viewDescriptor;
}));
ViewsRegistry.registerViews(viewDescriptors);
});
}
});
const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
workbenchRegistry.registerWorkbenchContribution(ViewsContainersExtensionHandler, LifecyclePhase.Starting);

View File

@@ -6,7 +6,7 @@
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import uri from 'vs/base/common/uri';
import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData, IAdapterExecutable, ITerminalSettings, IDebugAdapter, IDebugAdapterProvider } from 'vs/workbench/parts/debug/common/debug';
import { IDebugService, IConfig, IDebugConfigurationProvider, IBreakpoint, IFunctionBreakpoint, IBreakpointData, IAdapterExecutable, ITerminalSettings, IDebugAdapter, IDebugAdapterProvider, ITerminalLauncher } from 'vs/workbench/parts/debug/common/debug';
import { TPromise } from 'vs/base/common/winjs.base';
import {
ExtHostContext, ExtHostDebugServiceShape, MainThreadDebugServiceShape, DebugSessionUUID, MainContext,
@@ -18,6 +18,8 @@ import { AbstractDebugAdapter } from 'vs/workbench/parts/debug/node/debugAdapter
import * as paths from 'vs/base/common/paths';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { convertToVSCPaths, convertToDAPaths } from 'vs/workbench/parts/debug/common/debugUtils';
import { ITerminalService } from 'vs/workbench/parts/terminal/common/terminal';
import { AbstractTerminalLauncher } from 'vs/workbench/parts/debug/electron-browser/terminalSupport';
@extHostNamedCustomer(MainContext.MainThreadDebugService)
@@ -28,11 +30,13 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
private _breakpointEventsActive: boolean;
private _debugAdapters: Map<number, ExtensionHostDebugAdapter>;
private _debugAdaptersHandleCounter = 1;
private _terminalLauncher: ITerminalLauncher;
constructor(
extHostContext: IExtHostContext,
@IDebugService private debugService: IDebugService
@IDebugService private debugService: IDebugService,
@ITerminalService private terminalService: ITerminalService,
) {
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostDebugService);
this._toDispose = [];
@@ -73,7 +77,10 @@ export class MainThreadDebugService implements MainThreadDebugServiceShape, IDeb
}
runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise<void> {
return this._proxy.$runInTerminal(args, config);
if (!this._terminalLauncher) {
this._terminalLauncher = new ExtensionTerminalLauncher(this.terminalService, this._proxy);
}
return this._terminalLauncher.runInTerminal(args, config);
}
public dispose(): void {
@@ -295,3 +302,25 @@ class ExtensionHostDebugAdapter extends AbstractDebugAdapter {
return this._proxy.$stopDASession(this._handle);
}
}
export class ExtensionTerminalLauncher extends AbstractTerminalLauncher {
constructor(
@ITerminalService terminalService: ITerminalService,
private _proxy: ExtHostDebugServiceShape
) {
super(terminalService);
}
protected runInExternalTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise<void> {
return this._proxy.$runInTerminal(args, config);
}
protected isBusy(processId: number): TPromise<boolean> {
return this._proxy.$isTerminalBusy(processId);
}
protected prepareCommand(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise<any> {
return this._proxy.$prepareCommandForTerminal(args, config);
}
}

View File

@@ -9,7 +9,6 @@ import { IDisposable } from 'vs/base/common/lifecycle';
import { TPromise } from 'vs/base/common/winjs.base';
import { ITextModel, DefaultEndOfLine } from 'vs/editor/common/model';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
import { MainThreadDocumentContentProvidersShape, ExtHostContext, ExtHostDocumentContentProvidersShape, MainContext, IExtHostContext } from '../node/extHost.protocol';
import { createTextBuffer } from 'vs/editor/common/model/textModel';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
@@ -28,8 +27,7 @@ export class MainThreadDocumentContentProviders implements MainThreadDocumentCon
@ITextModelService private readonly _textModelResolverService: ITextModelService,
@IModeService private readonly _modeService: IModeService,
@IModelService private readonly _modelService: IModelService,
@ICodeEditorService codeEditorService: ICodeEditorService,
@IEditorGroupService editorGroupService: IEditorGroupService
@ICodeEditorService codeEditorService: ICodeEditorService
) {
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostDocumentContentProviders);
}

View File

@@ -10,7 +10,7 @@ import { IModelService, shouldSynchronizeModel } from 'vs/editor/common/services
import { IDisposable, dispose, IReference } from 'vs/base/common/lifecycle';
import { TextFileModelChangeEvent, ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { TPromise } from 'vs/base/common/winjs.base';
import { IFileService } from 'vs/platform/files/common/files';
import { IFileService, FileOperation } from 'vs/platform/files/common/files';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { ExtHostContext, MainThreadDocumentsShape, ExtHostDocumentsShape, IExtHostContext } from '../node/extHost.protocol';
@@ -119,6 +119,12 @@ export class MainThreadDocuments implements MainThreadDocumentsShape {
}
}));
this._toDispose.push(fileService.onAfterOperation(e => {
if (e.operation === FileOperation.MOVE) {
this._proxy.$onDidRename(e.resource, e.target.resource);
}
}));
this._modelToDisposeMap = Object.create(null);
}

View File

@@ -12,8 +12,9 @@ import { Event, Emitter } from 'vs/base/common/event';
import { ExtHostContext, ExtHostDocumentsAndEditorsShape, IModelAddedData, ITextEditorAddData, IDocumentsAndEditorsDelta, IExtHostContext, MainContext } from '../node/extHost.protocol';
import { MainThreadTextEditor } from './mainThreadEditor';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { Position as EditorPosition, IEditor } from 'vs/platform/editor/common/editor';
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
import { EditorViewColumn, editorGroupToViewColumn } from 'vs/workbench/api/shared/editor';
import { IEditor } from 'vs/workbench/common/editor';
import { extHostCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import { MainThreadDocuments } from 'vs/workbench/api/electron-browser/mainThreadDocuments';
import { MainThreadTextEditors } from 'vs/workbench/api/electron-browser/mainThreadEditors';
@@ -21,8 +22,8 @@ import { IModeService } from 'vs/editor/common/services/modeService';
import { IFileService } from 'vs/platform/files/common/files';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
import { isCodeEditor, isDiffEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { isDiffEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser';
import URI from 'vs/base/common/uri';
import { IBulkEditService } from 'vs/editor/browser/services/bulkEditService';
@@ -160,7 +161,7 @@ class MainThreadDocumentAndEditorStateComputer {
private readonly _onDidChangeState: (delta: DocumentAndEditorStateDelta) => void,
@IModelService private readonly _modelService: IModelService,
@ICodeEditorService private readonly _codeEditorService: ICodeEditorService,
@IWorkbenchEditorService private readonly _workbenchEditorService: IWorkbenchEditorService
@IEditorService private readonly _editorService: IEditorService
) {
this._modelService.onModelAdded(this._updateStateOnModelAdd, this, this._toDispose);
this._modelService.onModelRemoved(this._updateState, this, this._toDispose);
@@ -251,25 +252,19 @@ class MainThreadDocumentAndEditorStateComputer {
}
// active editor: if none of the previous editors had focus we try
// to match the action workbench editor with one of editor we have
// to match the active workbench editor with one of editor we have
// just computed
if (!activeEditor) {
const workbenchEditor = this._workbenchEditorService.getActiveEditor();
if (workbenchEditor) {
const workbenchEditorControl = workbenchEditor.getControl();
let candidate: ICodeEditor;
if (isCodeEditor(workbenchEditorControl)) {
candidate = workbenchEditorControl;
} else if (isDiffEditor(workbenchEditorControl)) {
candidate = workbenchEditorControl.getModifiedEditor();
}
if (candidate) {
editors.forEach(snapshot => {
if (candidate === snapshot.editor) {
activeEditor = snapshot.id;
}
});
}
let candidate = this._editorService.activeTextEditorWidget;
if (isDiffEditor(candidate)) {
candidate = candidate.getModifiedEditor();
}
if (candidate) {
editors.forEach(snapshot => {
if (candidate === snapshot.editor) {
activeEditor = snapshot.id;
}
});
}
}
@@ -305,14 +300,14 @@ export class MainThreadDocumentsAndEditors {
extHostContext: IExtHostContext,
@IModelService private readonly _modelService: IModelService,
@ITextFileService private readonly _textFileService: ITextFileService,
@IWorkbenchEditorService private readonly _workbenchEditorService: IWorkbenchEditorService,
@IEditorService private readonly _editorService: IEditorService,
@ICodeEditorService codeEditorService: ICodeEditorService,
@IModeService modeService: IModeService,
@IFileService fileService: IFileService,
@ITextModelService textModelResolverService: ITextModelService,
@IUntitledEditorService untitledEditorService: IUntitledEditorService,
@IEditorGroupService editorGroupService: IEditorGroupService,
@IBulkEditService bulkEditService: IBulkEditService,
@IEditorGroupsService private readonly _editorGroupService: IEditorGroupsService,
@IBulkEditService bulkEditService: IBulkEditService
) {
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostDocumentsAndEditors);
@@ -320,11 +315,11 @@ export class MainThreadDocumentsAndEditors {
const mainThreadDocuments = new MainThreadDocuments(this, extHostContext, this._modelService, modeService, this._textFileService, fileService, textModelResolverService, untitledEditorService);
extHostContext.set(MainContext.MainThreadDocuments, mainThreadDocuments);
const mainThreadTextEditors = new MainThreadTextEditors(this, extHostContext, codeEditorService, bulkEditService, this._workbenchEditorService, editorGroupService);
const mainThreadTextEditors = new MainThreadTextEditors(this, extHostContext, codeEditorService, bulkEditService, this._editorService, this._editorGroupService);
extHostContext.set(MainContext.MainThreadTextEditors, mainThreadTextEditors);
// It is expected that the ctor of the state computer calls our `_onDelta`.
this._stateComputer = new MainThreadDocumentAndEditorStateComputer(delta => this._onDelta(delta), _modelService, codeEditorService, _workbenchEditorService);
this._stateComputer = new MainThreadDocumentAndEditorStateComputer(delta => this._onDelta(delta), _modelService, codeEditorService, this._editorService);
this._toDispose = [
mainThreadDocuments,
@@ -426,10 +421,10 @@ export class MainThreadDocumentsAndEditors {
};
}
private _findEditorPosition(editor: MainThreadTextEditor): EditorPosition {
for (let workbenchEditor of this._workbenchEditorService.getVisibleEditors()) {
private _findEditorPosition(editor: MainThreadTextEditor): EditorViewColumn {
for (let workbenchEditor of this._editorService.visibleControls) {
if (editor.matches(workbenchEditor)) {
return workbenchEditor.position;
return editorGroupToViewColumn(this._editorGroupService, workbenchEditor.group);
}
}
return undefined;

View File

@@ -6,7 +6,7 @@
import * as editorCommon from 'vs/editor/common/editorCommon';
import { Event, Emitter } from 'vs/base/common/event';
import { IEditor } from 'vs/platform/editor/common/editor';
import { IEditor } from 'vs/workbench/common/editor';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { Range, IRange } from 'vs/editor/common/core/range';

View File

@@ -4,6 +4,9 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IEditorOptions, ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { localize } from 'vs/nls';
import { disposed } from 'vs/base/common/errors';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { equals as objectEquals } from 'vs/base/common/objects';
@@ -15,10 +18,11 @@ import { IRange } from 'vs/editor/common/core/range';
import { ISelection } from 'vs/editor/common/core/selection';
import { IDecorationOptions, IDecorationRenderOptions, ILineChange } from 'vs/editor/common/editorCommon';
import { ISingleEditOperation } from 'vs/editor/common/model';
import { ITextEditorOptions, Position as EditorPosition } from 'vs/platform/editor/common/editor';
import { EditorViewColumn, viewColumnToEditorGroup, editorGroupToViewColumn } from 'vs/workbench/api/shared/editor';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { IApplyEditsOptions, ITextEditorConfigurationUpdate, IUndoStopOptions, TextEditorRevealType, WorkspaceEditDto, reviveWorkspaceEditDto } from 'vs/workbench/api/node/extHost.protocol';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
import { ExtHostContext, ExtHostEditorsShape, IExtHostContext, ITextDocumentShowOptions, ITextEditorPositionData, MainThreadTextEditorsShape } from '../node/extHost.protocol';
import { MainThreadDocumentsAndEditors } from './mainThreadDocumentsAndEditors';
import { MainThreadTextEditor } from './mainThreadEditor';
@@ -27,7 +31,6 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
private _proxy: ExtHostEditorsShape;
private _documentsAndEditors: MainThreadDocumentsAndEditors;
private _workbenchEditorService: IWorkbenchEditorService;
private _toDispose: IDisposable[];
private _textEditorsListenersMap: { [editorId: string]: IDisposable[]; };
private _editorPositionData: ITextEditorPositionData;
@@ -38,12 +41,11 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
extHostContext: IExtHostContext,
@ICodeEditorService private readonly _codeEditorService: ICodeEditorService,
@IBulkEditService private readonly _bulkEditService: IBulkEditService,
@IWorkbenchEditorService workbenchEditorService: IWorkbenchEditorService,
@IEditorGroupService editorGroupService: IEditorGroupService,
@IEditorService private readonly _editorService: IEditorService,
@IEditorGroupsService private readonly _editorGroupService: IEditorGroupsService
) {
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostEditors);
this._documentsAndEditors = documentsAndEditors;
this._workbenchEditorService = workbenchEditorService;
this._toDispose = [];
this._textEditorsListenersMap = Object.create(null);
this._editorPositionData = null;
@@ -51,8 +53,8 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
this._toDispose.push(documentsAndEditors.onTextEditorAdd(editors => editors.forEach(this._onTextEditorAdd, this)));
this._toDispose.push(documentsAndEditors.onTextEditorRemove(editors => editors.forEach(this._onTextEditorRemove, this)));
this._toDispose.push(editorGroupService.onEditorsChanged(() => this._updateActiveAndVisibleTextEditors()));
this._toDispose.push(editorGroupService.onEditorGroupMoved(() => this._updateActiveAndVisibleTextEditors()));
this._toDispose.push(this._editorService.onDidVisibleEditorsChange(() => this._updateActiveAndVisibleTextEditors()));
this._toDispose.push(this._editorGroupService.onDidRemoveGroup(() => this._updateActiveAndVisibleTextEditors()));
this._registeredDecorationTypes = Object.create(null);
}
@@ -96,10 +98,10 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
private _getTextEditorPositionData(): ITextEditorPositionData {
let result: ITextEditorPositionData = Object.create(null);
for (let workbenchEditor of this._workbenchEditorService.getVisibleEditors()) {
for (let workbenchEditor of this._editorService.visibleControls) {
const id = this._documentsAndEditors.findTextEditorIdFor(workbenchEditor);
if (id) {
result[id] = workbenchEditor.position;
result[id] = editorGroupToViewColumn(this._editorGroupService, workbenchEditor.group);
}
}
return result;
@@ -121,7 +123,7 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
options: editorOptions
};
return this._workbenchEditorService.openEditor(input, options.position).then(editor => {
return this._editorService.openEditor(input, viewColumnToEditorGroup(this._editorGroupService, options.position)).then(editor => {
if (!editor) {
return undefined;
}
@@ -129,14 +131,14 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
});
}
$tryShowEditor(id: string, position: EditorPosition): TPromise<void> {
$tryShowEditor(id: string, position?: EditorViewColumn): TPromise<void> {
let mainThreadEditor = this._documentsAndEditors.getEditor(id);
if (mainThreadEditor) {
let model = mainThreadEditor.getModel();
return this._workbenchEditorService.openEditor({
return this._editorService.openEditor({
resource: model.uri,
options: { preserveFocus: false }
}, position).then(() => { return; });
}, viewColumnToEditorGroup(this._editorGroupService, position)).then(() => { return; });
}
return undefined;
}
@@ -144,10 +146,10 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
$tryHideEditor(id: string): TPromise<void> {
let mainThreadEditor = this._documentsAndEditors.getEditor(id);
if (mainThreadEditor) {
let editors = this._workbenchEditorService.getVisibleEditors();
let editors = this._editorService.visibleControls;
for (let editor of editors) {
if (mainThreadEditor.matches(editor)) {
return this._workbenchEditorService.closeEditor(editor.position, editor.input).then(() => { return; });
return editor.group.closeEditor(editor.input).then(() => { return; });
}
}
}
@@ -242,3 +244,33 @@ export class MainThreadTextEditors implements MainThreadTextEditorsShape {
return TPromise.as(diffEditor.getLineChanges());
}
}
// --- commands
CommandsRegistry.registerCommand('_workbench.open', function (accessor: ServicesAccessor, args: [URI, IEditorOptions, EditorViewColumn]) {
const editorService = accessor.get(IEditorService);
const editorGroupService = accessor.get(IEditorGroupsService);
const [resource, options, position] = args;
return editorService.openEditor({ resource, options }, viewColumnToEditorGroup(editorGroupService, position)).then(() => void 0);
});
CommandsRegistry.registerCommand('_workbench.diff', function (accessor: ServicesAccessor, args: [URI, URI, string, string, IEditorOptions, EditorViewColumn]) {
const editorService = accessor.get(IEditorService);
const editorGroupService = accessor.get(IEditorGroupsService);
let [leftResource, rightResource, label, description, options, position] = args;
if (!options || typeof options !== 'object') {
options = {
preserveFocus: false
};
}
if (!label) {
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);
});

View File

@@ -307,7 +307,10 @@ class CodeActionOnParticipant implements ISaveParticipant {
}
private async getActionsToRun(model: ITextModel, codeActionsOnSave: CodeActionKind[]) {
const actions = await getCodeActions(model, model.getFullModelRange(), { kind: CodeActionKind.Source, includeSourceActions: true });
const actions = await 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;
}

View File

@@ -4,13 +4,12 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as path from 'path';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { values } from 'vs/base/common/map';
import URI, { UriComponents } from 'vs/base/common/uri';
import { PPromise, TPromise } from 'vs/base/common/winjs.base';
import { IFileMatch, ISearchComplete, ISearchProgressItem, ISearchQuery, ISearchResultProvider, ISearchService, QueryType, IRawFileMatch2, ISearchCompleteStats, IFolderQuery } from 'vs/platform/search/common/search';
import { IFileMatch, ISearchComplete, ISearchProgressItem, ISearchQuery, ISearchResultProvider, ISearchService, QueryType, IRawFileMatch2, ISearchCompleteStats } from 'vs/platform/search/common/search';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import { ExtHostContext, ExtHostSearchShape, IExtHostContext, MainContext, MainThreadSearchShape } from '../node/extHost.protocol';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
@@ -58,7 +57,6 @@ class SearchOperation {
constructor(
readonly progress: (match: IFileMatch) => any,
readonly folders: IFolderQuery[],
readonly id: number = ++SearchOperation._idPool,
readonly matches = new Map<string, IFileMatch>()
) {
@@ -102,6 +100,9 @@ class RemoteSearchProvider implements ISearchResultProvider {
}
const folderQueriesForScheme = query.folderQueries.filter(fq => fq.folder.scheme === this._scheme);
if (!folderQueriesForScheme.length) {
return TPromise.wrap(null);
}
query = {
...query,
@@ -112,7 +113,7 @@ class RemoteSearchProvider implements ISearchResultProvider {
return new PPromise((resolve, reject, report) => {
const search = new SearchOperation(report, query.folderQueries);
const search = new SearchOperation(report);
this._searches.set(search.id, search);
outer = query.type === QueryType.File
@@ -142,14 +143,8 @@ class RemoteSearchProvider implements ISearchResultProvider {
const searchOp = this._searches.get(session);
if (Array.isArray(dataOrUri)) {
dataOrUri.forEach(m => {
const folderQuery = searchOp.folders[m.resource.folderIdx];
if (!folderQuery) {
return;
}
const fullUri = URI.file(path.join(folderQuery.folder.fsPath, m.resource.relativePath));
searchOp.addMatch({
resource: fullUri,
resource: URI.revive(m.resource),
lineMatches: m.lineMatches
});
});

View File

@@ -12,6 +12,7 @@ import URI from 'vs/base/common/uri';
import * as Objects from 'vs/base/common/objects';
import { TPromise } from 'vs/base/common/winjs.base';
import * as Types from 'vs/base/common/types';
import * as Platform from 'vs/base/common/platform';
import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
@@ -21,12 +22,11 @@ import {
} from 'vs/workbench/parts/tasks/common/tasks';
import { ITaskService, TaskFilter } from 'vs/workbench/parts/tasks/common/taskService';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import { ExtHostContext, MainThreadTaskShape, ExtHostTaskShape, MainContext, IExtHostContext } from 'vs/workbench/api/node/extHost.protocol';
import {
TaskDefinitionDTO, TaskExecutionDTO, ProcessExecutionOptionsDTO, TaskPresentationOptionsDTO,
ProcessExecutionDTO, ShellExecutionDTO, ShellExecutionOptionsDTO, TaskDTO, TaskSourceDTO, TaskHandleDTO, TaskFilterDTO, TaskProcessStartedDTO, TaskProcessEndedDTO
ProcessExecutionDTO, ShellExecutionDTO, ShellExecutionOptionsDTO, TaskDTO, TaskSourceDTO, TaskHandleDTO, TaskFilterDTO, TaskProcessStartedDTO, TaskProcessEndedDTO, TaskSystemInfoDTO
} from 'vs/workbench/api/shared/tasks';
export { TaskDTO, TaskHandleDTO, TaskExecutionDTO, TaskFilterDTO };
@@ -357,6 +357,7 @@ namespace TaskFilterDTO {
@extHostNamedCustomer(MainContext.MainThreadTask)
export class MainThreadTask implements MainThreadTaskShape {
private _extHostContext: IExtHostContext;
private _proxy: ExtHostTaskShape;
private _activeHandles: { [handle: number]: boolean; };
@@ -471,4 +472,35 @@ export class MainThreadTask implements MainThreadTaskShape {
});
});
}
public $registerTaskSystem(key: string, info: TaskSystemInfoDTO): void {
let platform: Platform.Platform;
switch (info.platform) {
case 'win32':
platform = Platform.Platform.Windows;
break;
case 'darwin':
platform = Platform.Platform.Mac;
break;
case 'linux':
platform = Platform.Platform.Linux;
break;
default:
platform = Platform.platform;
}
this._taskService.registerTaskSystem(key, {
platform: platform,
fileSystemScheme: key,
context: this._extHostContext,
resolveVariables: (workspaceFolder: IWorkspaceFolder, variables: Set<string>): TPromise<Map<string, string>> => {
let vars: string[] = [];
variables.forEach(item => vars.push(item));
return this._proxy.$resolveVariables(workspaceFolder.uri, vars).then(values => {
let result = new Map<string, string>();
Object.keys(values).forEach(key => result.set(key, values[key]));
return result;
});
}
});
}
}

View File

@@ -7,7 +7,7 @@
import { TPromise } from 'vs/base/common/winjs.base';
import { Disposable } from 'vs/base/common/lifecycle';
import { ExtHostContext, MainThreadTreeViewsShape, ExtHostTreeViewsShape, MainContext, IExtHostContext } from '../node/extHost.protocol';
import { ITreeViewDataProvider, ITreeItem, IViewsService, ITreeViewer } from 'vs/workbench/common/views';
import { ITreeViewDataProvider, ITreeItem, IViewsService, ITreeViewer, ViewsRegistry, ICustomViewDescriptor } 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';
@@ -30,10 +30,10 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie
$registerTreeViewDataProvider(treeViewId: string): void {
const dataProvider = new TreeViewDataProvider(treeViewId, this._proxy, this.notificationService);
this._dataProviders.set(treeViewId, dataProvider);
const treeViewer = this.viewsService.getTreeViewer(treeViewId);
if (treeViewer) {
treeViewer.dataProvider = dataProvider;
this.registerListeners(treeViewId, treeViewer);
const viewer = this.getTreeViewer(treeViewId);
if (viewer) {
viewer.dataProvider = dataProvider;
this.registerListeners(treeViewId, viewer);
} else {
this.notificationService.error('No view is registered with id: ' + treeViewId);
}
@@ -42,13 +42,13 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie
$reveal(treeViewId: string, item: ITreeItem, parentChain: ITreeItem[], options?: { select?: boolean }): TPromise<void> {
return this.viewsService.openView(treeViewId)
.then(() => {
const viewer = this.viewsService.getTreeViewer(treeViewId);
const viewer = this.getTreeViewer(treeViewId);
return viewer ? viewer.reveal(item, parentChain, options) : null;
});
}
$refresh(treeViewId: string, itemsToRefreshByHandle: { [treeItemHandle: string]: ITreeItem }): TPromise<void> {
const viewer = this.viewsService.getTreeViewer(treeViewId);
const viewer = this.getTreeViewer(treeViewId);
const dataProvider = this._dataProviders.get(treeViewId);
if (viewer && dataProvider) {
const itemsToRefresh = dataProvider.getItemsToRefresh(itemsToRefreshByHandle);
@@ -63,9 +63,14 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie
this._register(treeViewer.onDidChangeSelection(items => this._proxy.$setSelection(treeViewId, items.map(({ handle }) => handle))));
}
private getTreeViewer(treeViewId: string): ITreeViewer {
const viewDescriptor: ICustomViewDescriptor = <ICustomViewDescriptor>ViewsRegistry.getView(treeViewId);
return viewDescriptor ? viewDescriptor.treeViewer : null;
}
dispose(): void {
this._dataProviders.forEach((dataProvider, treeViewId) => {
const treeViewer = this.viewsService.getTreeViewer(treeViewId);
const treeViewer = this.getTreeViewer(treeViewId);
if (treeViewer) {
treeViewer.dataProvider = null;
}

View File

@@ -8,16 +8,16 @@ import URI, { UriComponents } from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { localize } from 'vs/nls';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { Position } from 'vs/platform/editor/common/editor';
import { EditorViewColumn, viewColumnToEditorGroup, editorGroupToViewColumn } from 'vs/workbench/api/shared/editor';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { ExtHostContext, ExtHostWebviewsShape, IExtHostContext, MainContext, MainThreadWebviewsShape, WebviewPanelHandle } from 'vs/workbench/api/node/extHost.protocol';
import { WebviewEditor } from 'vs/workbench/parts/webview/electron-browser/webviewEditor';
import { WebviewEditorInput } from 'vs/workbench/parts/webview/electron-browser/webviewEditorInput';
import { IWebviewEditorService, WebviewInputOptions, WebviewReviver } from 'vs/workbench/parts/webview/electron-browser/webviewEditorService';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IWebviewEditorService, WebviewInputOptions, WebviewReviver, ICreateWebViewShowOptions } from 'vs/workbench/parts/webview/electron-browser/webviewEditorService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IEditorGroupService } from 'vs/workbench/services/group/common/groupService';
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
import { extHostNamedCustomer } from './extHostCustomers';
@extHostNamedCustomer(MainContext.MainThreadWebviews)
@@ -40,17 +40,17 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
constructor(
context: IExtHostContext,
@IContextKeyService contextKeyService: IContextKeyService,
@IEditorGroupService editorGroupService: IEditorGroupService,
@IEditorGroupsService private readonly _editorGroupService: IEditorGroupsService,
@ILifecycleService lifecycleService: ILifecycleService,
@IWorkbenchEditorService private readonly _editorService: IWorkbenchEditorService,
@IEditorService private readonly _editorService: IEditorService,
@IWebviewEditorService private readonly _webviewService: IWebviewEditorService,
@IOpenerService private readonly _openerService: IOpenerService,
@IExtensionService private readonly _extensionService: IExtensionService,
) {
this._proxy = context.getProxy(ExtHostContext.ExtHostWebviews);
editorGroupService.onEditorsChanged(this.onEditorsChanged, this, this._toDispose);
editorGroupService.onEditorGroupMoved(this.onEditorGroupMoved, this, this._toDispose);
_editorService.onDidActiveEditorChange(this.onActiveEditorChanged, this, this._toDispose);
_editorService.onDidVisibleEditorsChange(this.onVisibleEditorsChanged, this, this._toDispose);
this._toDispose.push(_webviewService.registerReviver(MainThreadWebviews.viewType, this));
@@ -67,11 +67,20 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
handle: WebviewPanelHandle,
viewType: string,
title: string,
showOptions: { viewColumn: Position, preserveFocus: boolean },
showOptions: { viewColumn: EditorViewColumn | null, preserveFocus: boolean },
options: WebviewInputOptions,
extensionLocation: UriComponents
): void {
const webview = this._webviewService.createWebview(MainThreadWebviews.viewType, title, showOptions, options, URI.revive(extensionLocation), this.createWebviewEventDelegate(handle));
const mainThreadShowOptions: ICreateWebViewShowOptions = Object.create(null);
if (showOptions) {
mainThreadShowOptions.preserveFocus = showOptions.preserveFocus;
mainThreadShowOptions.group = viewColumnToEditorGroup(this._editorGroupService, showOptions.viewColumn);
}
const webview = this._webviewService.createWebview(MainThreadWebviews.viewType, title, mainThreadShowOptions, {
...options,
localResourceRoots: Array.isArray(options.localResourceRoots) ? options.localResourceRoots.map(URI.revive) : undefined
}, URI.revive(extensionLocation), this.createWebviewEventDelegate(handle));
webview.state = {
viewType: viewType,
state: undefined
@@ -96,18 +105,20 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
webview.html = value;
}
$reveal(handle: WebviewPanelHandle, viewColumn: Position | null, preserveFocus: boolean): void {
$reveal(handle: WebviewPanelHandle, viewColumn: EditorViewColumn | null, preserveFocus: boolean): void {
const webview = this.getWebview(handle);
if (webview.isDisposed()) {
return;
}
this._webviewService.revealWebview(webview, viewColumn, preserveFocus);
const targetGroup = this._editorGroupService.getGroup(viewColumnToEditorGroup(this._editorGroupService, viewColumn));
this._webviewService.revealWebview(webview, targetGroup || this._editorGroupService.activeGroup, preserveFocus);
}
async $postMessage(handle: WebviewPanelHandle, message: any): TPromise<boolean> {
const webview = this.getWebview(handle);
const editors = this._editorService.getVisibleEditors()
const editors = this._editorService.visibleControls
.filter(e => e instanceof WebviewEditor)
.map(e => e as WebviewEditor)
.filter(e => e.input.matches(webview));
@@ -129,19 +140,21 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
reviveWebview(webview: WebviewEditorInput): TPromise<void> {
const viewType = webview.state.viewType;
return this._extensionService.activateByEvent(`onView:${viewType}`).then(() => {
return this._extensionService.activateByEvent(`onWebviewPanel:${viewType}`).then(() => {
const handle = 'revival-' + MainThreadWebviews.revivalPool++;
this._webviews.set(handle, webview);
webview._events = this.createWebviewEventDelegate(handle);
let state;
try {
state = JSON.parse(webview.state.state);
} catch {
state = {};
let state = undefined;
if (webview.state.state) {
try {
state = JSON.parse(webview.state.state);
} catch {
// noop
}
}
return this._proxy.$deserializeWebviewPanel(handle, webview.state.viewType, webview.getTitle(), state, webview.position, webview.options)
return this._proxy.$deserializeWebviewPanel(handle, webview.state.viewType, webview.getTitle(), state, editorGroupToViewColumn(this._editorGroupService, webview.group), webview.options)
.then(undefined, () => {
webview.html = MainThreadWebviews.getDeserializationFailedContents(viewType);
});
@@ -149,11 +162,11 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
}
canRevive(webview: WebviewEditorInput): boolean {
if (webview.isDisposed()) {
if (webview.isDisposed() || !webview.state) {
return false;
}
return (this._revivers.has(webview.viewType) || webview.reviver !== null);
return this._revivers.has(webview.state.viewType) || !!webview.reviver;
}
private _onWillShutdown(): TPromise<boolean> {
@@ -187,8 +200,8 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
return webview;
}
private onEditorsChanged() {
const activeEditor = this._editorService.getActiveEditor();
private onActiveEditorChanged() {
const activeEditor = this._editorService.activeControl;
let newActiveWebview: { input: WebviewEditorInput, handle: WebviewPanelHandle } | undefined = undefined;
if (activeEditor && activeEditor.input instanceof WebviewEditorInput) {
for (const handle of map.keys(this._webviews)) {
@@ -202,7 +215,7 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
if (newActiveWebview && newActiveWebview.handle === this._activeWebview) {
// Webview itself unchanged but position may have changed
this._proxy.$onDidChangeWebviewPanelViewState(newActiveWebview.handle, true, newActiveWebview.input.position);
this._proxy.$onDidChangeWebviewPanelViewState(newActiveWebview.handle, true, editorGroupToViewColumn(this._editorGroupService, newActiveWebview.input.group));
return;
}
@@ -210,29 +223,32 @@ export class MainThreadWebviews implements MainThreadWebviewsShape, WebviewReviv
if (typeof this._activeWebview !== 'undefined') {
const oldActiveWebview = this._webviews.get(this._activeWebview);
if (oldActiveWebview) {
this._proxy.$onDidChangeWebviewPanelViewState(this._activeWebview, false, oldActiveWebview.position);
this._proxy.$onDidChangeWebviewPanelViewState(this._activeWebview, false, editorGroupToViewColumn(this._editorGroupService, oldActiveWebview.group));
}
}
// Then for newly active
if (newActiveWebview) {
this._proxy.$onDidChangeWebviewPanelViewState(newActiveWebview.handle, true, activeEditor.position);
this._proxy.$onDidChangeWebviewPanelViewState(newActiveWebview.handle, true, editorGroupToViewColumn(this._editorGroupService, activeEditor.group));
this._activeWebview = newActiveWebview.handle;
} else {
this._activeWebview = undefined;
}
}
private onEditorGroupMoved(): void {
for (const workbenchEditor of this._editorService.getVisibleEditors()) {
private onVisibleEditorsChanged(): void {
for (const workbenchEditor of this._editorService.visibleControls) {
if (!workbenchEditor.input) {
return;
}
this._webviews.forEach((input, handle) => {
if (workbenchEditor.input.matches(input) && input.position !== workbenchEditor.position) {
input.updatePosition(workbenchEditor.position);
this._proxy.$onDidChangeWebviewPanelViewState(handle, handle === this._activeWebview, workbenchEditor.position);
const inputPosition = editorGroupToViewColumn(this._editorGroupService, input.group);
const editorPosition = editorGroupToViewColumn(this._editorGroupService, workbenchEditor.group);
if (workbenchEditor.input.matches(input) && inputPosition !== editorPosition) {
input.updateGroup(workbenchEditor.group.id);
this._proxy.$onDidChangeWebviewPanelViewState(handle, handle === this._activeWebview, editorPosition);
}
});
}

View File

@@ -8,7 +8,8 @@ import URI from 'vs/base/common/uri';
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 { Position as EditorPosition, ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { EditorViewColumn } from 'vs/workbench/api/shared/editor';
// -----------------------------------------------------------------
// The following commands are registered on both sides separately.
@@ -70,21 +71,21 @@ export class OpenAPICommand {
public static ID = 'vscode.open';
public static execute(executor: ICommandsExecutor, resource: URI, columnOrOptions?: vscode.ViewColumn | vscode.TextDocumentShowOptions): Thenable<any> {
let options: ITextEditorOptions;
let column: EditorPosition;
let position: EditorViewColumn;
if (columnOrOptions) {
if (typeof columnOrOptions === 'number') {
column = typeConverters.ViewColumn.from(columnOrOptions);
position = typeConverters.ViewColumn.from(columnOrOptions);
} else {
options = typeConverters.TextEditorOptions.from(columnOrOptions);
column = typeConverters.ViewColumn.from(columnOrOptions.viewColumn);
position = typeConverters.ViewColumn.from(columnOrOptions.viewColumn);
}
}
return executor.executeCommand('_workbench.open', [
resource,
options,
column
position
]);
}
}

View File

@@ -122,7 +122,7 @@ export function createApiFactory(
const extHostTerminalService = rpcProtocol.set(ExtHostContext.ExtHostTerminalService, new ExtHostTerminalService(rpcProtocol, extHostConfiguration, extHostLogService));
const extHostSCM = rpcProtocol.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(rpcProtocol, extHostCommands, extHostLogService));
const extHostSearch = rpcProtocol.set(ExtHostContext.ExtHostSearch, new ExtHostSearch(rpcProtocol, schemeTransformer));
const extHostTask = rpcProtocol.set(ExtHostContext.ExtHostTask, new ExtHostTask(rpcProtocol, extHostWorkspace));
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);
const extHostProgress = rpcProtocol.set(ExtHostContext.ExtHostProgress, new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress)));
@@ -140,7 +140,7 @@ export function createApiFactory(
const extHostLanguages = new ExtHostLanguages(rpcProtocol);
// Register API-ish commands
ExtHostApiCommands.register(extHostCommands, extHostTask);
ExtHostApiCommands.register(extHostCommands);
return function (extension: IExtensionDescription): typeof vscode {
@@ -396,9 +396,6 @@ export function createApiFactory(
showInputBox(options?: vscode.InputBoxOptions, token?: vscode.CancellationToken) {
return extHostQuickOpen.showInput(undefined, options, token);
},
multiStepInput<T>(handler: (input: vscode.QuickInput, token: vscode.CancellationToken) => Thenable<T>, token?: vscode.CancellationToken): Thenable<T> {
return extHostQuickOpen.multiStepInput(handler, token);
},
showOpenDialog(options) {
return extHostDialogs.showOpenDialog(options);
},
@@ -565,9 +562,6 @@ export function createApiFactory(
registerFileSystemProvider(scheme, provider, options) {
return extHostFileSystem.registerFileSystemProvider(scheme, provider, options);
},
registerDeprecatedFileSystemProvider: proposedApiFunction(extension, (scheme, provider) => {
return extHostFileSystem.registerDeprecatedFileSystemProvider(scheme, provider);
}),
registerSearchProvider: proposedApiFunction(extension, (scheme, provider) => {
return extHostSearch.registerSearchProvider(scheme, provider);
}),
@@ -576,6 +570,9 @@ export function createApiFactory(
}),
registerWorkspaceCommentProvider: proposedApiFunction(extension, (provider: vscode.WorkspaceCommentProvider) => {
return exthostCommentProviders.registerWorkspaceCommentProvider(provider);
}),
onDidRenameResource: proposedApiFunction(extension, (listener, thisArg?, disposables?) => {
return extHostDocuments.onDidRenameResource(listener, thisArg, disposables);
})
};
@@ -633,12 +630,12 @@ export function createApiFactory(
registerTaskProvider: (type: string, provider: vscode.TaskProvider) => {
return extHostTask.registerTaskProvider(extension, provider);
},
fetchTasks: proposedApiFunction(extension, (filter?: vscode.TaskFilter): Thenable<vscode.Task[]> => {
fetchTasks: (filter?: vscode.TaskFilter): Thenable<vscode.Task[]> => {
return extHostTask.fetchTasks(filter);
}),
executeTask: proposedApiFunction(extension, (task: vscode.Task): Thenable<vscode.TaskExecution> => {
},
executeTask: (task: vscode.Task): Thenable<vscode.TaskExecution> => {
return extHostTask.executeTask(extension, task);
}),
},
get taskExecutions(): vscode.TaskExecution[] {
return extHostTask.taskExecutions;
},
@@ -677,6 +674,7 @@ export function createApiFactory(
Color: extHostTypes.Color,
ColorPresentation: extHostTypes.ColorPresentation,
ColorInformation: extHostTypes.ColorInformation,
CodeActionTrigger: extHostTypes.CodeActionTrigger,
EndOfLine: extHostTypes.EndOfLine,
CompletionItem: extHostTypes.CompletionItem,
CompletionItemKind: extHostTypes.CompletionItemKind,
@@ -750,8 +748,6 @@ export function createApiFactory(
ConfigurationTarget: extHostTypes.ConfigurationTarget,
RelativePattern: extHostTypes.RelativePattern,
DeprecatedFileChangeType: extHostTypes.DeprecatedFileChangeType,
DeprecatedFileType: extHostTypes.DeprecatedFileType,
FileChangeType: extHostTypes.FileChangeType,
FileType: files.FileType,
FileSystemError: extHostTypes.FileSystemError,

View File

@@ -13,7 +13,7 @@ import Severity from 'vs/base/common/severity';
import { TPromise } from 'vs/base/common/winjs.base';
import { IMarkerData } from 'vs/platform/markers/common/markers';
import { Position as EditorPosition } from 'vs/platform/editor/common/editor';
import { EditorViewColumn } from 'vs/workbench/api/shared/editor';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { StatusbarAlignment as MainThreadStatusBarAlignment } from 'vs/platform/statusbar/common/statusbar';
import { ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
@@ -48,7 +48,7 @@ import { CommentRule, CharacterPair, EnterAction } from 'vs/editor/common/modes/
import { ISingleEditOperation } from 'vs/editor/common/model';
import { IPatternInfo, IRawSearchQuery, IRawFileMatch2, ISearchCompleteStats } from 'vs/platform/search/common/search';
import { LogLevel } from 'vs/platform/log/common/log';
import { TaskExecutionDTO, TaskDTO, TaskHandleDTO, TaskFilterDTO, TaskProcessStartedDTO, TaskProcessEndedDTO } from 'vs/workbench/api/shared/tasks';
import { TaskExecutionDTO, TaskDTO, TaskHandleDTO, TaskFilterDTO, TaskProcessStartedDTO, TaskProcessEndedDTO, TaskSystemInfoDTO } from 'vs/workbench/api/shared/tasks';
export interface IEnvironment {
isExtensionDevelopmentDebug: boolean;
@@ -189,7 +189,7 @@ export interface IApplyEditsOptions extends IUndoStopOptions {
}
export interface ITextDocumentShowOptions {
position?: EditorPosition;
position?: EditorViewColumn;
preserveFocus?: boolean;
pinned?: boolean;
selection?: IRange;
@@ -199,7 +199,7 @@ export interface MainThreadTextEditorsShape extends IDisposable {
$tryShowTextDocument(resource: UriComponents, options: ITextDocumentShowOptions): TPromise<string>;
$registerTextEditorDecorationType(key: string, options: editorCommon.IDecorationRenderOptions): void;
$removeTextEditorDecorationType(key: string): void;
$tryShowEditor(id: string, position: EditorPosition): TPromise<void>;
$tryShowEditor(id: string, position: EditorViewColumn): TPromise<void>;
$tryHideEditor(id: string): TPromise<void>;
$trySetOptions(id: string, options: ITextEditorConfigurationUpdate): TPromise<void>;
$trySetDecorations(id: string, key: string, ranges: editorCommon.IDecorationOptions[]): TPromise<void>;
@@ -364,9 +364,9 @@ export interface MainThreadTelemetryShape extends IDisposable {
export type WebviewPanelHandle = string;
export interface MainThreadWebviewsShape extends IDisposable {
$createWebviewPanel(handle: WebviewPanelHandle, viewType: string, title: string, viewOptions: { viewColumn: EditorPosition, preserveFocus: boolean }, options: vscode.WebviewPanelOptions & vscode.WebviewOptions, extensionLocation: UriComponents): void;
$createWebviewPanel(handle: WebviewPanelHandle, viewType: string, title: string, viewOptions: { viewColumn: EditorViewColumn, preserveFocus: boolean }, options: vscode.WebviewPanelOptions & vscode.WebviewOptions, extensionLocation: UriComponents): void;
$disposeWebview(handle: WebviewPanelHandle): void;
$reveal(handle: WebviewPanelHandle, viewColumn: EditorPosition | null, preserveFocus: boolean): void;
$reveal(handle: WebviewPanelHandle, viewColumn: EditorViewColumn | null, preserveFocus: boolean): void;
$setTitle(handle: WebviewPanelHandle, value: string): void;
$setHtml(handle: WebviewPanelHandle, value: string): void;
$postMessage(handle: WebviewPanelHandle, value: any): Thenable<boolean>;
@@ -377,9 +377,9 @@ export interface MainThreadWebviewsShape extends IDisposable {
export interface ExtHostWebviewsShape {
$onMessage(handle: WebviewPanelHandle, message: any): void;
$onDidChangeWebviewPanelViewState(handle: WebviewPanelHandle, active: boolean, position: EditorPosition): void;
$onDidChangeWebviewPanelViewState(handle: WebviewPanelHandle, active: boolean, position: EditorViewColumn): void;
$onDidDisposeWebviewPanel(handle: WebviewPanelHandle): Thenable<void>;
$deserializeWebviewPanel(newWebviewHandle: WebviewPanelHandle, viewType: string, title: string, state: any, position: EditorPosition, options: vscode.WebviewOptions): Thenable<void>;
$deserializeWebviewPanel(newWebviewHandle: WebviewPanelHandle, viewType: string, title: string, state: any, position: EditorViewColumn, options: vscode.WebviewOptions): Thenable<void>;
}
export interface MainThreadUrlsShape extends IDisposable {
@@ -418,10 +418,11 @@ export interface MainThreadSearchShape extends IDisposable {
export interface MainThreadTaskShape extends IDisposable {
$registerTaskProvider(handle: number): TPromise<void>;
$unregisterTaskProvider(handle: number): TPromise<void>;
$fetchTasks(filter?: TaskFilterDTO): TPromise<TaskDTO[]>;
$executeTask(task: TaskHandleDTO | TaskDTO): TPromise<TaskExecutionDTO>;
$terminateTask(id: string): TPromise<void>;
$unregisterTaskProvider(handle: number): TPromise<void>;
$registerTaskSystem(scheme: string, info: TaskSystemInfoDTO): void;
}
export interface MainThreadExtensionServiceShape extends IDisposable {
@@ -538,6 +539,7 @@ export interface ExtHostDocumentsShape {
$acceptModelSaved(strURL: UriComponents): void;
$acceptDirtyStateChanged(strURL: UriComponents, isDirty: boolean): void;
$acceptModelChanged(strURL: UriComponents, e: IModelChangedEvent, isDirty: boolean): void;
$onDidRename(oldURL: UriComponents, newURL: UriComponents): void;
}
export interface ExtHostDocumentSaveParticipantShape {
@@ -550,10 +552,10 @@ export interface ITextEditorAddData {
options: IResolvedTextEditorConfiguration;
selections: ISelection[];
visibleRanges: IRange[];
editorPosition: EditorPosition;
editorPosition: EditorViewColumn;
}
export interface ITextEditorPositionData {
[id: string]: EditorPosition;
[id: string]: EditorViewColumn;
}
export interface IEditorPropertiesChangeData {
options: IResolvedTextEditorConfiguration | null;
@@ -790,6 +792,7 @@ export interface ExtHostTaskShape {
$onDidStartTaskProcess(value: TaskProcessStartedDTO): void;
$onDidEndTaskProcess(value: TaskProcessEndedDTO): void;
$OnDidEndTask(execution: TaskExecutionDTO): void;
$resolveVariables(workspaceFolder: URI, variables: string[]): TPromise<any>;
}
export interface IBreakpointDto {
@@ -836,6 +839,8 @@ export interface ISourceMultiBreakpointDto {
export interface ExtHostDebugServiceShape {
$substituteVariables(folder: UriComponents | undefined, config: IConfig): TPromise<IConfig>;
$runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise<void>;
$isTerminalBusy(processId: number): TPromise<boolean>;
$prepareCommandForTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise<any>;
$startDASession(handle: number, debugType: string, adapterExecutableInfo: IAdapterExecutable | null, debugPort: number): TPromise<void>;
$stopDASession(handle: number): TPromise<void>;
$sendDAMessage(handle: number, message: DebugProtocol.ProtocolMessage): TPromise<void>;

View File

@@ -18,22 +18,19 @@ import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
import { IWorkspaceSymbolProvider } from 'vs/workbench/parts/search/common/search';
import { CustomCodeAction } from 'vs/workbench/api/node/extHostLanguageFeatures';
import { ExtHostTask } from './extHostTask';
import { ICommandsExecutor, PreviewHTMLAPICommand, OpenFolderAPICommand, DiffAPICommand, OpenAPICommand, RemoveFromRecentlyOpenedAPICommand } from './apiCommands';
export class ExtHostApiCommands {
static register(commands: ExtHostCommands, workspace: ExtHostTask) {
return new ExtHostApiCommands(commands, workspace).registerCommands();
static register(commands: ExtHostCommands) {
return new ExtHostApiCommands(commands).registerCommands();
}
private _commands: ExtHostCommands;
private _tasks: ExtHostTask;
private _disposables: IDisposable[] = [];
private constructor(commands: ExtHostCommands, task: ExtHostTask) {
private constructor(commands: ExtHostCommands) {
this._commands = commands;
this._tasks = task;
}
registerCommands() {
@@ -176,11 +173,6 @@ export class ExtHostApiCommands {
],
returns: 'A promise that resolves to an array of DocumentLink-instances.'
});
this._register('vscode.executeTaskProvider', this._executeTaskProvider, {
description: 'Execute task provider',
args: [],
returns: 'An array of task handles'
});
this._register('vscode.executeDocumentColorProvider', this._executeDocumentColorProvider, {
description: 'Execute document color provider.',
args: [
@@ -494,10 +486,6 @@ export class ExtHostApiCommands {
return this._commands.executeCommand<modes.ILink[]>('_executeLinkProvider', resource)
.then(tryMapWith(typeConverters.DocumentLink.to));
}
private _executeTaskProvider(): Thenable<vscode.Task[]> {
return this._tasks.fetchTasks();
}
}
function tryMapWith<T, R>(f: (x: T) => R) {

View File

@@ -15,7 +15,7 @@ import { IConfigurationData, ConfigurationTarget, IConfigurationModel } from 'vs
import { Configuration, ConfigurationChangeEvent, ConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
import { WorkspaceConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels';
import { ResourceMap } from 'vs/base/common/map';
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
import { ConfigurationScope, OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry';
import { isObject } from 'vs/base/common/types';
declare var Proxy: any; // TODO@TypeScript
@@ -191,7 +191,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
}
private _validateConfigurationAccess(key: string, resource: URI, extensionId: string): void {
const scope = this._configurationScopes[key];
const scope = OVERRIDE_PROPERTY_PATTERN.test(key) ? ConfigurationScope.RESOURCE : this._configurationScopes[key];
const extensionIdText = extensionId ? `[${extensionId}] ` : '';
if (ConfigurationScope.RESOURCE === scope) {
if (resource === void 0) {

View File

@@ -22,7 +22,7 @@ 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 { IAdapterExecutable, ITerminalSettings, IDebuggerContribution, IConfig, IDebugAdapter } from 'vs/workbench/parts/debug/common/debug';
import { getTerminalLauncher } 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 { VariableResolver } from 'vs/workbench/services/configurationResolver/node/variableResolver';
import { IStringDictionary } from 'vs/base/common/collections';
@@ -68,7 +68,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
constructor(mainContext: IMainContext,
private _workspace: ExtHostWorkspace,
private _workspaceService: ExtHostWorkspace,
private _extensionService: ExtHostExtensionService,
private _editorsService: ExtHostDocumentsAndEditors,
private _configurationService: ExtHostConfiguration
@@ -125,12 +125,28 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
return void 0;
}
public $isTerminalBusy(processId: number): TPromise<boolean> {
return asWinJsPromise(token => hasChildprocesses(processId));
}
public $prepareCommandForTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise<any> {
return asWinJsPromise(token => prepareCommand(args, config));
}
public $substituteVariables(folderUri: UriComponents | undefined, config: IConfig): TPromise<IConfig> {
if (!this._variableResolver) {
this._variableResolver = new ExtHostVariableResolverService(this._workspace, this._editorsService, this._configurationService);
this._variableResolver = new ExtHostVariableResolverService(this._workspaceService, this._editorsService, this._configurationService);
}
const folder = <IWorkspaceFolder>this.getFolder(folderUri);
return asWinJsPromise(token => DebugAdapter.substituteVariables(folder, config, this._variableResolver));
const folder = this.getFolder(folderUri);
let ws: IWorkspaceFolder = {
uri: folder.uri,
name: folder.name,
index: folder.index,
toResource: () => {
throw new Error('Not implemented');
}
};
return asWinJsPromise(token => DebugAdapter.substituteVariables(ws, config, this._variableResolver));
}
public $startDASession(handle: number, debugType: string, adpaterExecutable: IAdapterExecutable | null, debugPort: number): TPromise<void> {
@@ -479,14 +495,10 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
this._onDidReceiveDebugSessionCustomEvent.fire(ee);
}
private getFolder(_folderUri: UriComponents | undefined) {
private getFolder(_folderUri: UriComponents | undefined): vscode.WorkspaceFolder {
if (_folderUri) {
const folderUriString = URI.revive(_folderUri).toString();
const folders = this._workspace.getWorkspaceFolders();
const found = folders.filter(f => f.uri.toString() === folderUriString);
if (found && found.length > 0) {
return found[0];
}
const folderURI = URI.revive(_folderUri);
return this._workspaceService.resolveWorkspaceFolder(folderURI);
}
return undefined;
}

View File

@@ -17,17 +17,17 @@ import { keys } from 'vs/base/common/map';
export class DiagnosticCollection implements vscode.DiagnosticCollection {
private static readonly _maxDiagnosticsPerFile: number = 250;
private readonly _name: string;
private readonly _maxDiagnosticsPerFile: number;
private readonly _onDidChangeDiagnostics: Emitter<(vscode.Uri | string)[]>;
private _proxy: MainThreadDiagnosticsShape;
private _isDisposed = false;
private _data = new Map<string, vscode.Diagnostic[]>();
constructor(name: string, proxy: MainThreadDiagnosticsShape, onDidChangeDiagnostics: Emitter<(vscode.Uri | string)[]>) {
constructor(name: string, maxDiagnosticsPerFile: number, proxy: MainThreadDiagnosticsShape, onDidChangeDiagnostics: Emitter<(vscode.Uri | string)[]>) {
this._name = name;
this._maxDiagnosticsPerFile = maxDiagnosticsPerFile;
this._proxy = proxy;
this._onDidChangeDiagnostics = onDidChangeDiagnostics;
}
@@ -109,15 +109,15 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
let diagnostics = this._data.get(uri.toString());
if (diagnostics) {
// no more than 250 diagnostics per file
if (diagnostics.length > DiagnosticCollection._maxDiagnosticsPerFile) {
// no more than N diagnostics per file
if (diagnostics.length > this._maxDiagnosticsPerFile) {
marker = [];
const order = [DiagnosticSeverity.Error, DiagnosticSeverity.Warning, DiagnosticSeverity.Information, DiagnosticSeverity.Hint];
orderLoop: for (let i = 0; i < 4; i++) {
for (let diagnostic of diagnostics) {
if (diagnostic.severity === order[i]) {
const len = marker.push(converter.Diagnostic.from(diagnostic));
if (len === DiagnosticCollection._maxDiagnosticsPerFile) {
if (len === this._maxDiagnosticsPerFile) {
break orderLoop;
}
}
@@ -126,8 +126,8 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
// add 'signal' marker for showing omitted errors/warnings
marker.push({
severity: MarkerSeverity.Error,
message: localize({ key: 'limitHit', comment: ['amount of errors/warning skipped due to limits'] }, "Not showing {0} further errors and warnings.", diagnostics.length - DiagnosticCollection._maxDiagnosticsPerFile),
severity: MarkerSeverity.Info,
message: localize({ key: 'limitHit', comment: ['amount of errors/warning skipped due to limits'] }, "Not showing {0} further errors and warnings.", diagnostics.length - this._maxDiagnosticsPerFile),
startLineNumber: marker[marker.length - 1].startLineNumber,
startColumn: marker[marker.length - 1].startColumn,
endLineNumber: marker[marker.length - 1].endLineNumber,
@@ -201,6 +201,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
private static _idPool: number = 0;
private static readonly _maxDiagnosticsPerFile: number = 1000;
private readonly _proxy: MainThreadDiagnosticsShape;
private readonly _collections: DiagnosticCollection[] = [];
@@ -248,7 +249,7 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
const { _collections, _proxy, _onDidChangeDiagnostics } = this;
const result = new class extends DiagnosticCollection {
constructor() {
super(name, _proxy, _onDidChangeDiagnostics);
super(name, ExtHostDiagnostics._maxDiagnosticsPerFile, _proxy, _onDidChangeDiagnostics);
_collections.push(this);
}
dispose() {

View File

@@ -21,11 +21,13 @@ export class ExtHostDocuments implements ExtHostDocumentsShape {
private _onDidRemoveDocument = new Emitter<vscode.TextDocument>();
private _onDidChangeDocument = new Emitter<vscode.TextDocumentChangeEvent>();
private _onDidSaveDocument = new Emitter<vscode.TextDocument>();
private _onDidRenameResource = new Emitter<vscode.ResourceRenamedEvent>();
readonly onDidAddDocument: Event<vscode.TextDocument> = this._onDidAddDocument.event;
readonly onDidRemoveDocument: Event<vscode.TextDocument> = this._onDidRemoveDocument.event;
readonly onDidChangeDocument: Event<vscode.TextDocumentChangeEvent> = this._onDidChangeDocument.event;
readonly onDidSaveDocument: Event<vscode.TextDocument> = this._onDidSaveDocument.event;
readonly onDidRenameResource: Event<vscode.ResourceRenamedEvent> = this._onDidRenameResource.event;
private _toDispose: IDisposable[];
private _proxy: MainThreadDocumentsShape;
@@ -148,4 +150,11 @@ export class ExtHostDocuments implements ExtHostDocumentsShape {
public setWordDefinitionFor(modeId: string, wordDefinition: RegExp): void {
setWordDefinitionFor(modeId, wordDefinition);
}
public $onDidRename(oldURL: UriComponents, newURL: UriComponents): void {
const oldResource = URI.revive(oldURL);
const newResource = URI.revive(newURL);
this._onDidRenameResource.fire({ oldResource, newResource });
}
}

View File

@@ -6,15 +6,13 @@
import URI, { UriComponents } from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { Event, mapEvent } from 'vs/base/common/event';
import { MainContext, IMainContext, ExtHostFileSystemShape, MainThreadFileSystemShape, IFileChangeDto } from './extHost.protocol';
import * as vscode from 'vscode';
import * as files from 'vs/platform/files/common/files';
import * as path from 'path';
import { IDisposable } from 'vs/base/common/lifecycle';
import { asWinJsPromise } from 'vs/base/common/async';
import { values } from 'vs/base/common/map';
import { Range, DeprecatedFileType, DeprecatedFileChangeType, FileChangeType } from 'vs/workbench/api/node/extHostTypes';
import { Range, FileChangeType } from 'vs/workbench/api/node/extHostTypes';
import { ExtHostLanguageFeatures } from 'vs/workbench/api/node/extHostLanguageFeatures';
import { Schemas } from 'vs/base/common/network';
@@ -34,7 +32,7 @@ class FsLinkProvider implements vscode.DocumentLinkProvider {
}
}
provideDocumentLinks(document: vscode.TextDocument, token: vscode.CancellationToken): vscode.ProviderResult<vscode.DocumentLink[]> {
provideDocumentLinks(document: vscode.TextDocument): vscode.ProviderResult<vscode.DocumentLink[]> {
if (this._schemes.size === 0) {
return undefined;
}
@@ -60,106 +58,6 @@ class FsLinkProvider implements vscode.DocumentLinkProvider {
}
}
class FileSystemProviderShim implements vscode.FileSystemProvider {
onDidChangeFile: vscode.Event<vscode.FileChangeEvent[]>;
constructor(private readonly _delegate: vscode.DeprecatedFileSystemProvider) {
if (!this._delegate.onDidChange) {
this.onDidChangeFile = Event.None;
} else {
this.onDidChangeFile = mapEvent(this._delegate.onDidChange, old => old.map(FileSystemProviderShim._modernizeFileChange));
}
}
watch(uri: vscode.Uri, options: {}): vscode.Disposable {
// does nothing because in the old API there was no notion of
// watch and provider decide what file events to generate...
return { dispose() { } };
}
stat(resource: vscode.Uri): Thenable<vscode.FileStat> {
return this._delegate.stat(resource).then(stat => FileSystemProviderShim._modernizeFileStat(stat));
}
rename(oldUri: vscode.Uri, newUri: vscode.Uri): Thenable<void> {
return this._delegate.move(oldUri, newUri).then(stat => void 0);
}
readDirectory(resource: vscode.Uri): Thenable<[string, vscode.FileType][]> {
return this._delegate.readdir(resource).then(tuples => {
return tuples.map(tuple => <[string, vscode.FileType]>[path.posix.basename(tuple[0].path), FileSystemProviderShim._modernizeFileStat(tuple[1]).type]);
});
}
private static _modernizeFileStat(stat: vscode.DeprecatedFileStat): vscode.FileStat {
let { mtime, size, type } = stat;
let newType: files.FileType;
// no support for bitmask, effectively no support for symlinks
switch (type) {
case DeprecatedFileType.Dir:
newType = files.FileType.Directory;
break;
case DeprecatedFileType.File:
newType = files.FileType.File;
break;
case DeprecatedFileType.Symlink:
newType = files.FileType.File & files.FileType.SymbolicLink;
break;
}
return { type: newType, ctime: 0, mtime, size };
}
private static _modernizeFileChange(e: vscode.DeprecatedFileChange): vscode.FileChangeEvent {
let { resource, type } = e;
let newType: vscode.FileChangeType;
switch (type) {
case DeprecatedFileChangeType.Updated:
newType = FileChangeType.Changed;
break;
case DeprecatedFileChangeType.Added:
newType = FileChangeType.Created;
break;
case DeprecatedFileChangeType.Deleted:
newType = FileChangeType.Deleted;
break;
}
return { uri: resource, type: newType };
}
// --- delete/create file or folder
delete(resource: vscode.Uri): Thenable<void> {
return this._delegate.stat(resource).then(stat => {
if (stat.type === DeprecatedFileType.Dir) {
return this._delegate.rmdir(resource);
} else {
return this._delegate.unlink(resource);
}
});
}
createDirectory(resource: vscode.Uri): Thenable<void> {
return this._delegate.mkdir(resource).then(stat => void 0);
}
// --- read/write
readFile(resource: vscode.Uri): Thenable<Uint8Array> {
let chunks: Buffer[] = [];
return this._delegate.read(resource, 0, -1, {
report(data) {
chunks.push(Buffer.from(data));
}
}).then(() => {
return Buffer.concat(chunks);
});
}
writeFile(resource: vscode.Uri, content: Uint8Array, options: files.FileWriteOptions): Thenable<void> {
return this._delegate.write(resource, content);
}
}
export class ExtHostFileSystem implements ExtHostFileSystemShape {
private readonly _proxy: MainThreadFileSystemShape;
@@ -185,11 +83,7 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
extHostLanguageFeatures.registerDocumentLinkProvider('*', this._linkProvider);
}
registerDeprecatedFileSystemProvider(scheme: string, provider: vscode.DeprecatedFileSystemProvider) {
return this.registerFileSystemProvider(scheme, new FileSystemProviderShim(provider), { isCaseSensitive: false });
}
registerFileSystemProvider(scheme: string, provider: vscode.FileSystemProvider, options: { isCaseSensitive?: boolean }) {
registerFileSystemProvider(scheme: string, provider: vscode.FileSystemProvider, options: { isCaseSensitive?: boolean } = {}) {
if (this._usedSchemes.has(scheme)) {
throw new Error(`a provider for the scheme '${scheme}' is already registered`);
@@ -252,15 +146,15 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
}
$stat(handle: number, resource: UriComponents): TPromise<files.IStat, any> {
return asWinJsPromise(token => this._fsProvider.get(handle).stat(URI.revive(resource))).then(ExtHostFileSystem._asIStat);
return asWinJsPromise(() => this._fsProvider.get(handle).stat(URI.revive(resource))).then(ExtHostFileSystem._asIStat);
}
$readdir(handle: number, resource: UriComponents): TPromise<[string, files.FileType][], any> {
return asWinJsPromise(token => this._fsProvider.get(handle).readDirectory(URI.revive(resource)));
return asWinJsPromise(() => this._fsProvider.get(handle).readDirectory(URI.revive(resource)));
}
$readFile(handle: number, resource: UriComponents): TPromise<string> {
return asWinJsPromise(token => {
return asWinJsPromise(() => {
return this._fsProvider.get(handle).readFile(URI.revive(resource));
}).then(data => {
return Buffer.isBuffer(data) ? data.toString('base64') : Buffer.from(data.buffer, data.byteOffset, data.byteLength).toString('base64');
@@ -268,33 +162,33 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
}
$writeFile(handle: number, resource: UriComponents, base64Content: string, opts: files.FileWriteOptions): TPromise<void, any> {
return asWinJsPromise(token => this._fsProvider.get(handle).writeFile(URI.revive(resource), Buffer.from(base64Content, 'base64'), opts));
return asWinJsPromise(() => this._fsProvider.get(handle).writeFile(URI.revive(resource), Buffer.from(base64Content, 'base64'), opts));
}
$delete(handle: number, resource: UriComponents): TPromise<void, any> {
return asWinJsPromise(token => this._fsProvider.get(handle).delete(URI.revive(resource), { recursive: true }));
return asWinJsPromise(() => this._fsProvider.get(handle).delete(URI.revive(resource), { recursive: true }));
}
$rename(handle: number, oldUri: UriComponents, newUri: UriComponents, opts: files.FileOverwriteOptions): TPromise<void, any> {
return asWinJsPromise(token => this._fsProvider.get(handle).rename(URI.revive(oldUri), URI.revive(newUri), opts));
return asWinJsPromise(() => this._fsProvider.get(handle).rename(URI.revive(oldUri), URI.revive(newUri), opts));
}
$copy(handle: number, oldUri: UriComponents, newUri: UriComponents, opts: files.FileOverwriteOptions): TPromise<void, any> {
return asWinJsPromise(token => this._fsProvider.get(handle).copy(URI.revive(oldUri), URI.revive(newUri), opts));
return asWinJsPromise(() => this._fsProvider.get(handle).copy(URI.revive(oldUri), URI.revive(newUri), opts));
}
$mkdir(handle: number, resource: UriComponents): TPromise<void, any> {
return asWinJsPromise(token => this._fsProvider.get(handle).createDirectory(URI.revive(resource)));
return asWinJsPromise(() => this._fsProvider.get(handle).createDirectory(URI.revive(resource)));
}
$watch(handle: number, session: number, resource: UriComponents, opts: files.IWatchOptions): void {
asWinJsPromise(token => {
asWinJsPromise(() => {
let subscription = this._fsProvider.get(handle).watch(URI.revive(resource), opts);
this._watches.set(session, subscription);
});
}
$unwatch(handle: number, session: number): void {
$unwatch(session: number): void {
let subscription = this._watches.get(session);
if (subscription) {
subscription.dispose();

View File

@@ -65,6 +65,9 @@ class OutlineAdapter {
let parentStack: Hierarchy<SymbolInformation2>[] = [];
for (let i = 0; i < info.length; i++) {
let element = new Hierarchy(new SymbolInformation2(info[i].name, '', info[i].kind, info[i].location.range, info[i].location));
element.parent.containerName = info[i].containerName;
element.parent.location = info[i].location; // todo@joh make this proper
while (true) {
if (parentStack.length === 0) {
parentStack.push(element);
@@ -72,7 +75,7 @@ class OutlineAdapter {
break;
}
let parent = parentStack[parentStack.length - 1];
if (parent.parent.range.contains(element.parent.range)) {
if (parent.parent.range.contains(element.parent.range) && !parent.parent.range.isEqual(element.parent.range)) {
parent.children.push(element);
parentStack.push(element);
break;
@@ -88,17 +91,12 @@ class CodeLensAdapter {
private static _badCmd: vscode.Command = { command: 'missing', title: '<<MISSING COMMAND>>' };
private _documents: ExtHostDocuments;
private _commands: CommandsConverter;
private _heapService: ExtHostHeapService;
private _provider: vscode.CodeLensProvider;
constructor(documents: ExtHostDocuments, commands: CommandsConverter, heapService: ExtHostHeapService, provider: vscode.CodeLensProvider) {
this._documents = documents;
this._commands = commands;
this._heapService = heapService;
this._provider = provider;
}
constructor(
private readonly _documents: ExtHostDocuments,
private readonly _commands: CommandsConverter,
private readonly _heapService: ExtHostHeapService,
private readonly _provider: vscode.CodeLensProvider
) { }
provideCodeLenses(resource: URI): TPromise<modes.ICodeLensSymbol[]> {
const doc = this._documents.getDocumentData(resource).document;
@@ -140,13 +138,11 @@ class CodeLensAdapter {
}
class DefinitionAdapter {
private _documents: ExtHostDocuments;
private _provider: vscode.DefinitionProvider;
constructor(documents: ExtHostDocuments, provider: vscode.DefinitionProvider) {
this._documents = documents;
this._provider = provider;
}
constructor(
private readonly _documents: ExtHostDocuments,
private readonly _provider: vscode.DefinitionProvider
) { }
provideDefinition(resource: URI, position: IPosition): TPromise<modes.Definition> {
let doc = this._documents.getDocumentData(resource).document;
@@ -163,13 +159,11 @@ class DefinitionAdapter {
}
class ImplementationAdapter {
private _documents: ExtHostDocuments;
private _provider: vscode.ImplementationProvider;
constructor(documents: ExtHostDocuments, provider: vscode.ImplementationProvider) {
this._documents = documents;
this._provider = provider;
}
constructor(
private readonly _documents: ExtHostDocuments,
private readonly _provider: vscode.ImplementationProvider
) { }
provideImplementation(resource: URI, position: IPosition): TPromise<modes.Definition> {
let doc = this._documents.getDocumentData(resource).document;
@@ -186,13 +180,11 @@ class ImplementationAdapter {
}
class TypeDefinitionAdapter {
private _documents: ExtHostDocuments;
private _provider: vscode.TypeDefinitionProvider;
constructor(documents: ExtHostDocuments, provider: vscode.TypeDefinitionProvider) {
this._documents = documents;
this._provider = provider;
}
constructor(
private readonly _documents: ExtHostDocuments,
private readonly _provider: vscode.TypeDefinitionProvider
) { }
provideTypeDefinition(resource: URI, position: IPosition): TPromise<modes.Definition> {
const doc = this._documents.getDocumentData(resource).document;
@@ -208,15 +200,12 @@ class TypeDefinitionAdapter {
}
}
class HoverAdapter {
constructor(
private readonly _documents: ExtHostDocuments,
private readonly _provider: vscode.HoverProvider,
) {
//
}
) { }
public provideHover(resource: URI, position: IPosition): TPromise<modes.Hover> {
@@ -241,13 +230,10 @@ class HoverAdapter {
class DocumentHighlightAdapter {
private _documents: ExtHostDocuments;
private _provider: vscode.DocumentHighlightProvider;
constructor(documents: ExtHostDocuments, provider: vscode.DocumentHighlightProvider) {
this._documents = documents;
this._provider = provider;
}
constructor(
private readonly _documents: ExtHostDocuments,
private readonly _provider: vscode.DocumentHighlightProvider
) { }
provideDocumentHighlights(resource: URI, position: IPosition): TPromise<modes.DocumentHighlight[]> {
@@ -265,13 +251,10 @@ class DocumentHighlightAdapter {
class ReferenceAdapter {
private _documents: ExtHostDocuments;
private _provider: vscode.ReferenceProvider;
constructor(documents: ExtHostDocuments, provider: vscode.ReferenceProvider) {
this._documents = documents;
this._provider = provider;
}
constructor(
private readonly _documents: ExtHostDocuments,
private readonly _provider: vscode.ReferenceProvider
) { }
provideReferences(resource: URI, position: IPosition, context: modes.ReferenceContext): TPromise<modes.Location[]> {
let doc = this._documents.getDocumentData(resource).document;
@@ -315,7 +298,8 @@ class CodeActionAdapter {
const codeActionContext: vscode.CodeActionContext = {
diagnostics: allDiagnostics,
only: context.only ? new CodeActionKind(context.only) : undefined
only: context.only ? new CodeActionKind(context.only) : undefined,
triggerKind: context.trigger,
};
return asWinJsPromise(token =>
@@ -359,13 +343,10 @@ class CodeActionAdapter {
class DocumentFormattingAdapter {
private _documents: ExtHostDocuments;
private _provider: vscode.DocumentFormattingEditProvider;
constructor(documents: ExtHostDocuments, provider: vscode.DocumentFormattingEditProvider) {
this._documents = documents;
this._provider = provider;
}
constructor(
private readonly _documents: ExtHostDocuments,
private readonly _provider: vscode.DocumentFormattingEditProvider
) { }
provideDocumentFormattingEdits(resource: URI, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
@@ -382,13 +363,10 @@ class DocumentFormattingAdapter {
class RangeFormattingAdapter {
private _documents: ExtHostDocuments;
private _provider: vscode.DocumentRangeFormattingEditProvider;
constructor(documents: ExtHostDocuments, provider: vscode.DocumentRangeFormattingEditProvider) {
this._documents = documents;
this._provider = provider;
}
constructor(
private readonly _documents: ExtHostDocuments,
private readonly _provider: vscode.DocumentRangeFormattingEditProvider
) { }
provideDocumentRangeFormattingEdits(resource: URI, range: IRange, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
@@ -406,13 +384,10 @@ class RangeFormattingAdapter {
class OnTypeFormattingAdapter {
private _documents: ExtHostDocuments;
private _provider: vscode.OnTypeFormattingEditProvider;
constructor(documents: ExtHostDocuments, provider: vscode.OnTypeFormattingEditProvider) {
this._documents = documents;
this._provider = provider;
}
constructor(
private readonly _documents: ExtHostDocuments,
private readonly _provider: vscode.OnTypeFormattingEditProvider
) { }
autoFormatTriggerCharacters: string[] = []; // not here
@@ -498,13 +473,10 @@ class RenameAdapter {
return typeof provider.prepareRename === 'function';
}
private _documents: ExtHostDocuments;
private _provider: vscode.RenameProvider;
constructor(documents: ExtHostDocuments, provider: vscode.RenameProvider) {
this._documents = documents;
this._provider = provider;
}
constructor(
private readonly _documents: ExtHostDocuments,
private readonly _provider: vscode.RenameProvider
) { }
provideRenameEdits(resource: URI, position: IPosition, newName: string): TPromise<modes.WorkspaceEdit> {
@@ -733,13 +705,10 @@ class SuggestAdapter {
class SignatureHelpAdapter {
private _documents: ExtHostDocuments;
private _provider: vscode.SignatureHelpProvider;
constructor(documents: ExtHostDocuments, provider: vscode.SignatureHelpProvider) {
this._documents = documents;
this._provider = provider;
}
constructor(
private readonly _documents: ExtHostDocuments,
private readonly _provider: vscode.SignatureHelpProvider
) { }
provideSignatureHelp(resource: URI, position: IPosition): TPromise<modes.SignatureHelp> {
@@ -757,15 +726,11 @@ class SignatureHelpAdapter {
class LinkProviderAdapter {
private _documents: ExtHostDocuments;
private _heapService: ExtHostHeapService;
private _provider: vscode.DocumentLinkProvider;
constructor(documents: ExtHostDocuments, heapService: ExtHostHeapService, provider: vscode.DocumentLinkProvider) {
this._documents = documents;
this._heapService = heapService;
this._provider = provider;
}
constructor(
private readonly _documents: ExtHostDocuments,
private readonly _heapService: ExtHostHeapService,
private readonly _provider: vscode.DocumentLinkProvider
) { }
provideLinks(resource: URI): TPromise<modes.ILink[]> {
const doc = this._documents.getDocumentData(resource).document;

View File

@@ -6,12 +6,11 @@
import { TPromise } from 'vs/base/common/winjs.base';
import { wireCancellationToken, asWinJsPromise } from 'vs/base/common/async';
import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation';
import { QuickPickOptions, QuickPickItem, InputBoxOptions, WorkspaceFolderPickOptions, WorkspaceFolder, QuickInput } from 'vscode';
import { CancellationToken } from 'vs/base/common/cancellation';
import { QuickPickOptions, QuickPickItem, InputBoxOptions, WorkspaceFolderPickOptions, WorkspaceFolder } from 'vscode';
import { MainContext, MainThreadQuickOpenShape, ExtHostQuickOpenShape, MyQuickPickItems, IMainContext } from './extHost.protocol';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
import { isPromiseCanceledError } from 'vs/base/common/errors';
export type Item = string | QuickPickItem;
@@ -24,8 +23,6 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
private _onDidSelectItem: (handle: number) => void;
private _validateInput: (input: string) => string | Thenable<string>;
private _nextMultiStepHandle = 1;
constructor(mainContext: IMainContext, workspace: ExtHostWorkspace, commands: ExtHostCommands) {
this._proxy = mainContext.getProxy(MainContext.MainThreadQuickOpen);
this._workspace = workspace;
@@ -145,42 +142,4 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
return this._workspace.getWorkspaceFolders().filter(folder => folder.uri.toString() === selectedFolder.uri.toString())[0];
});
}
// ---- Multi-step input
multiStepInput<T>(handler: (input: QuickInput, token: CancellationToken) => Thenable<T>, clientToken: CancellationToken = CancellationToken.None): Thenable<T> {
const handle = this._nextMultiStepHandle++;
const remotePromise = this._proxy.$multiStep(handle);
const cancellationSource = new CancellationTokenSource();
const handlerPromise = TPromise.wrap(handler({
showQuickPick: this.showQuickPick.bind(this, handle),
showInputBox: this.showInput.bind(this, handle)
}, cancellationSource.token));
clientToken.onCancellationRequested(() => {
remotePromise.cancel();
cancellationSource.cancel();
});
return TPromise.join<void, T>([
remotePromise.then(() => {
throw new Error('Unexpectedly fulfilled promise.');
}, err => {
if (!isPromiseCanceledError(err)) {
throw err;
}
cancellationSource.cancel();
}),
handlerPromise.then(result => {
remotePromise.cancel();
return result;
}, err => {
remotePromise.cancel();
throw err;
})
]).then(([_, result]) => result, ([remoteErr, handlerErr]) => {
throw handlerErr || remoteErr;
});
}
}

View File

@@ -14,10 +14,11 @@ import * as strings from 'vs/base/common/strings';
import URI, { UriComponents } from 'vs/base/common/uri';
import { PPromise, TPromise } from 'vs/base/common/winjs.base';
import { IItemAccessor, ScorerCache, compareItemsByScore, prepareQuery } from 'vs/base/parts/quickopen/common/quickOpenScorer';
import { ICachedSearchStats, IRawFileMatch2, IFolderQuery, IPatternInfo, IRawSearchQuery, ISearchQuery, ISearchCompleteStats, IFileMatch } from 'vs/platform/search/common/search';
import { ICachedSearchStats, IFileMatch, IFolderQuery, IPatternInfo, IRawSearchQuery, ISearchQuery, ISearchCompleteStats, IRawFileMatch2 } from 'vs/platform/search/common/search';
import * as vscode from 'vscode';
import { ExtHostSearchShape, IMainContext, MainContext, MainThreadSearchShape } from './extHost.protocol';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { joinPath } from 'vs/base/common/resources';
type OneOrMore<T> = T | T[];
@@ -133,9 +134,11 @@ function reviveFolderQuery(rawFolderQuery: IFolderQuery<UriComponents>): IFolder
class TextSearchResultsCollector {
private _batchedCollector: BatchedCollector<IRawFileMatch2>;
private _currentFolderIdx: number;
private _currentRelativePath: string;
private _currentFileMatch: IRawFileMatch2;
constructor(private _onResult: (result: IRawFileMatch2[]) => void) {
constructor(private folderQueries: IFolderQuery[], private _onResult: (result: IRawFileMatch2[]) => void) {
this._batchedCollector = new BatchedCollector<IRawFileMatch2>(512, items => this.sendItems(items));
}
@@ -143,17 +146,15 @@ class TextSearchResultsCollector {
// Collects TextSearchResults into IInternalFileMatches and collates using BatchedCollector.
// This is efficient for ripgrep which sends results back one file at a time. It wouldn't be efficient for other search
// providers that send results in random order. We could do this step afterwards instead.
if (this._currentFileMatch && (this._currentFileMatch.resource.folderIdx !== folderIdx || this._currentFileMatch.resource.relativePath !== data.path)) {
if (this._currentFileMatch && (this._currentFolderIdx !== folderIdx || this._currentRelativePath !== data.path)) {
this.pushToCollector();
this._currentFileMatch = null;
}
if (!this._currentFileMatch) {
const resource = joinPath(this.folderQueries[folderIdx].folder, data.path);
this._currentFileMatch = {
resource: {
folderIdx,
relativePath: data.path
},
resource,
lineMatches: []
};
}
@@ -271,7 +272,7 @@ class BatchedCollector<T> {
}
interface IDirectoryEntry {
base: string;
base: URI;
relativePath: string;
basename: string;
}
@@ -282,8 +283,8 @@ interface IDirectoryTree {
}
interface IInternalFileMatch {
base?: string;
relativePath: string; // Not necessarily relative... extraFiles put an absolute path here. Rename.
base: URI;
relativePath?: string; // Not present for extraFiles or absolute path matches
basename: string;
size?: number;
}
@@ -349,7 +350,7 @@ class QueryGlobTester {
}
return this._parsedIncludeExpression ?
TPromise.as(this._parsedIncludeExpression(testPath, basename, siblingsFn)).then(result => !result) :
TPromise.as(this._parsedIncludeExpression(testPath, basename, siblingsFn)).then(result => !!result) :
TPromise.wrap(true);
}).then(included => {
return included;
@@ -393,20 +394,22 @@ class TextSearchEngine {
const folderQueries = this.config.folderQueries;
return new PPromise<{ limitHit: boolean }, IRawFileMatch2[]>((resolve, reject, _onResult) => {
this.collector = new TextSearchResultsCollector(_onResult);
this.collector = new TextSearchResultsCollector(this.config.folderQueries, _onResult);
const onResult = (match: vscode.TextSearchResult, folderIdx: number) => {
if (this.isCanceled) {
return;
}
this.resultCount++;
this.collector.add(match, folderIdx);
if (this.resultCount >= this.config.maxResults) {
this.isLimitHit = true;
this.cancel();
}
if (!this.isLimitHit) {
this.resultCount++;
this.collector.add(match, folderIdx);
}
};
// For each root folder
@@ -433,9 +436,9 @@ class TextSearchEngine {
const testingPs = [];
const progress = {
report: (result: vscode.TextSearchResult) => {
const siblingFn = () => {
const siblingFn = folderQuery.folder.scheme === 'file' && (() => {
return this.readdir(path.dirname(path.join(folderQuery.folder.fsPath, result.path)));
};
});
testingPs.push(
queryTester.includedInQuery(result.path, path.basename(result.path), siblingFn)
@@ -491,7 +494,8 @@ class TextSearchEngine {
includes,
useIgnoreFiles: !this.config.disregardIgnoreFiles,
followSymlinks: !this.config.ignoreSymlinks,
encoding: this.config.fileEncoding
encoding: this.config.fileEncoding,
maxFileSize: this.config.maxFileSize
};
}
}
@@ -558,7 +562,7 @@ class FileSearchEngine {
// Report result from file pattern if matching
if (exists) {
onResult({
relativePath: this.filePattern,
base: URI.file(this.filePattern),
basename: path.basename(this.filePattern),
size
});
@@ -572,15 +576,15 @@ class FileSearchEngine {
// For each extra file
if (this.config.extraFileResources) {
this.config.extraFileResources
.map(uri => uri.toString())
.forEach(extraFilePath => {
const basename = path.basename(extraFilePath);
if (this.globalExcludePattern && this.globalExcludePattern(extraFilePath, basename)) {
.forEach(extraFile => {
const extraFileStr = extraFile.toString(); // ?
const basename = path.basename(extraFileStr);
if (this.globalExcludePattern && this.globalExcludePattern(extraFileStr, basename)) {
return; // excluded
}
// File: Check for match on file pattern and include pattern
this.matchFile(onResult, { relativePath: extraFilePath /* no workspace relative path */, basename });
this.matchFile(onResult, { base: extraFile, basename });
});
}
@@ -588,7 +592,7 @@ class FileSearchEngine {
PPromise.join(folderQueries.map(fq => {
return this.searchInFolder(fq).then(null, null, onResult);
})).then(() => {
resolve({ isLimitHit: false });
resolve({ isLimitHit: this.isLimitHit });
}, (errs: Error[]) => {
const errMsg = errs
.map(err => toErrorMessage(err))
@@ -604,7 +608,6 @@ class FileSearchEngine {
let cancellation = new CancellationTokenSource();
return new PPromise((resolve, reject, onResult) => {
const options = this.getSearchOptionsForFolder(fq);
const folderStr = fq.folder.fsPath;
let filePatternSeen = false;
const tree = this.initDirectoryTree();
@@ -616,20 +619,19 @@ class FileSearchEngine {
return;
}
// This is slow...
if (noSiblingsClauses) {
if (relativePath === this.filePattern) {
filePatternSeen = true;
}
const basename = path.basename(relativePath);
this.matchFile(onResult, { base: folderStr, relativePath, basename });
this.matchFile(onResult, { base: fq.folder, relativePath, basename });
return;
}
// TODO: Optimize siblings clauses with ripgrep here.
this.addDirectoryEntries(tree, folderStr, relativePath, onResult);
this.addDirectoryEntries(tree, fq.folder, relativePath, onResult);
};
new TPromise(resolve => process.nextTick(resolve))
@@ -646,10 +648,10 @@ class FileSearchEngine {
if (noSiblingsClauses && this.isLimitHit) {
if (!filePatternSeen) {
// If the limit was hit, check whether filePattern is an exact relative match because it must be included
return this.checkFilePatternRelativeMatch(folderStr).then(({ exists, size }) => {
return this.checkFilePatternRelativeMatch(fq.folder).then(({ exists, size }) => {
if (exists) {
onResult({
base: folderStr,
base: fq.folder,
relativePath: this.filePattern,
basename: path.basename(this.filePattern),
});
@@ -658,7 +660,7 @@ class FileSearchEngine {
}
}
this.matchDirectoryTree(tree, folderStr, queryTester, onResult);
this.matchDirectoryTree(tree, queryTester, onResult);
return null;
}).then(
() => {
@@ -694,7 +696,7 @@ class FileSearchEngine {
return tree;
}
private addDirectoryEntries({ pathToEntries }: IDirectoryTree, base: string, relativeFile: string, onResult: (result: IInternalFileMatch) => void) {
private addDirectoryEntries({ pathToEntries }: IDirectoryTree, base: URI, relativeFile: string, onResult: (result: IInternalFileMatch) => void) {
// Support relative paths to files from a root resource (ignores excludes)
if (relativeFile === this.filePattern) {
const basename = path.basename(this.filePattern);
@@ -719,7 +721,7 @@ class FileSearchEngine {
add(relativeFile);
}
private matchDirectoryTree({ rootEntries, pathToEntries }: IDirectoryTree, rootFolder: string, queryTester: QueryGlobTester, onResult: (result: IInternalFileMatch) => void) {
private matchDirectoryTree({ rootEntries, pathToEntries }: IDirectoryTree, queryTester: QueryGlobTester, onResult: (result: IInternalFileMatch) => void) {
const self = this;
const filePattern = this.filePattern;
function matchDirectory(entries: IDirectoryEntry[]) {
@@ -794,12 +796,12 @@ class FileSearchEngine {
});
}
private checkFilePatternRelativeMatch(basePath: string): TPromise<{ exists: boolean, size?: number }> {
if (!this.filePattern || path.isAbsolute(this.filePattern)) {
private checkFilePatternRelativeMatch(base: URI): TPromise<{ exists: boolean, size?: number }> {
if (!this.filePattern || path.isAbsolute(this.filePattern) || base.scheme !== 'file') {
return TPromise.wrap({ exists: false });
}
const absolutePath = path.join(basePath, this.filePattern);
const absolutePath = path.join(base.fsPath, this.filePattern);
return this._pfs.stat(absolutePath).then(stat => {
return {
exists: !stat.isDirectory(),
@@ -894,7 +896,7 @@ class FileSearchManager {
private rawMatchToSearchItem(match: IInternalFileMatch): IFileMatch {
return {
resource: URI.file(match.base ? path.join(match.base, match.relativePath) : match.relativePath)
resource: joinPath(match.base, match.relativePath)
};
}

View File

@@ -12,7 +12,7 @@ import { asWinJsPromise } from 'vs/base/common/async';
import { Event, Emitter } from 'vs/base/common/event';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import * as TaskSystem from 'vs/workbench/parts/tasks/common/tasks';
import * as tasks from 'vs/workbench/parts/tasks/common/tasks';
import { MainContext, MainThreadTaskShape, ExtHostTaskShape, IMainContext } from 'vs/workbench/api/node/extHost.protocol';
@@ -21,8 +21,12 @@ 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
ShellExecutionOptionsDTO, ShellExecutionDTO, TaskDTO, TaskHandleDTO, TaskFilterDTO, TaskProcessStartedDTO, TaskProcessEndedDTO, TaskSystemInfoDTO
} from '../shared/tasks';
import { ExtHostVariableResolverService } from 'vs/workbench/api/node/extHostDebugService';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumentsAndEditors';
import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
export { TaskExecutionDTO };
@@ -197,40 +201,40 @@ namespace ProblemMatcher {
*/
namespace TaskRevealKind {
export function from(value: vscode.TaskRevealKind): TaskSystem.RevealKind {
export function from(value: vscode.TaskRevealKind): tasks.RevealKind {
if (value === void 0 || value === null) {
return TaskSystem.RevealKind.Always;
return tasks.RevealKind.Always;
}
switch (value) {
case types.TaskRevealKind.Silent:
return TaskSystem.RevealKind.Silent;
return tasks.RevealKind.Silent;
case types.TaskRevealKind.Never:
return TaskSystem.RevealKind.Never;
return tasks.RevealKind.Never;
}
return TaskSystem.RevealKind.Always;
return tasks.RevealKind.Always;
}
}
namespace TaskPanelKind {
export function from(value: vscode.TaskPanelKind): TaskSystem.PanelKind {
export function from(value: vscode.TaskPanelKind): tasks.PanelKind {
if (value === void 0 || value === null) {
return TaskSystem.PanelKind.Shared;
return tasks.PanelKind.Shared;
}
switch (value) {
case types.TaskPanelKind.Dedicated:
return TaskSystem.PanelKind.Dedicated;
return tasks.PanelKind.Dedicated;
case types.TaskPanelKind.New:
return TaskSystem.PanelKind.New;
return tasks.PanelKind.New;
default:
return TaskSystem.PanelKind.Shared;
return tasks.PanelKind.Shared;
}
}
}
namespace PresentationOptions {
export function from(value: vscode.TaskPresentationOptions): TaskSystem.PresentationOptions {
export function from(value: vscode.TaskPresentationOptions): tasks.PresentationOptions {
if (value === void 0 || value === null) {
return { reveal: TaskSystem.RevealKind.Always, echo: true, focus: false, panel: TaskSystem.PanelKind.Shared };
return { reveal: tasks.RevealKind.Always, echo: true, focus: false, panel: tasks.PanelKind.Shared };
}
return {
reveal: TaskRevealKind.from(value.reveal),
@@ -259,11 +263,11 @@ 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): TaskSystem.CommandOptions {
export function from(value: vscode.ShellExecutionOptions | vscode.ProcessExecutionOptions): tasks.CommandOptions {
if (value === void 0 || value === null) {
return undefined;
}
let result: TaskSystem.CommandOptions = {
let result: tasks.CommandOptions = {
};
if (typeof value.cwd === 'string') {
result.cwd = value.cwd;
@@ -285,7 +289,7 @@ namespace CommandOptions {
}
namespace ShellQuoteOptions {
export function from(value: vscode.ShellQuotingOptions): TaskSystem.ShellQuotingOptions {
export function from(value: vscode.ShellQuotingOptions): tasks.ShellQuotingOptions {
if (value === void 0 || value === null) {
return undefined;
}
@@ -298,12 +302,12 @@ namespace ShellQuoteOptions {
}
namespace ShellConfiguration {
export function from(value: { executable?: string, shellArgs?: string[], quotes?: vscode.ShellQuotingOptions }): TaskSystem.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: TaskSystem.ShellConfiguration = {
let result: tasks.ShellConfiguration = {
executable: value.executable,
args: Strings.from(value.shellArgs),
quoting: ShellQuoteOptions.from(value.quotes)
@@ -313,7 +317,7 @@ namespace ShellConfiguration {
}
namespace ShellString {
export function from(value: (string | vscode.ShellQuotedString)[]): TaskSystem.CommandString[] {
export function from(value: (string | vscode.ShellQuotedString)[]): tasks.CommandString[] {
if (value === void 0 || value === null) {
return undefined;
}
@@ -323,11 +327,11 @@ namespace ShellString {
namespace Tasks {
export function from(tasks: vscode.Task[], rootFolder: vscode.WorkspaceFolder, extension: IExtensionDescription): TaskSystem.ContributedTask[] {
export function from(tasks: vscode.Task[], rootFolder: vscode.WorkspaceFolder, extension: IExtensionDescription): tasks.ContributedTask[] {
if (tasks === void 0 || tasks === null) {
return [];
}
let result: TaskSystem.ContributedTask[] = [];
let result: tasks.ContributedTask[] = [];
for (let task of tasks) {
let converted = fromSingle(task, rootFolder, extension);
if (converted) {
@@ -337,11 +341,11 @@ namespace Tasks {
return result;
}
function fromSingle(task: vscode.Task, rootFolder: vscode.WorkspaceFolder, extension: IExtensionDescription): TaskSystem.ContributedTask {
function fromSingle(task: vscode.Task, rootFolder: vscode.WorkspaceFolder, extension: IExtensionDescription): tasks.ContributedTask {
if (typeof task.name !== 'string') {
return undefined;
}
let command: TaskSystem.CommandConfiguration;
let command: tasks.CommandConfiguration;
let execution = task.execution;
if (execution instanceof types.ProcessExecution) {
command = getProcessCommand(execution);
@@ -357,21 +361,21 @@ namespace Tasks {
let taskScope: types.TaskScope.Global | types.TaskScope.Workspace | vscode.WorkspaceFolder | undefined = task.scope;
let workspaceFolder: vscode.WorkspaceFolder | undefined;
let scope: TaskSystem.TaskScope;
let scope: tasks.TaskScope;
// For backwards compatibility
if (taskScope === void 0) {
scope = TaskSystem.TaskScope.Folder;
scope = tasks.TaskScope.Folder;
workspaceFolder = rootFolder;
} else if (taskScope === types.TaskScope.Global) {
scope = TaskSystem.TaskScope.Global;
scope = tasks.TaskScope.Global;
} else if (taskScope === types.TaskScope.Workspace) {
scope = TaskSystem.TaskScope.Workspace;
scope = tasks.TaskScope.Workspace;
} else {
scope = TaskSystem.TaskScope.Folder;
scope = tasks.TaskScope.Folder;
workspaceFolder = taskScope;
}
let source: TaskSystem.ExtensionTaskSource = {
kind: TaskSystem.TaskSourceKind.Extension,
let source: tasks.ExtensionTaskSource = {
kind: tasks.TaskSourceKind.Extension,
label: typeof task.source === 'string' ? task.source : extension.name,
extension: extension.id,
scope: scope,
@@ -380,17 +384,17 @@ namespace Tasks {
// 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 TaskSystem.ExtensionTaskSourceTransfer).__workspaceFolder = workspaceFolder ? workspaceFolder.uri as URI : undefined;
(source as any as tasks.ExtensionTaskSourceTransfer).__workspaceFolder = workspaceFolder ? workspaceFolder.uri as URI : undefined;
let label = nls.localize('task.label', '{0}: {1}', source.label, task.name);
let key = (task as types.Task).definitionKey;
let kind = (task as types.Task).definition;
let id = `${extension.id}.${key}`;
let taskKind: TaskSystem.TaskIdentifier = {
let taskKind: tasks.TaskIdentifier = {
_key: key,
type: kind.type
};
Objects.assign(taskKind, kind);
let result: TaskSystem.ContributedTask = {
let result: tasks.ContributedTask = {
_id: id, // uuidMap.getUUID(identifier),
_source: source,
_label: label,
@@ -407,14 +411,14 @@ namespace Tasks {
return result;
}
function getProcessCommand(value: vscode.ProcessExecution): TaskSystem.CommandConfiguration {
function getProcessCommand(value: vscode.ProcessExecution): tasks.CommandConfiguration {
if (typeof value.process !== 'string') {
return undefined;
}
let result: TaskSystem.CommandConfiguration = {
let result: tasks.CommandConfiguration = {
name: value.process,
args: Strings.from(value.args),
runtime: TaskSystem.RuntimeType.Process,
runtime: tasks.RuntimeType.Process,
suppressTaskName: true,
presentation: undefined
};
@@ -424,15 +428,15 @@ namespace Tasks {
return result;
}
function getShellCommand(value: vscode.ShellExecution): TaskSystem.CommandConfiguration {
function getShellCommand(value: vscode.ShellExecution): tasks.CommandConfiguration {
if (value.args) {
if (typeof value.command !== 'string' && typeof value.command.value !== 'string') {
return undefined;
}
let result: TaskSystem.CommandConfiguration = {
let result: tasks.CommandConfiguration = {
name: value.command,
args: ShellString.from(value.args),
runtime: TaskSystem.RuntimeType.Shell,
runtime: tasks.RuntimeType.Shell,
presentation: undefined
};
if (value.options) {
@@ -443,9 +447,9 @@ namespace Tasks {
if (typeof value.commandLine !== 'string') {
return undefined;
}
let result: TaskSystem.CommandConfiguration = {
let result: tasks.CommandConfiguration = {
name: value.commandLine,
runtime: TaskSystem.RuntimeType.Shell,
runtime: tasks.RuntimeType.Shell,
presentation: undefined
};
if (value.options) {
@@ -728,7 +732,9 @@ interface HandlerData {
export class ExtHostTask implements ExtHostTaskShape {
private _proxy: MainThreadTaskShape;
private _extHostWorkspace: ExtHostWorkspace;
private _workspaceService: ExtHostWorkspace;
private _editorService: ExtHostDocumentsAndEditors;
private _configurationService: ExtHostConfiguration;
private _handleCounter: number;
private _handlers: Map<number, HandlerData>;
private _taskExecutions: Map<string, TaskExecutionImpl>;
@@ -739,16 +745,18 @@ export class ExtHostTask implements ExtHostTaskShape {
private readonly _onDidTaskProcessStarted: Emitter<vscode.TaskProcessStartEvent> = new Emitter<vscode.TaskProcessStartEvent>();
private readonly _onDidTaskProcessEnded: Emitter<vscode.TaskProcessEndEvent> = new Emitter<vscode.TaskProcessEndEvent>();
constructor(mainContext: IMainContext, extHostWorkspace: ExtHostWorkspace) {
constructor(mainContext: IMainContext, workspaceService: ExtHostWorkspace, editorService: ExtHostDocumentsAndEditors, configurationService: ExtHostConfiguration) {
this._proxy = mainContext.getProxy(MainContext.MainThreadTask);
this._extHostWorkspace = extHostWorkspace;
this._workspaceService = workspaceService;
this._editorService = editorService;
this._configurationService = configurationService;
this._handleCounter = 0;
this._handlers = new Map<number, HandlerData>();
this._taskExecutions = new Map<string, TaskExecutionImpl>();
}
public get extHostWorkspace(): ExtHostWorkspace {
return this._extHostWorkspace;
return this._workspaceService;
}
public registerTaskProvider(extension: IExtensionDescription, provider: vscode.TaskProvider): vscode.Disposable {
@@ -764,11 +772,15 @@ export class ExtHostTask implements ExtHostTaskShape {
});
}
public registerTaskSystem(scheme: string, info: TaskSystemInfoDTO): void {
this._proxy.$registerTaskSystem(scheme, info);
}
public fetchTasks(filter?: vscode.TaskFilter): Thenable<vscode.Task[]> {
return this._proxy.$fetchTasks(TaskFilterDTO.from(filter)).then((values) => {
let result: vscode.Task[] = [];
for (let value of values) {
let task = TaskDTO.to(value, this._extHostWorkspace);
let task = TaskDTO.to(value, this._workspaceService);
if (task) {
result.push(task);
}
@@ -854,13 +866,13 @@ export class ExtHostTask implements ExtHostTaskShape {
}
}
public $provideTasks(handle: number): TPromise<TaskSystem.TaskSet> {
public $provideTasks(handle: number): TPromise<tasks.TaskSet> {
let handler = this._handlers.get(handle);
if (!handler) {
return TPromise.wrapError<TaskSystem.TaskSet>(new Error('no handler found'));
return TPromise.wrapError<tasks.TaskSet>(new Error('no handler found'));
}
return asWinJsPromise(token => handler.provider.provideTasks(token)).then(value => {
let workspaceFolders = this._extHostWorkspace.getWorkspaceFolders();
let workspaceFolders = this._workspaceService.getWorkspaceFolders();
return {
tasks: Tasks.from(value, workspaceFolders && workspaceFolders.length > 0 ? workspaceFolders[0] : undefined, handler.extension),
extension: handler.extension
@@ -868,6 +880,24 @@ export class ExtHostTask implements ExtHostTaskShape {
});
}
public $resolveVariables(uri: URI, variables: string[]): any {
let result = Object.create(null);
let workspaceFolder = this._workspaceService.resolveWorkspaceFolder(uri);
let resolver = new ExtHostVariableResolverService(this._workspaceService, this._editorService, this._configurationService);
let ws: IWorkspaceFolder = {
uri: workspaceFolder.uri,
name: workspaceFolder.name,
index: workspaceFolder.index,
toResource: () => {
throw new Error('Not implemented');
}
};
for (let variable of variables) {
result.push(variable, resolver.resolve(ws, variable));
}
return result;
}
private nextHandle(): number {
return this._handleCounter++;
}
@@ -881,7 +911,7 @@ export class ExtHostTask implements ExtHostTaskShape {
if (result) {
return result;
}
result = new TaskExecutionImpl(this, execution.id, task ? task : TaskDTO.to(execution.task, this._extHostWorkspace));
result = new TaskExecutionImpl(this, execution.id, task ? task : TaskDTO.to(execution.task, this._workspaceService));
this._taskExecutions.set(execution.id, result);
return result;
}

View File

@@ -11,7 +11,6 @@ import { TextEditorSelectionChangeKind } from './extHostTypes';
import * as TypeConverters from './extHostTypeConverters';
import { TextEditorDecorationType, ExtHostTextEditor } from './extHostTextEditor';
import { ExtHostDocumentsAndEditors } from './extHostDocumentsAndEditors';
import { Position as EditorPosition } from 'vs/platform/editor/common/editor';
import { MainContext, MainThreadTextEditorsShape, ExtHostEditorsShape, ITextDocumentShowOptions, ITextEditorPositionData, IMainContext, WorkspaceEditDto, IEditorPropertiesChangeData } from './extHost.protocol';
import * as vscode from 'vscode';
@@ -73,7 +72,6 @@ export class ExtHostEditors implements ExtHostEditorsShape {
};
} else {
options = {
position: EditorPosition.ONE,
preserveFocus: false
};
}

View File

@@ -116,11 +116,11 @@ class ExtHostTreeView<T> extends Disposable {
private _selectedElements: T[] = [];
get selectedElements(): T[] { return this._selectedElements; }
private _onDidExpandElement: Emitter<T> = this._register(new Emitter<T>());
readonly onDidExpandElement: Event<T> = this._onDidExpandElement.event;
private _onDidExpandElement: Emitter<vscode.TreeViewExpansionEvent<T>> = this._register(new Emitter<vscode.TreeViewExpansionEvent<T>>());
readonly onDidExpandElement: Event<vscode.TreeViewExpansionEvent<T>> = this._onDidExpandElement.event;
private _onDidCollapseElement: Emitter<T> = this._register(new Emitter<T>());
readonly onDidCollapseElement: Event<T> = this._onDidCollapseElement.event;
private _onDidCollapseElement: Emitter<vscode.TreeViewExpansionEvent<T>> = this._register(new Emitter<vscode.TreeViewExpansionEvent<T>>());
readonly onDidCollapseElement: Event<vscode.TreeViewExpansionEvent<T>> = this._onDidCollapseElement.event;
private refreshPromise: TPromise<void> = TPromise.as(null);
@@ -174,9 +174,9 @@ class ExtHostTreeView<T> extends Disposable {
const element = this.getExtensionElement(treeItemHandle);
if (element) {
if (expanded) {
this._onDidExpandElement.fire(element);
this._onDidExpandElement.fire({ element });
} else {
this._onDidCollapseElement.fire(element);
this._onDidCollapseElement.fire({ element });
}
}
}
@@ -362,7 +362,7 @@ class ExtHostTreeView<T> extends Disposable {
return item;
}
private createHandle(element: T, { id, label, resourceUri }: vscode.TreeItem, parent: TreeNode, first?: boolean): TreeItemHandle {
private createHandle(element: T, { id, label, resourceUri }: vscode.TreeItem, parent: TreeNode, returnFirst?: boolean): TreeItemHandle {
if (id) {
return `${ExtHostTreeView.ID_HANDLE_PREFIX}/${id}`;
}
@@ -373,14 +373,20 @@ class ExtHostTreeView<T> extends Disposable {
const existingHandle = this.nodes.has(element) ? this.nodes.get(element).item.handle : void 0;
const childrenNodes = (this.getChildrenNodes(parent) || []);
for (let counter = 0; counter <= childrenNodes.length; counter++) {
const handle = `${prefix}/${counter}:${elementId}`;
if (first || !this.elements.has(handle) || existingHandle === handle) {
return handle;
let handle: TreeItemHandle;
let counter = 0;
do {
handle = `${prefix}/${counter}:${elementId}`;
if (returnFirst || !this.elements.has(handle) || existingHandle === handle) {
// Return first if asked for or
// Return if handle does not exist or
// Return if handle is being reused
break;
}
}
counter++;
} while (counter <= childrenNodes.length);
throw new Error('This should not be reached');
return handle;
}
private getLightIconPath(extensionTreeItem: vscode.TreeItem): string {
@@ -457,7 +463,7 @@ class ExtHostTreeView<T> extends Disposable {
}
}
}
node.children = [];
node.children = void 0;
} else {
this.clearAll();
}

View File

@@ -6,7 +6,8 @@
import * as modes from 'vs/editor/common/modes';
import * as types from './extHostTypes';
import { Position as EditorPosition, ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { EditorViewColumn } from 'vs/workbench/api/shared/editor';
import { IDecorationOptions } from 'vs/editor/common/editorCommon';
import { EndOfLineSequence } from 'vs/editor/common/model';
import * as vscode from 'vscode';
@@ -156,29 +157,28 @@ export namespace DiagnosticSeverity {
}
export namespace ViewColumn {
export function from(column?: vscode.ViewColumn): EditorPosition {
let editorColumn = EditorPosition.ONE;
if (typeof column !== 'number') {
// stick with ONE
export function from(column?: vscode.ViewColumn): EditorViewColumn {
let editorColumn: EditorViewColumn;
if (column === <number>types.ViewColumn.One) {
editorColumn = 0;
} else if (column === <number>types.ViewColumn.Two) {
editorColumn = EditorPosition.TWO;
editorColumn = 1;
} else if (column === <number>types.ViewColumn.Three) {
editorColumn = EditorPosition.THREE;
} else if (column === <number>types.ViewColumn.Active) {
editorColumn = 2;
} else {
// in any other case (no column or ViewColumn.Active), leave the
// editorColumn as undefined which signals to use the active column
editorColumn = undefined;
}
return editorColumn;
}
export function to(position?: EditorPosition): vscode.ViewColumn {
if (typeof position !== 'number') {
return undefined;
}
if (position === EditorPosition.ONE) {
export function to(position?: EditorViewColumn): vscode.ViewColumn {
if (position === 0) {
return <number>types.ViewColumn.One;
} else if (position === EditorPosition.TWO) {
} else if (position === 1) {
return <number>types.ViewColumn.Two;
} else if (position === EditorPosition.THREE) {
} else if (position === 2) {
return <number>types.ViewColumn.Three;
}
return undefined;
@@ -381,7 +381,8 @@ export namespace HierarchicalSymbolInformation {
detail: info.parent.detail,
location: location.from(info.parent.location),
definingRange: Range.from(info.parent.range),
kind: SymbolKind.from(info.parent.kind)
kind: SymbolKind.from(info.parent.kind),
containerName: info.parent.containerName
};
if (info.children) {
result.children = info.children.map(from);

View File

@@ -903,6 +903,11 @@ export class Hierarchy<T> {
}
}
export enum CodeActionTrigger {
Automatic = 1,
Manual = 2,
}
export class CodeAction {
title: string;
@@ -1840,12 +1845,6 @@ export enum LogLevel {
}
//#region file api
// todo@remote
export enum DeprecatedFileChangeType {
Updated = 0,
Added = 1,
Deleted = 2
}
export enum FileChangeType {
Changed = 1,
@@ -1853,12 +1852,6 @@ export enum FileChangeType {
Deleted = 3,
}
export enum DeprecatedFileType {
File = 0,
Dir = 1,
Symlink = 2
}
export class FileSystemError extends Error {
static FileExists(messageOrUri?: string | URI): FileSystemError {

View File

@@ -7,7 +7,7 @@ import { MainContext, MainThreadWebviewsShape, IMainContext, ExtHostWebviewsShap
import * as vscode from 'vscode';
import { Event, Emitter } from 'vs/base/common/event';
import * as typeConverters from 'vs/workbench/api/node/extHostTypeConverters';
import { Position } from 'vs/platform/editor/common/editor';
import { EditorViewColumn } from 'vs/workbench/api/shared/editor';
import { TPromise } from 'vs/base/common/winjs.base';
import { Disposable } from './extHostTypes';
import URI from 'vs/base/common/uri';
@@ -248,7 +248,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
}
}
$onDidChangeWebviewPanelViewState(handle: WebviewPanelHandle, visible: boolean, position: Position): void {
$onDidChangeWebviewPanelViewState(handle: WebviewPanelHandle, visible: boolean, position: EditorViewColumn): void {
const panel = this.getWebviewPanel(handle);
if (panel) {
const viewColumn = typeConverters.ViewColumn.to(position);
@@ -274,7 +274,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
viewType: string,
title: string,
state: any,
position: Position,
position: EditorViewColumn,
options: vscode.WebviewOptions & vscode.WebviewPanelOptions
): Thenable<void> {
const serializer = this._serializers.get(viewType);

View File

@@ -0,0 +1,42 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IEditorGroupsService, IEditorGroup, GroupsOrder } from 'vs/workbench/services/group/common/editorGroupsService';
import { GroupIdentifier } from 'vs/workbench/common/editor';
import { ACTIVE_GROUP, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
// TODO@api this was previously a hardcoded list of editor positions (ONE, TWO, THREE)
// that with the introduction of grid editor feature is now unbounded. This should be
// revisited when the grid functionality is exposed to extensions,
export type EditorViewColumn = number;
export function viewColumnToEditorGroup(editorGroupService: IEditorGroupsService, position?: EditorViewColumn): GroupIdentifier {
if (typeof position !== 'number') {
return ACTIVE_GROUP; // prefer active group when position is undefined
}
const groups = editorGroupService.getGroups(GroupsOrder.CREATION_TIME);
let candidate = groups[position];
if (candidate) {
return candidate.id; // found direct match
}
let firstGroup = groups[0];
if (groups.length === 1 && firstGroup.count === 0) {
return firstGroup.id; // first editor should always open in first group
}
return SIDE_GROUP; // open to the side if group not found
}
export function editorGroupToViewColumn(editorGroupService: IEditorGroupsService, editorGroup: IEditorGroup | GroupIdentifier): EditorViewColumn {
const group = typeof editorGroup === 'number' ? editorGroupService.getGroup(editorGroup) : editorGroup;
return editorGroupService.getGroups(GroupsOrder.CREATION_TIME).indexOf(group);
}

View File

@@ -102,4 +102,8 @@ export interface TaskProcessEndedDTO {
export interface TaskFilterDTO {
version?: string;
type?: string;
}
export interface TaskSystemInfoDTO {
platform: string;
}