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

This commit is contained in:
Peng Lyu
2018-04-24 08:23:32 -07:00
1936 changed files with 33713 additions and 17924 deletions

View File

@@ -0,0 +1,99 @@
/*---------------------------------------------------------------------------------------------
* 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 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';
// -----------------------------------------------------------------
// The following commands are registered on both sides separately.
//
// We are trying to maintain backwards compatibility for cases where
// API commands are encoded as markdown links, for example.
// -----------------------------------------------------------------
export interface ICommandsExecutor {
executeCommand<T>(id: string, ...args: any[]): Thenable<T>;
}
function adjustHandler(handler: (executor: ICommandsExecutor, ...args: any[]) => any): ICommandHandler {
return (accessor, ...args: any[]) => {
return handler(accessor.get(ICommandService), ...args);
};
}
export class PreviewHTMLAPICommand {
public static ID = 'vscode.previewHtml';
public static execute(executor: ICommandsExecutor, uri: URI, position?: vscode.ViewColumn, label?: string, options?: any): Thenable<any> {
return executor.executeCommand('_workbench.previewHtml',
uri,
typeof position === 'number' && typeConverters.fromViewColumn(position),
label,
options
);
}
}
CommandsRegistry.registerCommand(PreviewHTMLAPICommand.ID, adjustHandler(PreviewHTMLAPICommand.execute));
export class OpenFolderAPICommand {
public static ID = 'vscode.openFolder';
public static execute(executor: ICommandsExecutor, uri?: URI, forceNewWindow?: boolean): Thenable<any> {
if (!uri) {
return executor.executeCommand('_files.pickFolderAndOpen', forceNewWindow);
}
return executor.executeCommand('_files.windowOpen', [uri.fsPath], forceNewWindow);
}
}
CommandsRegistry.registerCommand(OpenFolderAPICommand.ID, adjustHandler(OpenFolderAPICommand.execute));
export class DiffAPICommand {
public static ID = 'vscode.diff';
public static execute(executor: ICommandsExecutor, left: URI, right: URI, label: string, options?: vscode.TextDocumentShowOptions): Thenable<any> {
return executor.executeCommand('_workbench.diff', [
left, right,
label,
undefined,
typeConverters.toTextEditorOptions(options),
options ? typeConverters.fromViewColumn(options.viewColumn) : undefined
]);
}
}
CommandsRegistry.registerCommand(DiffAPICommand.ID, adjustHandler(DiffAPICommand.execute));
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;
if (columnOrOptions) {
if (typeof columnOrOptions === 'number') {
column = typeConverters.fromViewColumn(columnOrOptions);
} else {
options = typeConverters.toTextEditorOptions(columnOrOptions);
column = typeConverters.fromViewColumn(columnOrOptions.viewColumn);
}
}
return executor.executeCommand('_workbench.open', [
resource,
options,
column
]);
}
}
CommandsRegistry.registerCommand(OpenAPICommand.ID, adjustHandler(OpenAPICommand.execute));
export class RemoveFromRecentlyOpenedAPICommand {
public static ID = 'vscode.removeFromRecentlyOpened';
public static execute(executor: ICommandsExecutor, path: string): Thenable<any> {
return executor.executeCommand('_workbench.removeFromRecentlyOpened', path);
}
}
CommandsRegistry.registerCommand(RemoveFromRecentlyOpenedAPICommand.ID, adjustHandler(RemoveFromRecentlyOpenedAPICommand.execute));

View File

@@ -54,11 +54,12 @@ import { ExtHostFileSystem } from 'vs/workbench/api/node/extHostFileSystem';
import { ExtHostDecorations } from 'vs/workbench/api/node/extHostDecorations';
import { toGlobPattern, toLanguageSelector } from 'vs/workbench/api/node/extHostTypeConverters';
import { ExtensionActivatedByAPI } from 'vs/workbench/api/node/extHostExtensionActivator';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import { OverviewRulerLane } from 'vs/editor/common/model';
import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService';
import { ExtHostWebviews } from 'vs/workbench/api/node/extHostWebview';
import { ExtHostComments } from './extHostComments';
import { ExtHostSearch } from './extHostSearch';
import { ExtHostUrls } from './extHostUrls';
export interface IExtensionApiFactory {
(extension: IExtensionDescription): typeof vscode;
@@ -99,6 +100,7 @@ export function createApiFactory(
const extHostHeapService = rpcProtocol.set(ExtHostContext.ExtHostHeapService, new ExtHostHeapService());
const extHostDecorations = rpcProtocol.set(ExtHostContext.ExtHostDecorations, new ExtHostDecorations(rpcProtocol));
const extHostWebviews = rpcProtocol.set(ExtHostContext.ExtHostWebviews, new ExtHostWebviews(rpcProtocol));
const extHostUrls = rpcProtocol.set(ExtHostContext.ExtHostUrls, new ExtHostUrls(rpcProtocol));
const extHostDocumentsAndEditors = rpcProtocol.set(ExtHostContext.ExtHostDocumentsAndEditors, new ExtHostDocumentsAndEditors(rpcProtocol));
const extHostDocuments = rpcProtocol.set(ExtHostContext.ExtHostDocuments, new ExtHostDocuments(rpcProtocol, extHostDocumentsAndEditors));
const extHostDocumentContentProviders = rpcProtocol.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(rpcProtocol, extHostDocumentsAndEditors, extHostLogService));
@@ -107,15 +109,16 @@ export function createApiFactory(
const extHostCommands = rpcProtocol.set(ExtHostContext.ExtHostCommands, new ExtHostCommands(rpcProtocol, extHostHeapService, extHostLogService));
const extHostTreeViews = rpcProtocol.set(ExtHostContext.ExtHostTreeViews, new ExtHostTreeViews(rpcProtocol.getProxy(MainContext.MainThreadTreeViews), extHostCommands));
rpcProtocol.set(ExtHostContext.ExtHostWorkspace, extHostWorkspace);
const extHostDebugService = rpcProtocol.set(ExtHostContext.ExtHostDebugService, new ExtHostDebugService(rpcProtocol, extHostWorkspace, extensionService));
const extHostDebugService = rpcProtocol.set(ExtHostContext.ExtHostDebugService, new ExtHostDebugService(rpcProtocol, extHostWorkspace, extensionService, extHostDocumentsAndEditors, extHostConfiguration));
rpcProtocol.set(ExtHostContext.ExtHostConfiguration, extHostConfiguration);
const extHostDiagnostics = rpcProtocol.set(ExtHostContext.ExtHostDiagnostics, new ExtHostDiagnostics(rpcProtocol));
const extHostLanguageFeatures = rpcProtocol.set(ExtHostContext.ExtHostLanguageFeatures, new ExtHostLanguageFeatures(rpcProtocol, extHostDocuments, extHostCommands, extHostHeapService, extHostDiagnostics));
const extHostLanguageFeatures = rpcProtocol.set(ExtHostContext.ExtHostLanguageFeatures, new ExtHostLanguageFeatures(rpcProtocol, null, extHostDocuments, extHostCommands, extHostHeapService, extHostDiagnostics));
const extHostFileSystem = rpcProtocol.set(ExtHostContext.ExtHostFileSystem, new ExtHostFileSystem(rpcProtocol, extHostLanguageFeatures));
const extHostFileSystemEvent = rpcProtocol.set(ExtHostContext.ExtHostFileSystemEventService, new ExtHostFileSystemEventService());
const extHostQuickOpen = rpcProtocol.set(ExtHostContext.ExtHostQuickOpen, new ExtHostQuickOpen(rpcProtocol, extHostWorkspace, extHostCommands));
const extHostTerminalService = rpcProtocol.set(ExtHostContext.ExtHostTerminalService, new ExtHostTerminalService(rpcProtocol));
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));
const extHostTask = rpcProtocol.set(ExtHostContext.ExtHostTask, new ExtHostTask(rpcProtocol, extHostWorkspace));
const extHostWindow = rpcProtocol.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(rpcProtocol));
rpcProtocol.set(ExtHostContext.ExtHostExtensionService, extensionService);
@@ -138,27 +141,30 @@ export function createApiFactory(
return function (extension: IExtensionDescription): typeof vscode {
if (!isFalsyOrEmpty(product.extensionAllowedProposedApi)
&& product.extensionAllowedProposedApi.indexOf(extension.id) >= 0
) {
// fast lane -> proposed api is available to all extensions
// that are listed in product.json-files
extension.enableProposedApi = true;
} else if (extension.enableProposedApi && !extension.isBuiltin) {
if (
!initData.environment.enableProposedApiForAll &&
initData.environment.enableProposedApiFor.indexOf(extension.id) < 0
) {
extension.enableProposedApi = false;
console.error(`Extension '${extension.id} cannot use PROPOSED API (must started out of dev or enabled via --enable-proposed-api)`);
} else {
// proposed api is available when developing or when an extension was explicitly
// spelled out via a command line argument
console.warn(`Extension '${extension.id}' uses PROPOSED API which is subject to change and removal without notice.`);
// Check document selectors for being overly generic. Technically this isn't a problem but
// in practice many extensions say they support `fooLang` but need fs-access to do so. Those
// extension should specify then the `file`-scheme, e.g `{ scheme: 'fooLang', language: 'fooLang' }`
// We only inform once, it is not a warning because we just want to raise awareness and because
// we cannot say if the extension is doing it right or wrong...
let checkSelector = (function () {
let done = initData.environment.extensionDevelopmentPath !== extension.extensionFolderPath;
function inform(selector: vscode.DocumentSelector) {
console.info(`Extension '${extension.id}' uses a document selector without scheme. Learn more about this: https://go.microsoft.com/fwlink/?linkid=872305`);
done = true;
}
}
return function perform(selector: vscode.DocumentSelector): vscode.DocumentSelector {
if (!done) {
if (Array.isArray(selector)) {
selector.forEach(perform);
} else if (typeof selector === 'string') {
inform(selector);
} else if (typeof selector.scheme === 'undefined') {
inform(selector);
}
}
return selector;
};
})();
// namespace: commands
const commands: typeof vscode.commands = {
@@ -248,63 +254,63 @@ export function createApiFactory(
match(selector: vscode.DocumentSelector, document: vscode.TextDocument): number {
return score(toLanguageSelector(selector), document.uri, document.languageId, true);
},
registerCodeActionsProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable {
return extHostLanguageFeatures.registerCodeActionProvider(selector, provider);
registerCodeActionsProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider, metadata?: vscode.CodeActionProviderMetadata): vscode.Disposable {
return extHostLanguageFeatures.registerCodeActionProvider(checkSelector(selector), provider, metadata);
},
registerCodeLensProvider(selector: vscode.DocumentSelector, provider: vscode.CodeLensProvider): vscode.Disposable {
return extHostLanguageFeatures.registerCodeLensProvider(selector, provider);
return extHostLanguageFeatures.registerCodeLensProvider(checkSelector(selector), provider);
},
registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable {
return extHostLanguageFeatures.registerDefinitionProvider(selector, provider);
return extHostLanguageFeatures.registerDefinitionProvider(checkSelector(selector), provider);
},
registerImplementationProvider(selector: vscode.DocumentSelector, provider: vscode.ImplementationProvider): vscode.Disposable {
return extHostLanguageFeatures.registerImplementationProvider(selector, provider);
return extHostLanguageFeatures.registerImplementationProvider(checkSelector(selector), provider);
},
registerTypeDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.TypeDefinitionProvider): vscode.Disposable {
return extHostLanguageFeatures.registerTypeDefinitionProvider(selector, provider);
return extHostLanguageFeatures.registerTypeDefinitionProvider(checkSelector(selector), provider);
},
registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider): vscode.Disposable {
return extHostLanguageFeatures.registerHoverProvider(selector, provider, extension.id);
return extHostLanguageFeatures.registerHoverProvider(checkSelector(selector), provider, extension.id);
},
registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable {
return extHostLanguageFeatures.registerDocumentHighlightProvider(selector, provider);
return extHostLanguageFeatures.registerDocumentHighlightProvider(checkSelector(selector), provider);
},
registerReferenceProvider(selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable {
return extHostLanguageFeatures.registerReferenceProvider(selector, provider);
return extHostLanguageFeatures.registerReferenceProvider(checkSelector(selector), provider);
},
registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable {
return extHostLanguageFeatures.registerRenameProvider(selector, provider, extension.enableProposedApi);
return extHostLanguageFeatures.registerRenameProvider(checkSelector(selector), provider);
},
registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable {
return extHostLanguageFeatures.registerDocumentSymbolProvider(selector, provider);
return extHostLanguageFeatures.registerDocumentSymbolProvider(checkSelector(selector), provider);
},
registerWorkspaceSymbolProvider(provider: vscode.WorkspaceSymbolProvider): vscode.Disposable {
return extHostLanguageFeatures.registerWorkspaceSymbolProvider(provider);
},
registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable {
return extHostLanguageFeatures.registerDocumentFormattingEditProvider(selector, provider);
return extHostLanguageFeatures.registerDocumentFormattingEditProvider(checkSelector(selector), provider);
},
registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable {
return extHostLanguageFeatures.registerDocumentRangeFormattingEditProvider(selector, provider);
return extHostLanguageFeatures.registerDocumentRangeFormattingEditProvider(checkSelector(selector), provider);
},
registerOnTypeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, firstTriggerCharacter: string, ...moreTriggerCharacters: string[]): vscode.Disposable {
return extHostLanguageFeatures.registerOnTypeFormattingEditProvider(selector, provider, [firstTriggerCharacter].concat(moreTriggerCharacters));
return extHostLanguageFeatures.registerOnTypeFormattingEditProvider(checkSelector(selector), provider, [firstTriggerCharacter].concat(moreTriggerCharacters));
},
registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, ...triggerCharacters: string[]): vscode.Disposable {
return extHostLanguageFeatures.registerSignatureHelpProvider(selector, provider, triggerCharacters);
return extHostLanguageFeatures.registerSignatureHelpProvider(checkSelector(selector), provider, triggerCharacters);
},
registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, ...triggerCharacters: string[]): vscode.Disposable {
return extHostLanguageFeatures.registerCompletionItemProvider(selector, provider, triggerCharacters);
return extHostLanguageFeatures.registerCompletionItemProvider(checkSelector(selector), provider, triggerCharacters);
},
registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable {
return extHostLanguageFeatures.registerDocumentLinkProvider(selector, provider);
return extHostLanguageFeatures.registerDocumentLinkProvider(checkSelector(selector), provider);
},
registerColorProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable {
return extHostLanguageFeatures.registerColorProvider(selector, provider);
return extHostLanguageFeatures.registerColorProvider(checkSelector(selector), provider);
},
registerFoldingRangeProvider(selector: vscode.DocumentSelector, provider: vscode.FoldingRangeProvider): vscode.Disposable {
return extHostLanguageFeatures.registerFoldingRangeProvider(checkSelector(selector), provider);
},
registerFoldingProvider: proposedApiFunction(extension, (selector: vscode.DocumentSelector, provider: vscode.FoldingProvider): vscode.Disposable => {
return extHostLanguageFeatures.registerFoldingProvider(selector, provider);
}),
setLanguageConfiguration: (language: string, configuration: vscode.LanguageConfiguration): vscode.Disposable => {
return extHostLanguageFeatures.setLanguageConfiguration(language, configuration);
}
@@ -318,6 +324,9 @@ export function createApiFactory(
get visibleTextEditors() {
return extHostEditors.getVisibleTextEditors();
},
get terminals() {
return proposedApiFunction(extension, extHostTerminalService.terminals);
},
showTextDocument(documentOrUri: vscode.TextDocument | vscode.Uri, columnOrOptions?: vscode.ViewColumn | vscode.TextDocumentShowOptions, preserveFocus?: boolean): TPromise<vscode.TextEditor> {
let documentPromise: TPromise<vscode.TextDocument>;
if (URI.isUri(documentOrUri)) {
@@ -353,6 +362,9 @@ export function createApiFactory(
onDidCloseTerminal(listener, thisArg?, disposables?) {
return extHostTerminalService.onDidCloseTerminal(listener, thisArg, disposables);
},
onDidOpenTerminal: proposedApiFunction(extension, (listener, thisArg?, disposables?) => {
return extHostTerminalService.onDidOpenTerminal(listener, thisArg, disposables);
}),
get state() {
return extHostWindow.state;
},
@@ -399,6 +411,9 @@ export function createApiFactory(
createOutputChannel(name: string): vscode.OutputChannel {
return extHostOutputService.createOutputChannel(name);
},
createWebviewPanel(viewType: string, title: string, column: vscode.ViewColumn, options: vscode.WebviewPanelOptions & vscode.WebviewOptions): vscode.WebviewPanel {
return extHostWebviews.createWebview(viewType, title, column, options, extension.extensionFolderPath);
},
createTerminal(nameOrOptions: vscode.TerminalOptions | string, shellPath?: string, shellArgs?: string[]): vscode.Terminal {
if (typeof nameOrOptions === 'object') {
return extHostTerminalService.createTerminalFromOptions(<vscode.TerminalOptions>nameOrOptions);
@@ -418,11 +433,11 @@ export function createApiFactory(
registerDecorationProvider: proposedApiFunction(extension, (provider: vscode.DecorationProvider) => {
return extHostDecorations.registerDecorationProvider(provider, extension.id);
}),
createWebview: proposedApiFunction(extension, (viewType: string, title: string, column: vscode.ViewColumn, options: vscode.WebviewOptions) => {
return extHostWebviews.createWebview(viewType, title, column, options, extension.extensionFolderPath);
registerWebviewPanelSerializer: proposedApiFunction(extension, (viewType: string, serializer: vscode.WebviewPanelSerializer) => {
return extHostWebviews.registerWebviewPanelSerializer(viewType, serializer);
}),
registerWebviewSerializer: proposedApiFunction(extension, (viewType: string, serializer: vscode.WebviewSerializer) => {
return extHostWebviews.registerWebviewSerializer(viewType, serializer);
registerProtocolHandler: proposedApiFunction(extension, (handler: vscode.ProtocolHandler) => {
return extHostUrls.registerProtocolHandler(extension.id, handler);
})
};
@@ -522,17 +537,14 @@ export function createApiFactory(
registerTaskProvider: (type: string, provider: vscode.TaskProvider) => {
return extHostTask.registerTaskProvider(extension, provider);
},
// fetchTasks: proposedApiFunction(extension, (): Thenable<vscode.Task[]> => {
// return extHostTask.executeTaskProvider();
// }),
// executeTask: proposedApiFunction(extension, (task: vscode.Task): Thenable<vscode.TaskExecution> => {
// return extHostTask.executeTask(extension, task);
// }),
fetchTasks: (): Thenable<vscode.Task[]> => {
return extHostTask.executeTaskProvider();
},
executeTask: (task: vscode.Task): Thenable<vscode.TaskExecution> => {
fetchTasks: proposedApiFunction(extension, (filter?: vscode.TaskFilter): Thenable<vscode.Task[]> => {
return extHostTask.fetchTasks(filter);
}),
executeTask: proposedApiFunction(extension, (task: vscode.Task): Thenable<vscode.TaskExecution> => {
return extHostTask.executeTask(extension, task);
}),
get taskExecutions(): vscode.TaskExecution[] {
return extHostTask.taskExecutions;
},
onDidStartTask: (listeners, thisArgs?, disposables?) => {
return extHostTask.onDidStartTask(listeners, thisArgs, disposables);
@@ -540,8 +552,11 @@ export function createApiFactory(
onDidEndTask: (listeners, thisArgs?, disposables?) => {
return extHostTask.onDidEndTask(listeners, thisArgs, disposables);
},
registerFileSystemProvider: proposedApiFunction(extension, (scheme, provider, newProvider?) => {
return extHostFileSystem.registerFileSystemProvider(scheme, provider, newProvider);
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 extHostFileSystem.registerSearchProvider(scheme, provider);
@@ -551,6 +566,7 @@ export function createApiFactory(
}),
registerWorkspaceCommentProvider: proposedApiFunction(extension, (provider: vscode.WorkspaceCommentProvider) => {
return exthostCommentProviders.registerWorkspaceCommentProvider(provider);
return extHostSearch.registerSearchProvider(scheme, provider);
})
};
@@ -656,6 +672,12 @@ export function createApiFactory(
SourceBreakpoint: extHostTypes.SourceBreakpoint,
StatusBarAlignment: extHostTypes.StatusBarAlignment,
SymbolInformation: extHostTypes.SymbolInformation,
HierarchicalSymbolInformation: class extends extHostTypes.HierarchicalSymbolInformation {
constructor(name, kind, keyof, range) {
checkProposedApiEnabled(extension);
super(name, kind, keyof, range);
}
},
SymbolKind: extHostTypes.SymbolKind,
SourceControlInputBoxValidationType: extHostTypes.SourceControlInputBoxValidationType,
TextDocumentSaveReason: extHostTypes.TextDocumentSaveReason,
@@ -685,13 +707,15 @@ export function createApiFactory(
ConfigurationTarget: extHostTypes.ConfigurationTarget,
RelativePattern: extHostTypes.RelativePattern,
DeprecatedFileChangeType: extHostTypes.DeprecatedFileChangeType,
DeprecatedFileType: extHostTypes.DeprecatedFileType,
FileChangeType: extHostTypes.FileChangeType,
FileType: extHostTypes.FileType,
FoldingRangeList: extHostTypes.FoldingRangeList,
FileSystemError: extHostTypes.FileSystemError,
FoldingRange: extHostTypes.FoldingRange,
FoldingRangeType: extHostTypes.FoldingRangeType,
CommentThreadCollapsibleState: extHostTypes.CommentThreadCollapsibleState
CommentThreadCollapsibleState: extHostTypes.CommentThreadCollapsibleState,
FoldingRangeKind: extHostTypes.FoldingRangeKind
};
};
}

View File

@@ -24,7 +24,7 @@ import * as editorCommon from 'vs/editor/common/editorCommon';
import * as modes from 'vs/editor/common/modes';
import { IConfigurationData, ConfigurationTarget, IConfigurationModel } from 'vs/platform/configuration/common/configuration';
import { IConfig, IAdapterExecutable } from 'vs/workbench/parts/debug/common/debug';
import { IConfig, IAdapterExecutable, ITerminalSettings } from 'vs/workbench/parts/debug/common/debug';
import { IPickOpenEntry, IPickOptions } from 'vs/platform/quickOpen/common/quickOpen';
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
@@ -42,18 +42,16 @@ import { ITreeItem } from 'vs/workbench/common/views';
import { ThemeColor } from 'vs/platform/theme/common/themeService';
import { IDisposable } from 'vs/base/common/lifecycle';
import { SerializedError } from 'vs/base/common/errors';
import { IStat, FileChangeType } from 'vs/platform/files/common/files';
import { IStat, FileChangeType, IWatchOptions, FileSystemProviderCapabilities, FileOptions } from 'vs/platform/files/common/files';
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
import { CommentRule, CharacterPair, EnterAction } from 'vs/editor/common/modes/languageConfiguration';
import { ISingleEditOperation } from 'vs/editor/common/model';
import { ILineMatch, IPatternInfo } from 'vs/platform/search/common/search';
import { LogLevel } from 'vs/platform/log/common/log';
import { TaskExecutionDTO, TaskDTO, TaskHandleDTO } from 'vs/workbench/api/shared/tasks';
import { TaskExecutionDTO, TaskDTO, TaskHandleDTO, TaskFilterDTO } from 'vs/workbench/api/shared/tasks';
export interface IEnvironment {
isExtensionDevelopmentDebug: boolean;
enableProposedApiForAll: boolean;
enableProposedApiFor: string | string[];
appRoot: string;
appSettingsHome: string;
disableExtensions: boolean;
@@ -281,7 +279,7 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable {
$registerHoverProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerDocumentHighlightProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerReferenceSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerQuickFixSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerQuickFixSupport(handle: number, selector: ISerializedDocumentFilter[], supportedKinds?: string[]): void;
$registerDocumentFormattingSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerRangeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerOnTypeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[], autoFormatTriggerCharacters: string[]): void;
@@ -291,7 +289,7 @@ export interface MainThreadLanguageFeaturesShape extends IDisposable {
$registerSignatureHelpProvider(handle: number, selector: ISerializedDocumentFilter[], triggerCharacter: string[]): void;
$registerDocumentLinkProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerDocumentColorProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerFoldingProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerFoldingRangeProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
$setLanguageConfiguration(handle: number, languageId: string, configuration: ISerializedLanguageConfiguration): void;
}
@@ -329,6 +327,12 @@ export interface MainThreadTerminalServiceShape extends IDisposable {
$hide(terminalId: number): void;
$sendText(terminalId: number, text: string, addNewLine: boolean): void;
$show(terminalId: number, preserveFocus: boolean): void;
$registerOnDataListener(terminalId: number): void;
$sendProcessTitle(terminalId: number, title: string): void;
$sendProcessData(terminalId: number, data: string): void;
$sendProcessPid(terminalId: number, pid: number): void;
$sendProcessExit(terminalId: number, exitCode: number): void;
}
export interface MyQuickPickItems extends IPickOpenEntry {
@@ -355,26 +359,35 @@ export interface MainThreadTelemetryShape extends IDisposable {
$publicLog(eventName: string, data?: any): void;
}
export type WebviewHandle = string;
export type WebviewPanelHandle = string;
export interface MainThreadWebviewsShape extends IDisposable {
$createWebview(handle: WebviewHandle, viewType: string, title: string, column: EditorPosition, options: vscode.WebviewOptions, extensionFolderPath: string): void;
$disposeWebview(handle: WebviewHandle): void;
$reveal(handle: WebviewHandle, column: EditorPosition): void;
$setTitle(handle: WebviewHandle, value: string): void;
$setHtml(handle: WebviewHandle, value: string): void;
$sendMessage(handle: WebviewHandle, value: any): Thenable<boolean>;
$createWebviewPanel(handle: WebviewPanelHandle, viewType: string, title: string, column: EditorPosition, options: vscode.WebviewPanelOptions & vscode.WebviewOptions, extensionFolderPath: string): void;
$disposeWebview(handle: WebviewPanelHandle): void;
$reveal(handle: WebviewPanelHandle, column: EditorPosition | undefined): void;
$setTitle(handle: WebviewPanelHandle, value: string): void;
$setHtml(handle: WebviewPanelHandle, value: string): void;
$postMessage(handle: WebviewPanelHandle, value: any): Thenable<boolean>;
$registerSerializer(viewType: string): void;
$unregisterSerializer(viewType: string): void;
}
export interface ExtHostWebviewsShape {
$onMessage(handle: WebviewHandle, message: any): void;
$onDidChangeWeviewViewState(handle: WebviewHandle, active: boolean, position: EditorPosition): void;
$onDidDisposeWeview(handle: WebviewHandle): Thenable<void>;
$deserializeWebview(newWebviewHandle: WebviewHandle, viewType: string, state: any, position: EditorPosition, options: vscode.WebviewOptions): Thenable<void>;
$serializeWebview(webviewHandle: WebviewHandle): Thenable<any>;
$onMessage(handle: WebviewPanelHandle, message: any): void;
$onDidChangeWebviewPanelViewState(handle: WebviewPanelHandle, active: boolean, position: EditorPosition): void;
$onDidDisposeWebviewPanel(handle: WebviewPanelHandle): Thenable<void>;
$deserializeWebviewPanel(newWebviewHandle: WebviewPanelHandle, viewType: string, title: string, state: any, position: EditorPosition, options: vscode.WebviewOptions): Thenable<void>;
$serializeWebviewPanel(webviewHandle: WebviewPanelHandle): Thenable<any>;
}
export interface MainThreadUrlsShape extends IDisposable {
$registerProtocolHandler(handle: number, extensionId: string): TPromise<void>;
$unregisterProtocolHandler(handle: number): TPromise<void>;
}
export interface ExtHostUrlsShape {
$handleExternalUri(handle: number, uri: UriComponents): TPromise<void>;
}
export interface MainThreadWorkspaceShape extends IDisposable {
@@ -390,18 +403,20 @@ export interface IFileChangeDto {
}
export interface MainThreadFileSystemShape extends IDisposable {
$registerFileSystemProvider(handle: number, scheme: string): void;
$registerFileSystemProvider(handle: number, scheme: string, capabilities: FileSystemProviderCapabilities): void;
$unregisterProvider(handle: number): void;
$onFileSystemChange(handle: number, resource: IFileChangeDto[]): void;
}
export interface MainThreadSearchShape extends IDisposable {
$registerSearchProvider(handle: number, scheme: string): void;
$unregisterProvider(handle: number): void;
$onFileSystemChange(handle: number, resource: IFileChangeDto[]): void;
$handleFindMatch(handle: number, session, data: UriComponents | [UriComponents, ILineMatch]): void;
}
export interface MainThreadTaskShape extends IDisposable {
$registerTaskProvider(handle: number): TPromise<void>;
$executeTaskProvider(): TPromise<TaskDTO[]>;
$fetchTasks(filter?: TaskFilterDTO): TPromise<TaskDTO[]>;
$executeTask(task: TaskHandleDTO | TaskDTO): TPromise<TaskExecutionDTO>;
$terminateTask(id: string): TPromise<void>;
$unregisterTaskProvider(handle: number): TPromise<void>;
@@ -471,6 +486,7 @@ export interface MainThreadSCMShape extends IDisposable {
export type DebugSessionUUID = string;
export interface MainThreadDebugServiceShape extends IDisposable {
$registerDebugTypes(debugTypes: string[]);
$acceptDAMessage(handle: number, message: DebugProtocol.ProtocolMessage);
$acceptDAError(handle: number, name: string, message: string, stack: string);
$acceptDAExit(handle: number, code: number, signal: string);
@@ -574,16 +590,18 @@ export interface ExtHostWorkspaceShape {
export interface ExtHostFileSystemShape {
$stat(handle: number, resource: UriComponents): TPromise<IStat>;
$readFile(handle: number, resource: UriComponents): TPromise<string>;
$writeFile(handle: number, resource: UriComponents, base64Encoded: string): TPromise<void>;
$move(handle: number, resource: UriComponents, target: UriComponents): TPromise<IStat>;
$readFile(handle: number, resource: UriComponents, opts: FileOptions): TPromise<string>;
$writeFile(handle: number, resource: UriComponents, base64Encoded: string, opts: FileOptions): TPromise<void>;
$rename(handle: number, resource: UriComponents, target: UriComponents, opts: FileOptions): TPromise<IStat>;
$copy(handle: number, resource: UriComponents, target: UriComponents, opts: FileOptions): TPromise<IStat>;
$mkdir(handle: number, resource: UriComponents): TPromise<IStat>;
$readdir(handle: number, resource: UriComponents): TPromise<[UriComponents, IStat][]>;
$readdir(handle: number, resource: UriComponents): TPromise<[string, IStat][]>;
$delete(handle: number, resource: UriComponents): TPromise<void>;
$watch(handle: number, session: number, resource: UriComponents, opts: IWatchOptions): void;
$unwatch(handle: number, session: number): void;
}
export interface ExtHostSearchShape {
$provideFileSearchResults(handle: number, session: number, query: string): TPromise<void>;
$provideTextSearchResults(handle: number, session: number, pattern: IPatternInfo, options: { includes: string[], excludes: string[] }): TPromise<void>;
}
@@ -717,7 +735,7 @@ export interface ExtHostLanguageFeaturesShape {
$resolveWorkspaceSymbol(handle: number, symbol: SymbolInformationDto): TPromise<SymbolInformationDto>;
$releaseWorkspaceSymbols(handle: number, id: number): void;
$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string): TPromise<WorkspaceEditDto>;
$resolveRenameLocation(handle: number, resource: UriComponents, position: IPosition): TPromise<IRange>;
$resolveRenameLocation(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.RenameLocation>;
$provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.SuggestContext): TPromise<SuggestResultDto>;
$resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion>;
$releaseCompletionItems(handle: number, id: number): void;
@@ -726,7 +744,7 @@ export interface ExtHostLanguageFeaturesShape {
$resolveDocumentLink(handle: number, link: modes.ILink): TPromise<modes.ILink>;
$provideDocumentColors(handle: number, resource: UriComponents): TPromise<IRawColorInfo[]>;
$provideColorPresentations(handle: number, resource: UriComponents, colorInfo: IRawColorInfo): TPromise<modes.IColorPresentation[]>;
$provideFoldingRanges(handle: number, resource: UriComponents, context: modes.FoldingContext): TPromise<modes.IFoldingRangeList>;
$provideFoldingRanges(handle: number, resource: UriComponents, context: modes.FoldingContext): TPromise<modes.FoldingRange[]>;
}
export interface ExtHostQuickOpenShape {
@@ -734,9 +752,23 @@ export interface ExtHostQuickOpenShape {
$validateInput(input: string): TPromise<string>;
}
export interface ShellLaunchConfigDto {
name?: string;
executable?: string;
args?: string[] | string;
cwd?: string;
env?: { [key: string]: string };
}
export interface ExtHostTerminalServiceShape {
$acceptTerminalClosed(id: number): void;
$acceptTerminalOpened(id: number, name: string): void;
$acceptTerminalProcessId(id: number, processId: number): void;
$acceptTerminalProcessData(id: number, data: string);
$createProcess(id: number, shellLaunchConfig: ShellLaunchConfigDto, cols: number, rows: number): void;
$acceptProcessInput(id: number, data: string): void;
$acceptProcessResize(id: number, cols: number, rows: number): void;
$acceptProcessShutdown(id: number): void;
}
export interface ExtHostSCMShape {
@@ -794,6 +826,8 @@ export interface ISourceMultiBreakpointDto {
}
export interface ExtHostDebugServiceShape {
$substituteVariables(folder: UriComponents | undefined, config: IConfig): TPromise<IConfig>;
$runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise<void>;
$startDASession(handle: number, debugType: string, adapterExecutableInfo: IAdapterExecutable | null): TPromise<void>;
$stopDASession(handle: number): TPromise<void>;
$sendDAMessage(handle: number, message: DebugProtocol.ProtocolMessage): TPromise<void>;
@@ -864,10 +898,12 @@ export const MainContext = {
MainThreadTelemetry: createMainId<MainThreadTelemetryShape>('MainThreadTelemetry'),
MainThreadTerminalService: createMainId<MainThreadTerminalServiceShape>('MainThreadTerminalService'),
MainThreadWebviews: createMainId<MainThreadWebviewsShape>('MainThreadWebviews'),
MainThreadUrls: createMainId<MainThreadUrlsShape>('MainThreadUrls'),
MainThreadWorkspace: createMainId<MainThreadWorkspaceShape>('MainThreadWorkspace'),
MainThreadFileSystem: createMainId<MainThreadFileSystemShape>('MainThreadFileSystem'),
MainThreadExtensionService: createMainId<MainThreadExtensionServiceShape>('MainThreadExtensionService'),
MainThreadSCM: createMainId<MainThreadSCMShape>('MainThreadSCM'),
MainThreadSearch: createMainId<MainThreadSearchShape>('MainThreadSearch'),
MainThreadTask: createMainId<MainThreadTaskShape>('MainThreadTask'),
MainThreadWindow: createMainId<MainThreadWindowShape>('MainThreadWindow'),
};
@@ -893,10 +929,13 @@ export const ExtHostContext = {
ExtHostLogService: createExtId<ExtHostLogServiceShape>('ExtHostLogService'),
ExtHostTerminalService: createExtId<ExtHostTerminalServiceShape>('ExtHostTerminalService'),
ExtHostSCM: createExtId<ExtHostSCMShape>('ExtHostSCM'),
ExtHostSearch: createExtId<ExtHostSearchShape>('ExtHostSearch'),
ExtHostTask: createExtId<ExtHostTaskShape>('ExtHostTask'),
ExtHostWorkspace: createExtId<ExtHostWorkspaceShape>('ExtHostWorkspace'),
ExtHostWindow: createExtId<ExtHostWindowShape>('ExtHostWindow'),
ExtHostWebviews: createExtId<ExtHostWebviewsShape>('ExtHostWebviews'),
ExtHostProgress: createMainId<ExtHostProgressShape>('ExtHostProgress'),
ExtHostComments: createMainId<ExtHostCommentsShape>('ExtHostComments')
ExtHostComments: createMainId<ExtHostCommentsShape>('ExtHostComments'),
ExtHostUrls: createExtId<ExtHostUrlsShape>('ExtHostUrls'),
ExtHostProgress: createMainId<ExtHostProgressShape>('ExtHostProgress')
};

View File

@@ -17,9 +17,9 @@ import * as modes from 'vs/editor/common/modes';
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 { Position as EditorPosition, ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { CustomCodeAction } from 'vs/workbench/api/node/extHostLanguageFeatures';
import { ExtHostTask } from './extHostTask';
import { ICommandsExecutor, PreviewHTMLAPICommand, OpenFolderAPICommand, DiffAPICommand, OpenAPICommand, RemoveFromRecentlyOpenedAPICommand } from './apiCommands';
export class ExtHostApiCommands {
@@ -121,7 +121,8 @@ export class ExtHostApiCommands {
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
{ name: 'position', description: 'Position in a text document', constraint: types.Position },
{ name: 'triggerCharacter', description: '(optional) Trigger completion when the user types the character, like `,` or `(`', constraint: value => value === void 0 || typeof value === 'string' }
{ name: 'triggerCharacter', description: '(optional) Trigger completion when the user types the character, like `,` or `(`', constraint: value => value === void 0 || typeof value === 'string' },
{ name: 'itemResolveCount', description: '(optional) Number of completions to resolve (too large numbers slow down completions)', constraint: value => value === void 0 || typeof value === 'number' }
],
returns: 'A promise that resolves to a CompletionList-instance.'
});
@@ -136,7 +137,8 @@ export class ExtHostApiCommands {
this._register('vscode.executeCodeLensProvider', this._executeCodeLensProvider, {
description: 'Execute CodeLens provider.',
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI }
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
{ name: 'itemResolveCount', description: '(optional) Number of lenses that should be resolved and returned. Will only retrun resolved lenses, will impact performance)', constraint: value => value === void 0 || typeof value === 'number' }
],
returns: 'A promise that resolves to an array of CodeLens-instances.'
});
@@ -194,92 +196,68 @@ export class ExtHostApiCommands {
],
returns: 'A promise that resolves to an array of ColorPresentation objects.'
});
this._register('vscode.previewHtml', (uri: URI, position?: vscode.ViewColumn, label?: string, options?: any) => {
return this._commands.executeCommand('_workbench.previewHtml',
uri,
typeof position === 'number' && typeConverters.fromViewColumn(position),
label,
options);
}, {
description: `
Render the html of the resource in an editor view.
See [working with the html preview](https://code.visualstudio.com/docs/extensionAPI/vscode-api-commands#working-with-the-html-preview) for more information about the html preview's intergration with the editor and for best practices for extension authors.
// -----------------------------------------------------------------
// The following commands are registered on both sides separately.
//
// We are trying to maintain backwards compatibility for cases where
// API commands are encoded as markdown links, for example.
// -----------------------------------------------------------------
type ICommandHandler = (...args: any[]) => any;
const adjustHandler = (handler: (executor: ICommandsExecutor, ...args: any[]) => any): ICommandHandler => {
return (...args: any[]) => {
return handler(this._commands, ...args);
};
};
this._register(PreviewHTMLAPICommand.ID, adjustHandler(PreviewHTMLAPICommand.execute), {
description: `
Render the HTML of the resource in an editor view.
See [working with the HTML preview](https://code.visualstudio.com/docs/extensionAPI/vscode-api-commands#working-with-the-html-preview) for more information about the HTML preview's integration with the editor and for best practices for extension authors.
`,
args: [
{ name: 'uri', description: 'Uri of the resource to preview.', constraint: value => value instanceof URI || typeof value === 'string' },
{ name: 'column', description: '(optional) Column in which to preview.', constraint: value => typeof value === 'undefined' || (typeof value === 'number' && typeof types.ViewColumn[value] === 'string') },
{ name: 'label', description: '(optional) An human readable string that is used as title for the preview.', constraint: v => typeof v === 'string' || typeof v === 'undefined' },
{ name: 'options', description: '(optional) Options for controlling webview environment.', constraint: v => typeof v === 'object' || typeof v === 'undefined' }
]
});
args: [
{ name: 'uri', description: 'Uri of the resource to preview.', constraint: value => value instanceof URI || typeof value === 'string' },
{ name: 'column', description: '(optional) Column in which to preview.', constraint: value => typeof value === 'undefined' || (typeof value === 'number' && typeof types.ViewColumn[value] === 'string') },
{ name: 'label', description: '(optional) An human readable string that is used as title for the preview.', constraint: v => typeof v === 'string' || typeof v === 'undefined' },
{ name: 'options', description: '(optional) Options for controlling webview environment.', constraint: v => typeof v === 'object' || typeof v === 'undefined' }
]
});
this._register('vscode.openFolder', (uri?: URI, forceNewWindow?: boolean) => {
if (!uri) {
return this._commands.executeCommand('_files.pickFolderAndOpen', forceNewWindow);
}
this._register(OpenFolderAPICommand.ID, adjustHandler(OpenFolderAPICommand.execute), {
description: 'Open a folder or workspace in the current window or new window depending on the newWindow argument. Note that opening in the same window will shutdown the current extension host process and start a new one on the given folder/workspace unless the newWindow parameter is set to true.',
args: [
{ name: 'uri', description: '(optional) Uri of the folder or workspace file to open. If not provided, a native dialog will ask the user for the folder', constraint: value => value === void 0 || value instanceof URI },
{ name: 'newWindow', description: '(optional) Whether to open the folder/workspace in a new window or the same. Defaults to opening in the same window.', constraint: value => value === void 0 || typeof value === 'boolean' }
]
});
return this._commands.executeCommand('_files.windowOpen', [uri.fsPath], forceNewWindow);
}, {
description: 'Open a folder or workspace in the current window or new window depending on the newWindow argument. Note that opening in the same window will shutdown the current extension host process and start a new one on the given folder/workspace unless the newWindow parameter is set to true.',
args: [
{ name: 'uri', description: '(optional) Uri of the folder or workspace file to open. If not provided, a native dialog will ask the user for the folder', constraint: value => value === void 0 || value instanceof URI },
{ name: 'newWindow', description: '(optional) Whether to open the folder/workspace in a new window or the same. Defaults to opening in the same window.', constraint: value => value === void 0 || typeof value === 'boolean' }
]
});
this._register(DiffAPICommand.ID, adjustHandler(DiffAPICommand.execute), {
description: 'Opens the provided resources in the diff editor to compare their contents.',
args: [
{ name: 'left', description: 'Left-hand side resource of the diff editor', constraint: URI },
{ name: 'right', description: 'Right-hand side resource of the diff editor', constraint: URI },
{ name: 'title', description: '(optional) Human readable title for the diff editor', constraint: v => v === void 0 || typeof v === 'string' },
{ name: 'options', description: '(optional) Editor options, see vscode.TextDocumentShowOptions' }
]
});
this._register('vscode.diff', (left: URI, right: URI, label: string, options?: vscode.TextDocumentShowOptions) => {
return this._commands.executeCommand('_workbench.diff', [
left, right,
label,
undefined,
typeConverters.toTextEditorOptions(options),
options ? typeConverters.fromViewColumn(options.viewColumn) : undefined
]);
}, {
description: 'Opens the provided resources in the diff editor to compare their contents.',
args: [
{ name: 'left', description: 'Left-hand side resource of the diff editor', constraint: URI },
{ name: 'right', description: 'Right-hand side resource of the diff editor', constraint: URI },
{ name: 'title', description: '(optional) Human readable title for the diff editor', constraint: v => v === void 0 || typeof v === 'string' },
{ name: 'options', description: '(optional) Editor options, see vscode.TextDocumentShowOptions' }
]
});
this._register(OpenAPICommand.ID, adjustHandler(OpenAPICommand.execute), {
description: 'Opens the provided resource in the editor. Can be a text or binary file, or a http(s) url. If you need more control over the options for opening a text file, use vscode.window.showTextDocument instead.',
args: [
{ name: 'resource', description: 'Resource to open', constraint: URI },
{ name: 'columnOrOptions', description: '(optional) Either the column in which to open or editor options, see vscode.TextDocumentShowOptions', constraint: v => v === void 0 || typeof v === 'number' || typeof v === 'object' }
]
});
this._register('vscode.open', (resource: URI, columnOrOptions?: vscode.ViewColumn | vscode.TextDocumentShowOptions) => {
let options: ITextEditorOptions;
let column: EditorPosition;
if (columnOrOptions) {
if (typeof columnOrOptions === 'number') {
column = typeConverters.fromViewColumn(columnOrOptions);
} else {
options = typeConverters.toTextEditorOptions(columnOrOptions);
column = typeConverters.fromViewColumn(columnOrOptions.viewColumn);
}
}
return this._commands.executeCommand('_workbench.open', [
resource,
options,
column
]);
}, {
description: 'Opens the provided resource in the editor. Can be a text or binary file, or a http(s) url. If you need more control over the options for opening a text file, use vscode.window.showTextDocument instead.',
args: [
{ name: 'resource', description: 'Resource to open', constraint: URI },
{ name: 'columnOrOptions', description: '(optional) Either the column in which to open or editor options, see vscode.TextDocumentShowOptions', constraint: v => v === void 0 || typeof v === 'number' || typeof v === 'object' }
]
});
this._register('vscode.removeFromRecentlyOpened', (path: string) => {
return this._commands.executeCommand('_workbench.removeFromRecentlyOpened', path);
}, {
description: 'Removes an entry with the given path from the recently opened list.',
args: [
{ name: 'path', description: 'Path to remove from recently opened.', constraint: value => typeof value === 'string' }
]
});
this._register(RemoveFromRecentlyOpenedAPICommand.ID, adjustHandler(RemoveFromRecentlyOpenedAPICommand.execute), {
description: 'Removes an entry with the given path from the recently opened list.',
args: [
{ name: 'path', description: 'Path to remove from recently opened.', constraint: value => typeof value === 'string' }
]
});
}
// --- command impl
@@ -392,11 +370,12 @@ export class ExtHostApiCommands {
});
}
private _executeCompletionItemProvider(resource: URI, position: types.Position, triggerCharacter: string): Thenable<types.CompletionList> {
private _executeCompletionItemProvider(resource: URI, position: types.Position, triggerCharacter: string, maxItemsToResolve: number): Thenable<types.CompletionList> {
const args = {
resource,
position: position && typeConverters.fromPosition(position),
triggerCharacter
triggerCharacter,
maxItemsToResolve
};
return this._commands.executeCommand<modes.ISuggestResult>('_executeCompletionItemProvider', args).then(result => {
if (result) {
@@ -470,8 +449,8 @@ export class ExtHostApiCommands {
}));
}
private _executeCodeLensProvider(resource: URI): Thenable<vscode.CodeLens[]> {
const args = { resource };
private _executeCodeLensProvider(resource: URI, itemResolveCount: number): Thenable<vscode.CodeLens[]> {
const args = { resource, itemResolveCount };
return this._commands.executeCommand<modes.ICodeLensSymbol[]>('_executeCodeLensProvider', args)
.then(tryMapWith(item => {
return new types.CodeLens(
@@ -517,7 +496,7 @@ export class ExtHostApiCommands {
}
private _executeTaskProvider(): Thenable<vscode.Task[]> {
return this._tasks.executeTaskProvider();
return this._tasks.fetchTasks();
}
}
@@ -528,4 +507,4 @@ function tryMapWith<T, R>(f: (x: T) => R) {
}
return undefined;
};
}
}

View File

@@ -14,7 +14,7 @@ import { ConfigurationTarget as ExtHostConfigurationTarget } from './extHostType
import { IConfigurationData, ConfigurationTarget, IConfigurationModel } from 'vs/platform/configuration/common/configuration';
import { Configuration, ConfigurationChangeEvent, ConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
import { WorkspaceConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels';
import { StrictResourceMap } from 'vs/base/common/map';
import { ResourceMap } from 'vs/base/common/map';
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
import { isObject } from 'vs/base/common/types';
@@ -209,7 +209,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
private _toConfigurationChangeEvent(data: IWorkspaceConfigurationChangeEventData): vscode.ConfigurationChangeEvent {
const changedConfiguration = new ConfigurationModel(data.changedConfiguration.contents, data.changedConfiguration.keys, data.changedConfiguration.overrides);
const changedConfigurationByResource: StrictResourceMap<ConfigurationModel> = new StrictResourceMap<ConfigurationModel>();
const changedConfigurationByResource: ResourceMap<ConfigurationModel> = new ResourceMap<ConfigurationModel>();
for (const key of Object.keys(data.changedConfigurationByResource)) {
const resource = URI.parse(key);
const model = data.changedConfigurationByResource[key];
@@ -225,11 +225,11 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
const defaultConfiguration = ExtHostConfiguration.parseConfigurationModel(data.defaults);
const userConfiguration = ExtHostConfiguration.parseConfigurationModel(data.user);
const workspaceConfiguration = ExtHostConfiguration.parseConfigurationModel(data.workspace);
const folders: StrictResourceMap<ConfigurationModel> = Object.keys(data.folders).reduce((result, key) => {
const folders: ResourceMap<ConfigurationModel> = Object.keys(data.folders).reduce((result, key) => {
result.set(URI.parse(key), ExtHostConfiguration.parseConfigurationModel(data.folders[key]));
return result;
}, new StrictResourceMap<ConfigurationModel>());
return new Configuration(defaultConfiguration, userConfiguration, workspaceConfiguration, folders, new ConfigurationModel(), new StrictResourceMap<ConfigurationModel>(), false);
}, new ResourceMap<ConfigurationModel>());
return new Configuration(defaultConfiguration, userConfiguration, workspaceConfiguration, folders, new ConfigurationModel(), new ResourceMap<ConfigurationModel>(), false);
}
private static parseConfigurationModel(model: IConfigurationModel): ConfigurationModel {

View File

@@ -4,6 +4,9 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as paths from 'vs/base/common/paths';
import { Schemas } from 'vs/base/common/network';
import URI, { UriComponents } from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { Event, Emitter } from 'vs/base/common/event';
import { asWinJsPromise } from 'vs/base/common/async';
@@ -11,15 +14,20 @@ import {
MainContext, MainThreadDebugServiceShape, ExtHostDebugServiceShape, DebugSessionUUID,
IMainContext, IBreakpointsDeltaDto, ISourceMultiBreakpointDto, IFunctionBreakpointDto
} from 'vs/workbench/api/node/extHost.protocol';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import * as vscode from 'vscode';
import URI, { UriComponents } from 'vs/base/common/uri';
import { Disposable, Position, Location, SourceBreakpoint, FunctionBreakpoint } from 'vs/workbench/api/node/extHostTypes';
import { generateUuid } from 'vs/base/common/uuid';
import { DebugAdapter, convertToVSCPaths, convertToDAPaths } from 'vs/workbench/parts/debug/node/debugAdapter';
import * as paths from 'vs/base/common/paths';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
import { IAdapterExecutable } from 'vs/workbench/parts/debug/common/debug';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumentsAndEditors';
import { IAdapterExecutable, ITerminalSettings, IDebuggerContribution, IConfig } from 'vs/workbench/parts/debug/common/debug';
import { getTerminalLauncher } 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 { IConfigurationResolverService } from '../../services/configurationResolver/common/configurationResolver';
import { IStringDictionary } from 'vs/base/common/collections';
import { ExtHostConfiguration } from './extHostConfiguration';
export class ExtHostDebugService implements ExtHostDebugServiceShape {
@@ -55,8 +63,15 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
private _debugAdapters: Map<number, DebugAdapter>;
private _variableResolver: IConfigurationResolverService;
constructor(mainContext: IMainContext, private _workspace: ExtHostWorkspace, private _extensionService: ExtHostExtensionService) {
constructor(mainContext: IMainContext,
private _workspace: ExtHostWorkspace,
private _extensionService: ExtHostExtensionService,
private _editorsService: ExtHostDocumentsAndEditors,
private _configurationService: ExtHostConfiguration
) {
this._handleCounter = 0;
this._handlers = new Map<number, vscode.DebugConfigurationProvider>();
@@ -80,6 +95,41 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
this._breakpointEventsActive = false;
this._debugAdapters = new Map<number, DebugAdapter>();
// register all debug extensions
const debugTypes: string[] = [];
for (const ed of this._extensionService.getAllExtensionDescriptions()) {
if (ed.contributes) {
const debuggers = <IDebuggerContribution[]>ed.contributes['debuggers'];
if (debuggers && debuggers.length > 0) {
for (const dbg of debuggers) {
// only debugger contributions with a "label" are considered a "main" debugger contribution
if (dbg.type && dbg.label) {
debugTypes.push(dbg.type);
}
}
}
}
}
if (debugTypes.length > 0) {
this._debugServiceProxy.$registerDebugTypes(debugTypes);
}
}
public $runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise<void> {
const terminalLauncher = getTerminalLauncher();
if (terminalLauncher) {
return terminalLauncher.runInTerminal(args, config);
}
return void 0;
}
public $substituteVariables(folderUri: UriComponents | undefined, config: IConfig): TPromise<IConfig> {
if (!this._variableResolver) {
this._variableResolver = new ExtHostVariableResolverService(this._workspace, this._editorsService, this._configurationService);
}
const folder = <IWorkspaceFolder>this.getFolder(folderUri);
return asWinJsPromise(token => DebugAdapter.substituteVariables(folder, config, this._variableResolver));
}
public $startDASession(handle: number, debugType: string, adpaterExecutable: IAdapterExecutable | null): TPromise<void> {
@@ -475,3 +525,70 @@ export class ExtHostDebugConsole implements vscode.DebugConsole {
this.append(value + '\n');
}
}
export class ExtHostVariableResolverService implements IConfigurationResolverService {
_serviceBrand: any;
_variableResolver: VariableResolver;
constructor(workspace: ExtHostWorkspace, editors: ExtHostDocumentsAndEditors, configuration: ExtHostConfiguration) {
this._variableResolver = new VariableResolver({
getFolderUri: (folderName: string): URI => {
const folders = workspace.getWorkspaceFolders();
const found = folders.filter(f => f.name === folderName);
if (found && found.length > 0) {
return found[0].uri;
}
return undefined;
},
getWorkspaceFolderCount: (): number => {
return workspace.getWorkspaceFolders().length;
},
getConfigurationValue: (folderUri: URI, section: string) => {
return configuration.getConfiguration(undefined, folderUri).get<string>(section);
},
getExecPath: (): string | undefined => {
return undefined; // does not exist in EH
},
getFilePath: (): string | undefined => {
const activeEditor = editors.activeEditor();
if (activeEditor) {
const resource = activeEditor.document.uri;
if (resource.scheme === Schemas.file) {
return paths.normalize(resource.fsPath, true);
}
}
return undefined;
},
getSelectedText: (): string | undefined => {
const activeEditor = editors.activeEditor();
if (activeEditor && !activeEditor.selection.isEmpty) {
return activeEditor.document.getText(activeEditor.selection);
}
return undefined;
},
getLineNumber: (): string => {
const activeEditor = editors.activeEditor();
if (activeEditor) {
return String(activeEditor.selection.end.line + 1);
}
return undefined;
}
}, process.env);
}
public resolve(root: IWorkspaceFolder, value: string): string;
public resolve(root: IWorkspaceFolder, value: string[]): string[];
public resolve(root: IWorkspaceFolder, value: IStringDictionary<string>): IStringDictionary<string>;
public resolve(root: IWorkspaceFolder, value: any): any {
return this._variableResolver.resolveAny(root ? root.uri : undefined, value);
}
public resolveAny<T>(root: IWorkspaceFolder, value: T, commandMapping?: IStringDictionary<string>): T {
return this._variableResolver.resolveAny(root ? root.uri : undefined, value, commandMapping);
}
public executeCommandVariables(configuration: any, variables: IStringDictionary<string>): TPromise<IStringDictionary<string>> {
throw new Error('findAndExecuteCommandVariables not implemented.');
}
}

View File

@@ -68,8 +68,7 @@ export class ExtHostDocumentData extends MirrorTextModel {
this._document = {
get uri() { return data._uri; },
get fileName() { return data._uri.fsPath; },
// todo@remote
// documents from other fs-provider must not be untitled
// todo@remote -> https://github.com/Microsoft/vscode/issues/48269
get isUntitled() { return data._uri.scheme !== 'file'; },
get languageId() { return data._languageId; },
get version() { return data._versionId; },

View File

@@ -6,15 +6,17 @@
import URI, { UriComponents } from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { MainContext, IMainContext, ExtHostFileSystemShape, MainThreadFileSystemShape } from './extHost.protocol';
import { Event, mapEvent } from 'vs/base/common/event';
import { MainContext, IMainContext, ExtHostFileSystemShape, MainThreadFileSystemShape, IFileChangeDto } from './extHost.protocol';
import * as vscode from 'vscode';
import { IStat } from 'vs/platform/files/common/files';
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 { IPatternInfo } from 'vs/platform/search/common/search';
import { values } from 'vs/base/common/map';
import { Range, FileType } from 'vs/workbench/api/node/extHostTypes';
import { Range, DeprecatedFileType, DeprecatedFileChangeType, FileChangeType } from 'vs/workbench/api/node/extHostTypes';
import { ExtHostLanguageFeatures } from 'vs/workbench/api/node/extHostLanguageFeatures';
import { Schemas } from 'vs/base/common/network';
class FsLinkProvider implements vscode.DocumentLinkProvider {
@@ -55,44 +57,88 @@ class FsLinkProvider implements vscode.DocumentLinkProvider {
}
}
class FileSystemProviderShim implements vscode.FileSystemProvider {
class FileSystemProviderShim implements vscode.FileSystemProvider2 {
onDidChangeFile: vscode.Event<vscode.FileChangeEvent[]>;
_version: 2;
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));
}
}
onDidChange?: vscode.Event<vscode.FileChange[]>;
constructor(private readonly _delegate: vscode.FileSystemProvider) {
this.onDidChange = this._delegate.onDidChange;
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);
return this._delegate.stat(resource).then(stat => FileSystemProviderShim._modernizeFileStat(stat));
}
rename(oldUri: vscode.Uri, newUri: vscode.Uri): Thenable<vscode.FileStat> {
return this._delegate.move(oldUri, newUri);
return this._delegate.move(oldUri, newUri).then(stat => FileSystemProviderShim._modernizeFileStat(stat));
}
readdir(resource: vscode.Uri): Thenable<[vscode.Uri, vscode.FileStat][]> {
return this._delegate.readdir(resource);
readDirectory(resource: vscode.Uri): Thenable<[string, vscode.FileStat][]> {
return this._delegate.readdir(resource).then(tuples => {
return tuples.map(tuple => <[string, vscode.FileStat]>[path.posix.basename(tuple[0].path), FileSystemProviderShim._modernizeFileStat(tuple[1])]);
});
}
private static _modernizeFileStat(stat: vscode.DeprecatedFileStat): vscode.FileStat {
let { mtime, size, type } = stat;
let isFile = false;
let isDirectory = false;
let isSymbolicLink = false;
// no support for bitmask, effectively no support for symlinks
switch (type) {
case DeprecatedFileType.Dir:
isDirectory = true;
break;
case DeprecatedFileType.File:
isFile = true;
break;
case DeprecatedFileType.Symlink:
isSymbolicLink = true;
break;
}
return { mtime, size, isFile, isDirectory, isSymbolicLink };
}
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, options: { recursive: boolean; }): Thenable<void> {
return this.stat(resource).then(stat => {
if (stat.type === FileType.Dir) {
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);
}
});
}
create(resource: vscode.Uri, options: { type: vscode.FileType; }): Thenable<vscode.FileStat> {
if (options.type === FileType.Dir) {
return this._delegate.mkdir(resource);
} else {
return this._delegate.write(resource, Buffer.from([])).then(() => this._delegate.stat(resource));
}
createDirectory(resource: vscode.Uri): Thenable<vscode.FileStat> {
return this._delegate.mkdir(resource).then(stat => FileSystemProviderShim._modernizeFileStat(stat));
}
// --- read/write
@@ -107,7 +153,8 @@ class FileSystemProviderShim implements vscode.FileSystemProvider2 {
return Buffer.concat(chunks);
});
}
writeFile(resource: vscode.Uri, content: Uint8Array): Thenable<void> {
writeFile(resource: vscode.Uri, content: Uint8Array, options: files.FileOptions): Thenable<void> {
return this._delegate.write(resource, content);
}
}
@@ -115,110 +162,137 @@ class FileSystemProviderShim implements vscode.FileSystemProvider2 {
export class ExtHostFileSystem implements ExtHostFileSystemShape {
private readonly _proxy: MainThreadFileSystemShape;
private readonly _fsProvider = new Map<number, vscode.FileSystemProvider2>();
private readonly _searchProvider = new Map<number, vscode.SearchProvider>();
private readonly _linkProvider = new FsLinkProvider();
private readonly _fsProvider = new Map<number, vscode.FileSystemProvider>();
private readonly _usedSchemes = new Set<string>();
private readonly _watches = new Map<number, IDisposable>();
private _handlePool: number = 0;
constructor(mainContext: IMainContext, extHostLanguageFeatures: ExtHostLanguageFeatures) {
this._proxy = mainContext.getProxy(MainContext.MainThreadFileSystem);
this._usedSchemes.add(Schemas.file);
this._usedSchemes.add(Schemas.untitled);
this._usedSchemes.add(Schemas.vscode);
this._usedSchemes.add(Schemas.inMemory);
this._usedSchemes.add(Schemas.internal);
this._usedSchemes.add(Schemas.http);
this._usedSchemes.add(Schemas.https);
this._usedSchemes.add(Schemas.mailto);
this._usedSchemes.add(Schemas.data);
extHostLanguageFeatures.registerDocumentLinkProvider('*', this._linkProvider);
}
registerFileSystemProvider(scheme: string, provider: vscode.FileSystemProvider, newProvider: vscode.FileSystemProvider2) {
if (newProvider && newProvider._version === 2) {
return this._doRegisterFileSystemProvider(scheme, newProvider);
} else {
return this._doRegisterFileSystemProvider(scheme, new FileSystemProviderShim(provider));
}
registerDeprecatedFileSystemProvider(scheme: string, provider: vscode.DeprecatedFileSystemProvider) {
return this.registerFileSystemProvider(scheme, new FileSystemProviderShim(provider), { isCaseSensitive: false });
}
private _doRegisterFileSystemProvider(scheme: string, provider: vscode.FileSystemProvider2) {
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`);
}
const handle = this._handlePool++;
this._linkProvider.add(scheme);
this._usedSchemes.add(scheme);
this._fsProvider.set(handle, provider);
this._proxy.$registerFileSystemProvider(handle, scheme);
let reg: IDisposable;
if (provider.onDidChange) {
reg = provider.onDidChange(event => this._proxy.$onFileSystemChange(handle, <any>event));
let capabilites = files.FileSystemProviderCapabilities.FileReadWrite;
if (options.isCaseSensitive) {
capabilites += files.FileSystemProviderCapabilities.PathCaseSensitive;
}
if (typeof provider.copy === 'function') {
capabilites += files.FileSystemProviderCapabilities.FileFolderCopy;
}
this._proxy.$registerFileSystemProvider(handle, scheme, capabilites);
const subscription = provider.onDidChangeFile(event => {
let mapped: IFileChangeDto[] = [];
for (const e of event) {
let { uri: resource, type } = e;
if (resource.scheme !== scheme) {
// dropping events for wrong scheme
continue;
}
let newType: files.FileChangeType;
switch (type) {
case FileChangeType.Changed:
newType = files.FileChangeType.UPDATED;
break;
case FileChangeType.Created:
newType = files.FileChangeType.ADDED;
break;
case FileChangeType.Deleted:
newType = files.FileChangeType.DELETED;
break;
}
mapped.push({ resource, type: newType });
}
this._proxy.$onFileSystemChange(handle, mapped);
});
return {
dispose: () => {
if (reg) {
reg.dispose();
}
subscription.dispose();
this._linkProvider.delete(scheme);
this._usedSchemes.delete(scheme);
this._fsProvider.delete(handle);
this._proxy.$unregisterProvider(handle);
}
};
}
registerSearchProvider(scheme: string, provider: vscode.SearchProvider) {
const handle = this._handlePool++;
this._searchProvider.set(handle, provider);
this._proxy.$registerSearchProvider(handle, scheme);
return {
dispose: () => {
this._searchProvider.delete(handle);
this._proxy.$unregisterProvider(handle);
}
};
$stat(handle: number, resource: UriComponents): TPromise<files.IStat, any> {
return asWinJsPromise(token => this._fsProvider.get(handle).stat(URI.revive(resource), {}, token));
}
$stat(handle: number, resource: UriComponents): TPromise<IStat, any> {
return asWinJsPromise(token => this._fsProvider.get(handle).stat(URI.revive(resource), token));
$readdir(handle: number, resource: UriComponents): TPromise<[string, files.IStat][], any> {
return asWinJsPromise(token => this._fsProvider.get(handle).readDirectory(URI.revive(resource), {}, token));
}
$readdir(handle: number, resource: UriComponents): TPromise<[UriComponents, IStat][], any> {
return asWinJsPromise(token => this._fsProvider.get(handle).readdir(URI.revive(resource), token));
}
$readFile(handle: number, resource: UriComponents): TPromise<string> {
$readFile(handle: number, resource: UriComponents, opts: files.FileOptions): TPromise<string> {
return asWinJsPromise(token => {
return this._fsProvider.get(handle).readFile(URI.revive(resource), token);
return this._fsProvider.get(handle).readFile(URI.revive(resource), opts, token);
}).then(data => {
return Buffer.isBuffer(data) ? data.toString('base64') : Buffer.from(data.buffer, data.byteOffset, data.byteLength).toString('base64');
});
}
$writeFile(handle: number, resource: UriComponents, base64Content: string): TPromise<void, any> {
return asWinJsPromise(token => this._fsProvider.get(handle).writeFile(URI.revive(resource), Buffer.from(base64Content, 'base64'), token));
}
$delete(handle: number, resource: UriComponents): TPromise<void, any> {
return asWinJsPromise(token => this._fsProvider.get(handle).delete(URI.revive(resource), { recursive: true }));
}
$move(handle: number, oldUri: UriComponents, newUri: UriComponents): TPromise<IStat, any> {
return asWinJsPromise(token => this._fsProvider.get(handle).rename(URI.revive(oldUri), URI.revive(newUri)));
}
$mkdir(handle: number, resource: UriComponents): TPromise<IStat, any> {
return asWinJsPromise(token => this._fsProvider.get(handle).create(URI.revive(resource), { type: FileType.Dir }));
$writeFile(handle: number, resource: UriComponents, base64Content: string, opts: files.FileOptions): TPromise<void, any> {
return asWinJsPromise(token => this._fsProvider.get(handle).writeFile(URI.revive(resource), Buffer.from(base64Content, 'base64'), opts, token));
}
$provideFileSearchResults(handle: number, session: number, query: string): TPromise<void> {
const provider = this._searchProvider.get(handle);
if (!provider.provideFileSearchResults) {
return TPromise.as(undefined);
}
const progress = {
report: (uri) => {
this._proxy.$handleFindMatch(handle, session, uri);
}
};
return asWinJsPromise(token => provider.provideFileSearchResults(query, progress, token));
$delete(handle: number, resource: UriComponents): TPromise<void, any> {
return asWinJsPromise(token => this._fsProvider.get(handle).delete(URI.revive(resource), {}, token));
}
$provideTextSearchResults(handle: number, session: number, pattern: IPatternInfo, options: { includes: string[], excludes: string[] }): TPromise<void> {
const provider = this._searchProvider.get(handle);
if (!provider.provideTextSearchResults) {
return TPromise.as(undefined);
$rename(handle: number, oldUri: UriComponents, newUri: UriComponents, opts: files.FileOptions): TPromise<files.IStat, any> {
return asWinJsPromise(token => this._fsProvider.get(handle).rename(URI.revive(oldUri), URI.revive(newUri), opts, token));
}
$copy(handle: number, oldUri: UriComponents, newUri: UriComponents, opts: files.FileOptions): TPromise<files.IStat, any> {
return asWinJsPromise(token => this._fsProvider.get(handle).copy(URI.revive(oldUri), URI.revive(newUri), opts, token));
}
$mkdir(handle: number, resource: UriComponents): TPromise<files.IStat, any> {
return asWinJsPromise(token => this._fsProvider.get(handle).createDirectory(URI.revive(resource), {}, token));
}
$watch(handle: number, session: number, resource: UriComponents, opts: files.IWatchOptions): void {
asWinJsPromise(token => {
let subscription = this._fsProvider.get(handle).watch(URI.revive(resource), opts);
this._watches.set(session, subscription);
});
}
$unwatch(handle: number, session: number): void {
let subscription = this._watches.get(session);
if (subscription) {
subscription.dispose();
this._watches.delete(session);
}
const progress = {
report: (data: vscode.TextSearchResult) => {
this._proxy.$handleFindMatch(handle, session, [data.uri, {
lineNumber: data.range.start.line,
preview: data.preview.leading + data.preview.matching + data.preview.trailing,
offsetAndLengths: [[data.preview.leading.length, data.preview.matching.length]]
}]);
}
};
return asWinJsPromise(token => provider.provideTextSearchResults(pattern, options, progress, token));
}
}

View File

@@ -9,7 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { mixin } from 'vs/base/common/objects';
import * as vscode from 'vscode';
import * as TypeConverters from 'vs/workbench/api/node/extHostTypeConverters';
import { Range, Disposable, CompletionList, SnippetString, CodeActionKind } from 'vs/workbench/api/node/extHostTypes';
import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, HierarchicalSymbolInformation } from 'vs/workbench/api/node/extHostTypes';
import { ISingleEditOperation } from 'vs/editor/common/model';
import * as modes from 'vs/editor/common/modes';
import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService';
@@ -22,6 +22,7 @@ import { regExpLeadsToEndlessLoop } from 'vs/base/common/strings';
import { IPosition } from 'vs/editor/common/core/position';
import { IRange } from 'vs/editor/common/core/range';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import { isObject } from 'vs/base/common/types';
// --- adapter
@@ -38,6 +39,9 @@ class OutlineAdapter {
provideDocumentSymbols(resource: URI): TPromise<SymbolInformationDto[]> {
let doc = this._documents.getDocumentData(resource).document;
return asWinJsPromise(token => this._provider.provideDocumentSymbols(doc, token)).then(value => {
if (value instanceof HierarchicalSymbolInformation) {
value = HierarchicalSymbolInformation.toFlatSymbolInformation(value);
}
if (Array.isArray(value)) {
return value.map(symbol => IdObject.mixin(TypeConverters.fromSymbolInformation(symbol)));
}
@@ -466,14 +470,14 @@ class NavigateTypeAdapter {
class RenameAdapter {
static supportsResolving(provider: vscode.RenameProvider2): boolean {
static supportsResolving(provider: vscode.RenameProvider): boolean {
return typeof provider.resolveRenameLocation === 'function';
}
private _documents: ExtHostDocuments;
private _provider: vscode.RenameProvider2;
private _provider: vscode.RenameProvider;
constructor(documents: ExtHostDocuments, provider: vscode.RenameProvider2) {
constructor(documents: ExtHostDocuments, provider: vscode.RenameProvider) {
this._documents = documents;
this._provider = provider;
}
@@ -506,7 +510,7 @@ class RenameAdapter {
});
}
resolveRenameLocation(resource: URI, position: IPosition): TPromise<IRange> {
resolveRenameLocation(resource: URI, position: IPosition): TPromise<modes.RenameLocation> {
if (typeof this._provider.resolveRenameLocation !== 'function') {
return TPromise.as(undefined);
}
@@ -514,15 +518,28 @@ class RenameAdapter {
let doc = this._documents.getDocumentData(resource).document;
let pos = TypeConverters.toPosition(position);
return asWinJsPromise(token => this._provider.resolveRenameLocation(doc, pos, token)).then(range => {
return asWinJsPromise(token => this._provider.resolveRenameLocation(doc, pos, token)).then(rangeOrLocation => {
let range: vscode.Range;
let text: string;
if (Range.isRange(rangeOrLocation)) {
range = rangeOrLocation;
text = doc.getText(rangeOrLocation);
} else if (isObject(rangeOrLocation)) {
range = rangeOrLocation.range;
text = rangeOrLocation.placeholder;
}
if (!range) {
return undefined;
}
if (range && (!range.isSingleLine || range.start.line !== pos.line)) {
console.warn('INVALID rename context, range must be single line and on the same line');
if (!range.contains(pos)) {
console.warn('INVALID rename location: range must contain position');
return undefined;
}
return TypeConverters.fromRange(range);
return { range: TypeConverters.fromRange(range), text };
});
}
}
@@ -803,16 +820,16 @@ class FoldingProviderAdapter {
constructor(
private _documents: ExtHostDocuments,
private _provider: vscode.FoldingProvider
private _provider: vscode.FoldingRangeProvider
) { }
provideFoldingRanges(resource: URI, context: modes.FoldingContext): TPromise<modes.IFoldingRangeList> {
provideFoldingRanges(resource: URI, context: modes.FoldingContext): TPromise<modes.FoldingRange[]> {
const doc = this._documents.getDocumentData(resource).document;
return asWinJsPromise(token => this._provider.provideFoldingRanges(doc, context, token)).then(list => {
if (!Array.isArray(list.ranges)) {
return asWinJsPromise(token => this._provider.provideFoldingRanges(doc, context, token)).then(ranges => {
if (!Array.isArray(ranges)) {
return void 0;
}
return TypeConverters.FoldingRangeList.from(list);
return ranges.map(TypeConverters.FoldingRange.from);
});
}
}
@@ -823,10 +840,15 @@ type Adapter = OutlineAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapt
| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter | TypeDefinitionAdapter
| ColorProviderAdapter | FoldingProviderAdapter;
export interface ISchemeTransformer {
transformOutgoing(scheme: string): string;
}
export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
private static _handlePool: number = 0;
private readonly _schemeTransformer: ISchemeTransformer;
private _proxy: MainThreadLanguageFeaturesShape;
private _documents: ExtHostDocuments;
private _commands: ExtHostCommands;
@@ -836,11 +858,13 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
constructor(
mainContext: IMainContext,
schemeTransformer: ISchemeTransformer,
documents: ExtHostDocuments,
commands: ExtHostCommands,
heapMonitor: ExtHostHeapService,
diagnostics: ExtHostDiagnostics
) {
this._schemeTransformer = schemeTransformer;
this._proxy = mainContext.getProxy(MainContext.MainThreadLanguageFeatures);
this._documents = documents;
this._commands = commands;
@@ -877,6 +901,9 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
}
private _transformScheme(scheme: string): string {
if (this._schemeTransformer && typeof scheme === 'string') {
return this._schemeTransformer.transformOutgoing(scheme);
}
return scheme;
}
@@ -1013,9 +1040,9 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
// --- quick fix
registerCodeActionProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable {
registerCodeActionProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider, metadata?: vscode.CodeActionProviderMetadata): vscode.Disposable {
const handle = this._addNewAdapter(new CodeActionAdapter(this._documents, this._commands.converter, this._diagnostics, provider));
this._proxy.$registerQuickFixSupport(handle, this._transformDocumentSelector(selector));
this._proxy.$registerQuickFixSupport(handle, this._transformDocumentSelector(selector), metadata && metadata.providedCodeActionKinds ? metadata.providedCodeActionKinds.map(kind => kind.value) : undefined);
return this._createDisposable(handle);
}
@@ -1078,9 +1105,9 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
// --- rename
registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider, canUseProposedApi = false): vscode.Disposable {
registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable {
const handle = this._addNewAdapter(new RenameAdapter(this._documents, provider));
this._proxy.$registerRenameSupport(handle, this._transformDocumentSelector(selector), canUseProposedApi && RenameAdapter.supportsResolving(provider));
this._proxy.$registerRenameSupport(handle, this._transformDocumentSelector(selector), RenameAdapter.supportsResolving(provider));
return this._createDisposable(handle);
}
@@ -1088,7 +1115,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._withAdapter(handle, RenameAdapter, adapter => adapter.provideRenameEdits(URI.revive(resource), position, newName));
}
$resolveRenameLocation(handle: number, resource: URI, position: IPosition): TPromise<IRange> {
$resolveRenameLocation(handle: number, resource: URI, position: IPosition): TPromise<modes.RenameLocation> {
return this._withAdapter(handle, RenameAdapter, adapter => adapter.resolveRenameLocation(resource, position));
}
@@ -1154,13 +1181,13 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColorPresentations(URI.revive(resource), colorInfo));
}
registerFoldingProvider(selector: vscode.DocumentSelector, provider: vscode.FoldingProvider): vscode.Disposable {
registerFoldingRangeProvider(selector: vscode.DocumentSelector, provider: vscode.FoldingRangeProvider): vscode.Disposable {
const handle = this._addNewAdapter(new FoldingProviderAdapter(this._documents, provider));
this._proxy.$registerFoldingProvider(handle, this._transformDocumentSelector(selector));
this._proxy.$registerFoldingRangeProvider(handle, this._transformDocumentSelector(selector));
return this._createDisposable(handle);
}
$provideFoldingRanges(handle: number, resource: UriComponents, context: vscode.FoldingContext): TPromise<modes.IFoldingRangeList> {
$provideFoldingRanges(handle: number, resource: UriComponents, context: vscode.FoldingContext): TPromise<modes.FoldingRange[]> {
return this._withAdapter(handle, FoldingProviderAdapter, adapter => adapter.provideFoldingRanges(URI.revive(resource), context));
}

View File

@@ -0,0 +1,64 @@
/*---------------------------------------------------------------------------------------------
* 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 { asWinJsPromise } from 'vs/base/common/async';
import { TPromise } from 'vs/base/common/winjs.base';
import { IPatternInfo } from 'vs/platform/search/common/search';
import * as vscode from 'vscode';
import { ExtHostSearchShape, IMainContext, MainContext, MainThreadSearchShape } from './extHost.protocol';
export class ExtHostSearch implements ExtHostSearchShape {
private readonly _proxy: MainThreadSearchShape;
private readonly _searchProvider = new Map<number, vscode.SearchProvider>();
private _handlePool: number = 0;
constructor(mainContext: IMainContext) {
this._proxy = mainContext.getProxy(MainContext.MainThreadSearch);
}
registerSearchProvider(scheme: string, provider: vscode.SearchProvider) {
const handle = this._handlePool++;
this._searchProvider.set(handle, provider);
this._proxy.$registerSearchProvider(handle, scheme);
return {
dispose: () => {
this._searchProvider.delete(handle);
this._proxy.$unregisterProvider(handle);
}
};
}
$provideFileSearchResults(handle: number, session: number, query: string): TPromise<void> {
const provider = this._searchProvider.get(handle);
if (!provider.provideFileSearchResults) {
return TPromise.as(undefined);
}
const progress = {
report: (uri) => {
this._proxy.$handleFindMatch(handle, session, uri);
}
};
return asWinJsPromise(token => provider.provideFileSearchResults(query, progress, token));
}
$provideTextSearchResults(handle: number, session: number, pattern: IPatternInfo, options: { includes: string[], excludes: string[] }): TPromise<void> {
const provider = this._searchProvider.get(handle);
if (!provider.provideTextSearchResults) {
return TPromise.as(undefined);
}
const progress = {
report: (data: vscode.TextSearchResult) => {
this._proxy.$handleFindMatch(handle, session, [data.uri, {
lineNumber: data.range.start.line,
preview: data.preview.leading + data.preview.matching + data.preview.trailing,
offsetAndLengths: [[data.preview.leading.length, data.preview.matching.length]]
}]);
}
};
return asWinJsPromise(token => provider.provideTextSearchResults(pattern, options, progress, token));
}
}

View File

@@ -21,7 +21,7 @@ import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import * as vscode from 'vscode';
import {
TaskDefinitionDTO, TaskExecutionDTO, TaskPresentationOptionsDTO, ProcessExecutionOptionsDTO, ProcessExecutionDTO,
ShellExecutionOptionsDTO, ShellExecutionDTO, TaskDTO, TaskHandleDTO
ShellExecutionOptionsDTO, ShellExecutionDTO, TaskDTO, TaskHandleDTO, TaskFilterDTO
} from '../shared/tasks';
export { TaskExecutionDTO };
@@ -675,6 +675,19 @@ namespace TaskDTO {
}
}
namespace TaskFilterDTO {
export function from(value: vscode.TaskFilter): TaskFilterDTO {
return value;
}
export function to(value: TaskFilterDTO): vscode.TaskFilter {
if (!value) {
return undefined;
}
return Objects.assign(Object.create(null), value);
}
}
class TaskExecutionImpl implements vscode.TaskExecution {
constructor(readonly _id: string, private readonly _task: vscode.Task, private readonly _tasks: ExtHostTask) {
}
@@ -711,6 +724,7 @@ export class ExtHostTask implements ExtHostTaskShape {
private _extHostWorkspace: ExtHostWorkspace;
private _handleCounter: number;
private _handlers: Map<number, HandlerData>;
private _taskExecutions: Map<string, TaskExecutionImpl>;
private readonly _onDidExecuteTask: Emitter<vscode.TaskStartEvent> = new Emitter<vscode.TaskStartEvent>();
private readonly _onDidTerminateTask: Emitter<vscode.TaskEndEvent> = new Emitter<vscode.TaskEndEvent>();
@@ -720,6 +734,7 @@ export class ExtHostTask implements ExtHostTaskShape {
this._extHostWorkspace = extHostWorkspace;
this._handleCounter = 0;
this._handlers = new Map<number, HandlerData>();
this._taskExecutions = new Map<string, TaskExecutionImpl>();
}
public get extHostWorkspace(): ExtHostWorkspace {
@@ -739,8 +754,8 @@ export class ExtHostTask implements ExtHostTaskShape {
});
}
public executeTaskProvider(): Thenable<vscode.Task[]> {
return this._proxy.$executeTaskProvider().then((values) => {
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);
@@ -756,22 +771,28 @@ export class ExtHostTask implements ExtHostTaskShape {
let tTask = (task as types.Task);
// We have a preserved ID. So the task didn't change.
if (tTask._id !== void 0) {
return this._proxy.$executeTask(TaskHandleDTO.from(tTask)).then(value => new TaskExecutionImpl(value.id, task, this));
return this._proxy.$executeTask(TaskHandleDTO.from(tTask)).then(value => this.getTaskExecution(value, task));
} else {
let dto = TaskDTO.from(task, extension);
if (dto === void 0) {
return Promise.reject(new Error('Task is not valid'));
}
return this._proxy.$executeTask(dto).then(value => new TaskExecutionImpl(value.id, task, this));
return this._proxy.$executeTask(dto).then(value => this.getTaskExecution(value, task));
}
}
public $taskStarted(execution: TaskExecutionDTO): void {
this._onDidExecuteTask.fire({
execution: TaskExecutionDTO.to(execution, this)
execution: this.getTaskExecution(execution)
});
}
get taskExecutions(): vscode.TaskExecution[] {
let result: vscode.TaskExecution[] = [];
this._taskExecutions.forEach(value => result.push(value));
return result;
}
get onDidStartTask(): Event<vscode.TaskStartEvent> {
return this._onDidExecuteTask.event;
}
@@ -784,8 +805,10 @@ export class ExtHostTask implements ExtHostTaskShape {
}
public $taskEnded(execution: TaskExecutionDTO): void {
const _execution = this.getTaskExecution(execution);
this._taskExecutions.delete(execution.id);
this._onDidTerminateTask.fire({
execution: TaskExecutionDTO.to(execution, this)
execution: _execution
});
}
@@ -810,4 +833,14 @@ export class ExtHostTask implements ExtHostTaskShape {
private nextHandle(): number {
return this._handleCounter++;
}
private getTaskExecution(execution: TaskExecutionDTO, task?: vscode.Task): TaskExecutionImpl {
let result: TaskExecutionImpl = this._taskExecutions.get(execution.id);
if (result) {
return result;
}
result = new TaskExecutionImpl(execution.id, task ? task : TaskDTO.to(execution.task, this._extHostWorkspace), this);
this._taskExecutions.set(execution.id, result);
return result;
}
}

View File

@@ -5,11 +5,18 @@
'use strict';
import * as vscode from 'vscode';
import * as cp from 'child_process';
import * as os from 'os';
import * as platform from 'vs/base/common/platform';
import * as terminalEnvironment from 'vs/workbench/parts/terminal/node/terminalEnvironment';
import Uri from 'vs/base/common/uri';
import { Event, Emitter } from 'vs/base/common/event';
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IMainContext } from './extHost.protocol';
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IMainContext, ShellLaunchConfigDto } from 'vs/workbench/api/node/extHost.protocol';
import { IMessageFromTerminalProcess } from 'vs/workbench/parts/terminal/node/terminal';
import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration';
import { ILogService } from 'vs/platform/log/common/log';
export class ExtHostTerminal implements vscode.Terminal {
private _name: string;
private _id: number;
private _proxy: MainThreadTerminalServiceShape;
@@ -18,23 +25,37 @@ export class ExtHostTerminal implements vscode.Terminal {
private _pidPromise: Promise<number>;
private _pidPromiseComplete: (value: number) => any;
private readonly _onData: Emitter<string> = new Emitter<string>();
public get onData(): Event<string> {
// Tell the main side to start sending data if it's not already
this._proxy.$registerOnDataListener(this._id);
return this._onData && this._onData.event;
}
constructor(
proxy: MainThreadTerminalServiceShape,
name?: string,
name: string = '',
id?: number
) {
this._proxy = proxy;
this._name = name;
if (id) {
this._id = id;
}
this._queuedRequests = [];
this._pidPromise = new Promise<number>(c => {
this._pidPromiseComplete = c;
});
}
public create(
shellPath?: string,
shellArgs?: string[],
cwd?: string,
env?: { [key: string]: string },
waitOnExit?: boolean
) {
this._name = name;
this._queuedRequests = [];
this._proxy = proxy;
this._pidPromise = new Promise<number>(c => {
this._pidPromiseComplete = c;
});
this._proxy.$createTerminal(name, shellPath, shellArgs, cwd, env, waitOnExit).then((id) => {
): void {
this._proxy.$createTerminal(this._name, shellPath, shellArgs, cwd, env, waitOnExit).then((id) => {
this._id = id;
this._queuedRequests.forEach((r) => {
r.run(this._proxy, this._id);
@@ -44,12 +65,10 @@ export class ExtHostTerminal implements vscode.Terminal {
}
public get name(): string {
this._checkDisposed();
return this._name;
}
public get processId(): Thenable<number> {
this._checkDisposed();
return this._pidPromise;
}
@@ -76,8 +95,15 @@ export class ExtHostTerminal implements vscode.Terminal {
}
public _setProcessId(processId: number): void {
this._pidPromiseComplete(processId);
this._pidPromiseComplete = null;
// The event may fire 2 times when the panel is restored
if (this._pidPromiseComplete) {
this._pidPromiseComplete(processId);
this._pidPromiseComplete = null;
}
}
public _fireOnData(data: string): void {
this._onData.fire(data);
}
private _queueApiRequest(callback: (...args: any[]) => void, args: any[]) {
@@ -97,43 +123,69 @@ export class ExtHostTerminal implements vscode.Terminal {
}
export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
private readonly _onDidCloseTerminal: Emitter<vscode.Terminal>;
private _proxy: MainThreadTerminalServiceShape;
private _terminals: ExtHostTerminal[];
private _terminals: ExtHostTerminal[] = [];
private _terminalProcesses: { [id: number]: cp.ChildProcess } = {};
constructor(mainContext: IMainContext) {
this._onDidCloseTerminal = new Emitter<vscode.Terminal>();
public get terminals(): ExtHostTerminal[] { return this._terminals; }
private readonly _onDidCloseTerminal: Emitter<vscode.Terminal> = new Emitter<vscode.Terminal>();
public get onDidCloseTerminal(): Event<vscode.Terminal> { return this._onDidCloseTerminal && this._onDidCloseTerminal.event; }
private readonly _onDidOpenTerminal: Emitter<vscode.Terminal> = new Emitter<vscode.Terminal>();
public get onDidOpenTerminal(): Event<vscode.Terminal> { return this._onDidOpenTerminal && this._onDidOpenTerminal.event; }
constructor(
mainContext: IMainContext,
private _extHostConfiguration: ExtHostConfiguration,
private _logService: ILogService
) {
this._proxy = mainContext.getProxy(MainContext.MainThreadTerminalService);
this._terminals = [];
}
public createTerminal(name?: string, shellPath?: string, shellArgs?: string[]): vscode.Terminal {
let terminal = new ExtHostTerminal(this._proxy, name, shellPath, shellArgs);
let terminal = new ExtHostTerminal(this._proxy, name);
terminal.create(shellPath, shellArgs);
this._terminals.push(terminal);
return terminal;
}
public createTerminalFromOptions(options: vscode.TerminalOptions): vscode.Terminal {
let terminal = new ExtHostTerminal(this._proxy, options.name, options.shellPath, options.shellArgs, options.cwd, options.env /*, options.waitOnExit*/);
let terminal = new ExtHostTerminal(this._proxy, options.name);
terminal.create(options.shellPath, options.shellArgs, options.cwd, options.env /*, options.waitOnExit*/);
this._terminals.push(terminal);
return terminal;
}
public get onDidCloseTerminal(): Event<vscode.Terminal> {
return this._onDidCloseTerminal && this._onDidCloseTerminal.event;
public $acceptTerminalProcessData(id: number, data: string): void {
let index = this._getTerminalIndexById(id);
if (index === null) {
return;
}
const terminal = this._terminals[index];
terminal._fireOnData(data);
}
public $acceptTerminalClosed(id: number): void {
let index = this._getTerminalIndexById(id);
if (index === null) {
// The terminal was not created by the terminal API, ignore it
return;
}
let terminal = this._terminals.splice(index, 1)[0];
this._onDidCloseTerminal.fire(terminal);
}
public $acceptTerminalOpened(id: number, name: string): void {
let index = this._getTerminalIndexById(id);
if (index !== null) {
// The terminal has already been created (via createTerminal*), only fire the event
this._onDidOpenTerminal.fire(this.terminals[index]);
return;
}
let terminal = new ExtHostTerminal(this._proxy, name, id);
this._terminals.push(terminal);
this._onDidOpenTerminal.fire(terminal);
}
public $acceptTerminalProcessId(id: number, processId: number): void {
let terminal = this._getTerminalById(id);
if (terminal) {
@@ -141,6 +193,99 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
}
}
public $createProcess(id: number, shellLaunchConfig: ShellLaunchConfigDto, cols: number, rows: number): void {
// TODO: This function duplicates a lot of TerminalProcessManager.createProcess, ideally
// they would be merged into a single implementation.
const terminalConfig = this._extHostConfiguration.getConfiguration('terminal.integrated');
const locale = terminalConfig.get('setLocaleVariables') ? platform.locale : undefined;
if (!shellLaunchConfig.executable) {
// TODO: This duplicates some of TerminalConfigHelper.mergeDefaultShellPathAndArgs and should be merged
// this._configHelper.mergeDefaultShellPathAndArgs(shellLaunchConfig);
const platformKey = platform.isWindows ? 'windows' : platform.isMacintosh ? 'osx' : 'linux';
const shellConfigValue: string = terminalConfig.get(`shell.${platformKey}`);
const shellArgsConfigValue: string = terminalConfig.get(`shellArgs.${platformKey}`);
shellLaunchConfig.executable = shellConfigValue;
shellLaunchConfig.args = shellArgsConfigValue;
}
// TODO: Base the cwd on the last active workspace root
// const lastActiveWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot('file');
// this.initialCwd = terminalEnvironment.getCwd(shellLaunchConfig, lastActiveWorkspaceRootUri, this._configHelper);
const initialCwd = os.homedir();
// TODO: Pull in and resolve config settings
// // Resolve env vars from config and shell
// const lastActiveWorkspaceRoot = this._workspaceContextService.getWorkspaceFolder(lastActiveWorkspaceRootUri);
// const platformKey = platform.isWindows ? 'windows' : (platform.isMacintosh ? 'osx' : 'linux');
// const envFromConfig = terminalEnvironment.resolveConfigurationVariables(this._configurationResolverService, { ...this._configHelper.config.env[platformKey] }, lastActiveWorkspaceRoot);
// const envFromShell = terminalEnvironment.resolveConfigurationVariables(this._configurationResolverService, { ...shellLaunchConfig.env }, lastActiveWorkspaceRoot);
// shellLaunchConfig.env = envFromShell;
// Merge process env with the env from config
const parentEnv = { ...process.env };
// terminalEnvironment.mergeEnvironments(parentEnv, envFromConfig);
// Continue env initialization, merging in the env from the launch
// config and adding keys that are needed to create the process
const env = terminalEnvironment.createTerminalEnv(parentEnv, shellLaunchConfig, initialCwd, locale, cols, rows);
let cwd = Uri.parse(require.toUrl('../../parts/terminal/node')).fsPath;
const options = { env, cwd, execArgv: [] };
// Fork the process and listen for messages
this._logService.debug(`Terminal process launching on ext host`, options);
this._terminalProcesses[id] = cp.fork(Uri.parse(require.toUrl('bootstrap')).fsPath, ['--type=terminal'], options);
this._terminalProcesses[id].on('message', (message: IMessageFromTerminalProcess) => {
switch (message.type) {
case 'pid': this._proxy.$sendProcessPid(id, <number>message.content); break;
case 'title': this._proxy.$sendProcessTitle(id, <string>message.content); break;
case 'data': this._proxy.$sendProcessData(id, <string>message.content); break;
}
});
this._terminalProcesses[id].on('exit', (exitCode) => this._onProcessExit(id, exitCode));
}
public $acceptProcessInput(id: number, data: string): void {
if (this._terminalProcesses[id].connected) {
this._terminalProcesses[id].send({ event: 'input', data });
}
}
public $acceptProcessResize(id: number, cols: number, rows: number): void {
if (this._terminalProcesses[id].connected) {
try {
this._terminalProcesses[id].send({ event: 'resize', cols, rows });
} catch (error) {
// We tried to write to a closed pipe / channel.
if (error.code !== 'EPIPE' && error.code !== 'ERR_IPC_CHANNEL_CLOSED') {
throw (error);
}
}
}
}
public $acceptProcessShutdown(id: number): void {
if (this._terminalProcesses[id].connected) {
this._terminalProcesses[id].send({ event: 'shutdown' });
}
}
private _onProcessExit(id: number, exitCode: number): void {
// Remove listeners
const process = this._terminalProcesses[id];
process.removeAllListeners('message');
process.removeAllListeners('exit');
// Remove process reference
delete this._terminalProcesses[id];
// Send exit event to main side
this._proxy.$sendProcessExit(id, exitCode);
}
private _getTerminalById(id: number): ExtHostTerminal {
let index = this._getTerminalIndexById(id);
return index !== null ? this._terminals[index] : null;
@@ -149,6 +294,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
private _getTerminalIndexById(id: number): number {
let index: number = null;
this._terminals.some((terminal, i) => {
// TODO: This shouldn't be cas
let thisId = (<any>terminal)._id;
if (thisId === id) {
index = i;
@@ -161,7 +307,6 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
}
class ApiRequest {
private _callback: (...args: any[]) => void;
private _args: any[];

View File

@@ -623,11 +623,9 @@ export namespace ProgressLocation {
}
}
export namespace FoldingRangeList {
export function from(rangeList: vscode.FoldingRangeList): modes.IFoldingRangeList {
return {
ranges: rangeList.ranges.map(r => ({ startLineNumber: r.startLine + 1, endLineNumber: r.endLine + 1, type: r.type }))
};
export namespace FoldingRange {
export function from(r: vscode.FoldingRange): modes.FoldingRange {
return { start: r.start + 1, end: r.end + 1, kind: r.kind };
}
}

View File

@@ -208,7 +208,7 @@ export class Position {
export class Range {
static isRange(thing: any): thing is Range {
static isRange(thing: any): thing is vscode.Range {
if (thing instanceof Range) {
return true;
}
@@ -876,6 +876,38 @@ export class SymbolInformation {
}
}
export class HierarchicalSymbolInformation {
name: string;
location: Location;
kind: SymbolKind;
range: Range;
children: HierarchicalSymbolInformation[];
constructor(name: string, kind: SymbolKind, location: Location, range: Range) {
this.name = name;
this.kind = kind;
this.location = location;
this.range = range;
this.children = [];
}
static toFlatSymbolInformation(info: HierarchicalSymbolInformation): SymbolInformation[] {
let result: SymbolInformation[] = [];
HierarchicalSymbolInformation._toFlatSymbolInformation(info, undefined, result);
return result;
}
private static _toFlatSymbolInformation(info: HierarchicalSymbolInformation, containerName: string, bucket: SymbolInformation[]): void {
bucket.push(new SymbolInformation(info.name, info.kind, containerName, new Location(info.location.uri, info.range)));
if (Array.isArray(info.children)) {
for (const child of info.children) {
HierarchicalSymbolInformation._toFlatSymbolInformation(child, info.name, bucket);
}
}
}
}
export class CodeAction {
title: string;
@@ -903,6 +935,8 @@ export class CodeActionKind {
public static readonly RefactorExtract = CodeActionKind.Refactor.append('extract');
public static readonly RefactorInline = CodeActionKind.Refactor.append('inline');
public static readonly RefactorRewrite = CodeActionKind.Refactor.append('rewrite');
public static readonly Source = CodeActionKind.Empty.append('source');
public static readonly SourceOrganizeImports = CodeActionKind.Source.append('organizeImports');
constructor(
public readonly value: string
@@ -1812,59 +1846,91 @@ export enum LogLevel {
//#region file api
// todo@remote
export enum FileChangeType {
export enum DeprecatedFileChangeType {
Updated = 0,
Added = 1,
Deleted = 2
}
export enum FileType {
export enum FileChangeType {
Changed = 1,
Created = 2,
Deleted = 3,
}
export enum DeprecatedFileType {
File = 0,
Dir = 1,
Symlink = 2
}
export class FileSystemError extends Error {
static FileExists(messageOrUri?: string | URI): FileSystemError {
return new FileSystemError(messageOrUri, 'EntryExists', FileSystemError.FileExists);
}
static FileNotFound(messageOrUri?: string | URI): FileSystemError {
return new FileSystemError(messageOrUri, 'EntryNotFound', FileSystemError.FileNotFound);
}
static FileNotADirectory(messageOrUri?: string | URI): FileSystemError {
return new FileSystemError(messageOrUri, 'EntryNotADirectory', FileSystemError.FileNotADirectory);
}
static FileIsADirectory(messageOrUri?: string | URI): FileSystemError {
return new FileSystemError(messageOrUri, 'EntryIsADirectory', FileSystemError.FileIsADirectory);
}
constructor(uriOrMessage?: string | URI, code?: string, terminator?: Function) {
super(URI.isUri(uriOrMessage) ? uriOrMessage.toString(true) : uriOrMessage);
this.name = code ? `${code} (FileSystemError)` : `FileSystemError`;
if (typeof Error.captureStackTrace === 'function' && typeof terminator === 'function') {
// nice stack traces
Error.captureStackTrace(this, terminator);
}
}
}
//#endregion
//#region folding api
export class FoldingRangeList {
ranges: FoldingRange[];
constructor(ranges: FoldingRange[]) {
this.ranges = ranges;
}
}
export class FoldingRange {
startLine: number;
start: number;
endLine: number;
end: number;
type?: FoldingRangeType | string;
kind?: FoldingRangeKind;
constructor(startLine: number, endLine: number, type?: FoldingRangeType | string) {
this.startLine = startLine;
this.endLine = endLine;
this.type = type;
constructor(start: number, end: number, kind?: FoldingRangeKind) {
this.start = start;
this.end = end;
this.kind = kind;
}
}
export enum FoldingRangeType {
export class FoldingRangeKind {
/**
* Folding range for a comment
* Kind for folding range representing a comment. The value of the kind is 'comment'.
*/
Comment = 'comment',
static readonly Comment = new FoldingRangeKind('comment');
/**
* Folding range for a imports or includes
* Kind for folding range representing a import. The value of the kind is 'imports'.
*/
Imports = 'imports',
static readonly Imports = new FoldingRangeKind('imports');
/**
* Folding range for a region (e.g. `#region`)
* Kind for folding range representing regions (for example marked by `#region`, `#endregion`).
* The value of the kind is 'region'.
*/
Region = 'region'
static readonly Region = new FoldingRangeKind('region');
/**
* Creates a new [FoldingRangeKind](#FoldingRangeKind).
*
* @param value of the kind.
*/
public constructor(public value: string) {
}
}
//#endregion

View File

@@ -0,0 +1,46 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import { MainContext, IMainContext, ExtHostUrlsShape, MainThreadUrlsShape } from './extHost.protocol';
import URI, { UriComponents } from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { toDisposable } from 'vs/base/common/lifecycle';
export class ExtHostUrls implements ExtHostUrlsShape {
private static HandlePool = 0;
private readonly _proxy: MainThreadUrlsShape;
private handlers = new Map<number, vscode.ProtocolHandler>();
constructor(
mainContext: IMainContext
) {
this._proxy = mainContext.getProxy(MainContext.MainThreadUrls);
}
registerProtocolHandler(extensionId: string, handler: vscode.ProtocolHandler): vscode.Disposable {
const handle = ExtHostUrls.HandlePool++;
this.handlers.set(handle, handler);
this._proxy.$registerProtocolHandler(handle, extensionId);
return toDisposable(() => {
this.handlers.delete(handle);
this._proxy.$unregisterProtocolHandler(handle);
});
}
$handleExternalUri(handle: number, uri: UriComponents): TPromise<void> {
const handler = this.handlers.get(handle);
if (!handler) {
return TPromise.as(null);
}
handler.handleUri(URI.revive(uri));
return TPromise.as(null);
}
}

View File

@@ -3,78 +3,36 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Emitter, Event } from 'vs/base/common/event';
import { TPromise } from 'vs/base/common/winjs.base';
import { Position } from 'vs/platform/editor/common/editor';
import * as typeConverters from 'vs/workbench/api/node/extHostTypeConverters';
import { MainContext, MainThreadWebviewsShape, IMainContext, ExtHostWebviewsShape, WebviewPanelHandle } from './extHost.protocol';
import * as vscode from 'vscode';
import { ExtHostWebviewsShape, IMainContext, MainContext, MainThreadWebviewsShape, WebviewHandle } from './extHost.protocol';
import * as types from './extHostTypes';
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 { TPromise } from 'vs/base/common/winjs.base';
import { Disposable } from './extHostTypes';
export class ExtHostWebview implements vscode.Webview {
private readonly _handle: WebviewHandle;
private readonly _viewType: string;
private readonly _handle: WebviewPanelHandle;
private readonly _proxy: MainThreadWebviewsShape;
private _title: string;
private _html: string;
private _options: vscode.WebviewOptions;
private _isDisposed: boolean = false;
private _viewColumn: vscode.ViewColumn;
private _active: boolean;
public readonly onMessageEmitter = new Emitter<any>();
public readonly onDidReceiveMessage: Event<any> = this.onMessageEmitter.event;
public readonly onDisposeEmitter = new Emitter<void>();
public readonly onDidDispose: Event<void> = this.onDisposeEmitter.event;
public readonly onDidChangeViewStateEmitter = new Emitter<vscode.WebviewOnDidChangeViewStateEvent>();
public readonly onDidChangeViewState: Event<vscode.WebviewOnDidChangeViewStateEvent> = this.onDidChangeViewStateEmitter.event;
readonly _onMessageEmitter = new Emitter<any>();
public readonly onDidReceiveMessage: Event<any> = this._onMessageEmitter.event;
constructor(
handle: WebviewHandle,
handle: WebviewPanelHandle,
proxy: MainThreadWebviewsShape,
viewType: string,
viewColumn: vscode.ViewColumn,
options: vscode.WebviewOptions
) {
this._handle = handle;
this._proxy = proxy;
this._viewType = viewType;
this._viewColumn = viewColumn;
this._options = options;
}
public dispose() {
if (this._isDisposed) {
return;
}
this._isDisposed = true;
this._proxy.$disposeWebview(this._handle);
this.onDisposeEmitter.dispose();
this.onMessageEmitter.dispose();
this.onDidChangeViewStateEmitter.dispose();
}
get viewType(): string {
this.assertNotDisposed();
return this._viewType;
}
get title(): string {
this.assertNotDisposed();
return this._title;
}
set title(value: string) {
this.assertNotDisposed();
if (this._title !== value) {
this._title = value;
this._proxy.$setTitle(this._handle, value);
}
dispose() {
this._onMessageEmitter.dispose();
}
get html(): string {
@@ -95,34 +53,127 @@ export class ExtHostWebview implements vscode.Webview {
return this._options;
}
public postMessage(message: any): Thenable<boolean> {
this.assertNotDisposed();
return this._proxy.$postMessage(this._handle, message);
}
private assertNotDisposed() {
if (this._isDisposed) {
throw new Error('Webview is disposed');
}
}
}
export class ExtHostWebviewPanel implements vscode.WebviewPanel {
private readonly _handle: WebviewPanelHandle;
private readonly _proxy: MainThreadWebviewsShape;
private readonly _viewType: string;
private _title: string;
private readonly _options: vscode.WebviewPanelOptions;
private readonly _webview: ExtHostWebview;
private _isDisposed: boolean = false;
private _viewColumn: vscode.ViewColumn;
private _visible: boolean = true;
readonly _onDisposeEmitter = new Emitter<void>();
public readonly onDidDispose: Event<void> = this._onDisposeEmitter.event;
readonly _onDidChangeViewStateEmitter = new Emitter<vscode.WebviewPanelOnDidChangeViewStateEvent>();
public readonly onDidChangeViewState: Event<vscode.WebviewPanelOnDidChangeViewStateEvent> = this._onDidChangeViewStateEmitter.event;
constructor(
handle: WebviewPanelHandle,
proxy: MainThreadWebviewsShape,
viewType: string,
title: string,
viewColumn: vscode.ViewColumn,
editorOptions: vscode.WebviewPanelOptions,
webview: ExtHostWebview
) {
this._handle = handle;
this._proxy = proxy;
this._viewType = viewType;
this._options = editorOptions;
this._viewColumn = viewColumn;
this._title = title;
this._webview = webview;
}
public dispose() {
if (this._isDisposed) {
return;
}
this._isDisposed = true;
this._onDisposeEmitter.fire();
this._proxy.$disposeWebview(this._handle);
this._webview.dispose();
this._onDisposeEmitter.dispose();
this._onDidChangeViewStateEmitter.dispose();
}
get webview() {
this.assertNotDisposed();
return this._webview;
}
get viewType(): string {
this.assertNotDisposed();
return this._viewType;
}
get title(): string {
this.assertNotDisposed();
return this._title;
}
set title(value: string) {
this.assertNotDisposed();
if (this._title !== value) {
this._title = value;
this._proxy.$setTitle(this._handle, value);
}
}
get options() {
return this._options;
}
get viewColumn(): vscode.ViewColumn {
this.assertNotDisposed();
return this._viewColumn;
}
get active(): boolean {
this.assertNotDisposed();
return this._active;
}
set viewColumn(value: vscode.ViewColumn) {
_setViewColumn(value: vscode.ViewColumn) {
this.assertNotDisposed();
this._viewColumn = value;
}
set active(value: boolean) {
get visible(): boolean {
this.assertNotDisposed();
this._active = value;
return this._visible;
}
_setVisible(value: boolean) {
this.assertNotDisposed();
this._visible = value;
}
public postMessage(message: any): Thenable<boolean> {
this.assertNotDisposed();
return this._proxy.$sendMessage(this._handle, message);
return this._proxy.$postMessage(this._handle, message);
}
public reveal(viewColumn: vscode.ViewColumn): void {
public reveal(viewColumn?: vscode.ViewColumn): void {
this.assertNotDisposed();
this._proxy.$reveal(this._handle, typeConverters.fromViewColumn(viewColumn));
this._proxy.$reveal(this._handle, viewColumn ? typeConverters.fromViewColumn(viewColumn) : undefined);
}
private assertNotDisposed() {
@@ -137,11 +188,11 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
private readonly _proxy: MainThreadWebviewsShape;
private readonly _webviews = new Map<WebviewHandle, ExtHostWebview>();
private readonly _serializers = new Map<string, vscode.WebviewSerializer>();
private readonly _webviewPanels = new Map<WebviewPanelHandle, ExtHostWebviewPanel>();
private readonly _serializers = new Map<string, vscode.WebviewPanelSerializer>();
constructor(
mainContext: IMainContext,
mainContext: IMainContext
) {
this._proxy = mainContext.getProxy(MainContext.MainThreadWebviews);
}
@@ -150,20 +201,21 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
viewType: string,
title: string,
viewColumn: vscode.ViewColumn,
options: vscode.WebviewOptions,
options: vscode.WebviewPanelOptions & vscode.WebviewOptions,
extensionFolderPath: string
): vscode.Webview {
): vscode.WebviewPanel {
const handle = ExtHostWebviews.webviewHandlePool++ + '';
this._proxy.$createWebview(handle, viewType, title, typeConverters.fromViewColumn(viewColumn), options, extensionFolderPath);
this._proxy.$createWebviewPanel(handle, viewType, title, typeConverters.fromViewColumn(viewColumn), options, extensionFolderPath);
const webview = new ExtHostWebview(handle, this._proxy, viewType, viewColumn, options);
this._webviews.set(handle, webview);
return webview;
const webview = new ExtHostWebview(handle, this._proxy, options);
const panel = new ExtHostWebviewPanel(handle, this._proxy, viewType, title, viewColumn, options, webview);
this._webviewPanels.set(handle, panel);
return panel;
}
registerWebviewSerializer(
registerWebviewPanelSerializer(
viewType: string,
serializer: vscode.WebviewSerializer
serializer: vscode.WebviewPanelSerializer
): vscode.Disposable {
if (this._serializers.has(viewType)) {
throw new Error(`Serializer for '${viewType}' already registered`);
@@ -172,74 +224,76 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
this._serializers.set(viewType, serializer);
this._proxy.$registerSerializer(viewType);
return new types.Disposable(() => {
return new Disposable(() => {
this._serializers.delete(viewType);
this._proxy.$unregisterSerializer(viewType);
});
}
$onMessage(handle: WebviewHandle, message: any): void {
const webview = this.getWebview(handle);
if (webview) {
webview.onMessageEmitter.fire(message);
$onMessage(handle: WebviewPanelHandle, message: any): void {
const panel = this.getWebviewPanel(handle);
if (panel) {
panel.webview._onMessageEmitter.fire(message);
}
}
$onDidChangeWeviewViewState(handle: WebviewHandle, active: boolean, position: Position): void {
const webview = this.getWebview(handle);
if (webview) {
$onDidChangeWebviewPanelViewState(handle: WebviewPanelHandle, visible: boolean, position: Position): void {
const panel = this.getWebviewPanel(handle);
if (panel) {
const viewColumn = typeConverters.toViewColumn(position);
if (webview.active !== active || webview.viewColumn !== viewColumn) {
webview.active = active;
webview.viewColumn = viewColumn;
webview.onDidChangeViewStateEmitter.fire({ active, viewColumn });
if (panel.visible !== visible || panel.viewColumn !== viewColumn) {
panel._setVisible(visible);
panel._setViewColumn(viewColumn);
panel._onDidChangeViewStateEmitter.fire({ webviewPanel: panel });
}
}
}
$onDidDisposeWeview(handle: WebviewHandle): Thenable<void> {
const webview = this.getWebview(handle);
if (webview) {
webview.onDisposeEmitter.fire();
this._webviews.delete(handle);
$onDidDisposeWebviewPanel(handle: WebviewPanelHandle): Thenable<void> {
const panel = this.getWebviewPanel(handle);
if (panel) {
panel.dispose();
this._webviewPanels.delete(handle);
}
return TPromise.as(void 0);
}
$deserializeWebview(
webviewHandle: WebviewHandle,
$deserializeWebviewPanel(
webviewHandle: WebviewPanelHandle,
viewType: string,
title: string,
state: any,
position: Position,
options: vscode.WebviewOptions
options: vscode.WebviewOptions & vscode.WebviewPanelOptions
): Thenable<void> {
const serializer = this._serializers.get(viewType);
if (!serializer) {
return TPromise.wrapError(new Error(`No serializer found for '${viewType}'`));
}
const revivedWebview = new ExtHostWebview(webviewHandle, this._proxy, viewType, typeConverters.toViewColumn(position), options);
this._webviews.set(webviewHandle, revivedWebview);
return serializer.deserializeWebview(revivedWebview, state);
const webview = new ExtHostWebview(webviewHandle, this._proxy, options);
const revivedPanel = new ExtHostWebviewPanel(webviewHandle, this._proxy, viewType, title, typeConverters.toViewColumn(position), options, webview);
this._webviewPanels.set(webviewHandle, revivedPanel);
return serializer.deserializeWebviewPanel(revivedPanel, state);
}
$serializeWebview(
webviewHandle: WebviewHandle
$serializeWebviewPanel(
webviewHandle: WebviewPanelHandle
): Thenable<any> {
const webview = this.getWebview(webviewHandle);
if (!webview) {
const panel = this.getWebviewPanel(webviewHandle);
if (!panel) {
return TPromise.as(undefined);
}
const serialzer = this._serializers.get(webview.viewType);
const serialzer = this._serializers.get(panel.viewType);
if (!serialzer) {
return TPromise.as(undefined);
}
return serialzer.serializeWebview(webview);
return serialzer.serializeWebviewPanel(panel);
}
private getWebview(handle: WebviewHandle): ExtHostWebview | undefined {
return this._webviews.get(handle);
private getWebviewPanel(handle: WebviewPanelHandle): ExtHostWebviewPanel | undefined {
return this._webviewPanels.get(handle);
}
}