mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-18 01:25:37 -05:00
Merge VS Code 1.23.1 (#1520)
This commit is contained in:
99
src/vs/workbench/api/node/apiCommands.ts
Normal file
99
src/vs/workbench/api/node/apiCommands.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. 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));
|
||||
@@ -46,6 +46,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||
import * as vscode from 'vscode';
|
||||
import * as paths from 'vs/base/common/paths';
|
||||
import * as files from 'vs/platform/files/common/files';
|
||||
import { MainContext, ExtHostContext, IInitData, IExtHostContext } from './extHost.protocol';
|
||||
import * as languageConfiguration from 'vs/editor/common/modes/languageConfiguration';
|
||||
import { TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions';
|
||||
@@ -55,10 +56,11 @@ 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 { ExtHostSearch } from './extHostSearch';
|
||||
import { ExtHostUrls } from './extHostUrls';
|
||||
|
||||
export interface IExtensionApiFactory {
|
||||
(extension: IExtensionDescription): typeof vscode;
|
||||
@@ -99,9 +101,10 @@ 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 extHostDocumentsAndEditors = rpcProtocol.set(ExtHostContext.ExtHostDocumentsAndEditors, new ExtHostDocumentsAndEditors(rpcProtocol, extHostWebviews));
|
||||
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));
|
||||
const extHostDocumentContentProviders = rpcProtocol.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(rpcProtocol, extHostDocumentsAndEditors, extHostLogService));
|
||||
const extHostDocumentSaveParticipant = rpcProtocol.set(ExtHostContext.ExtHostDocumentSaveParticipant, new ExtHostDocumentSaveParticipant(extHostLogService, extHostDocuments, rpcProtocol.getProxy(MainContext.MainThreadTextEditors)));
|
||||
const extHostEditors = rpcProtocol.set(ExtHostContext.ExtHostEditors, new ExtHostEditors(rpcProtocol, extHostDocumentsAndEditors));
|
||||
const extHostCommands = rpcProtocol.set(ExtHostContext.ExtHostCommands, new ExtHostCommands(rpcProtocol, extHostHeapService, extHostLogService));
|
||||
@@ -111,15 +114,17 @@ export function createApiFactory(
|
||||
//const extHostDebugService = rpcProtocol.set(ExtHostContext.ExtHostDebugService, new ExtHostDebugService(threadService, extHostWorkspace));
|
||||
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);
|
||||
const extHostProgress = rpcProtocol.set(ExtHostContext.ExtHostProgress, new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress)));
|
||||
|
||||
// Check that no named customers are missing
|
||||
const expected: ProxyIdentifier<any>[] = Object.keys(ExtHostContext).map((key) => ExtHostContext[key]);
|
||||
@@ -129,44 +134,51 @@ export function createApiFactory(
|
||||
const extHostMessageService = new ExtHostMessageService(rpcProtocol);
|
||||
const extHostDialogs = new ExtHostDialogs(rpcProtocol);
|
||||
const extHostStatusBar = new ExtHostStatusBar(rpcProtocol);
|
||||
const extHostProgress = new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress));
|
||||
const extHostOutputService = new ExtHostOutputService(rpcProtocol);
|
||||
const extHostLanguages = new ExtHostLanguages(rpcProtocol);
|
||||
|
||||
// Register API-ish commands
|
||||
ExtHostApiCommands.register(extHostCommands);
|
||||
ExtHostApiCommands.register(extHostCommands, extHostTask);
|
||||
|
||||
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 informOnce(selector: vscode.DocumentSelector) {
|
||||
if (!done) {
|
||||
console.info(`Extension '${extension.id}' uses a document selector without scheme. Learn more about this: https://go.microsoft.com/fwlink/?linkid=872305`);
|
||||
done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return function perform(selector: vscode.DocumentSelector): vscode.DocumentSelector {
|
||||
if (Array.isArray(selector)) {
|
||||
selector.forEach(perform);
|
||||
} else if (typeof selector === 'string') {
|
||||
informOnce(selector);
|
||||
} else {
|
||||
if (typeof selector.scheme === 'undefined') {
|
||||
informOnce(selector);
|
||||
}
|
||||
if (!extension.enableProposedApi && typeof selector.exclusive === 'boolean') {
|
||||
throwProposedApiError(extension);
|
||||
}
|
||||
}
|
||||
return selector;
|
||||
};
|
||||
})();
|
||||
|
||||
// namespace: commands
|
||||
const commands: typeof vscode.commands = {
|
||||
registerCommand(id: string, command: <T>(...args: any[]) => T | Thenable<T>, thisArgs?: any): vscode.Disposable {
|
||||
return extHostCommands.registerCommand(id, command, thisArgs);
|
||||
return extHostCommands.registerCommand(true, id, command, thisArgs);
|
||||
},
|
||||
registerTextEditorCommand(id: string, callback: (textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit, ...args: any[]) => void, thisArg?: any): vscode.Disposable {
|
||||
return extHostCommands.registerCommand(id, (...args: any[]): any => {
|
||||
return extHostCommands.registerCommand(true, id, (...args: any[]): any => {
|
||||
let activeTextEditor = extHostEditors.getActiveTextEditor();
|
||||
if (!activeTextEditor) {
|
||||
console.warn('Cannot execute ' + id + ' because there is no active text editor.');
|
||||
@@ -187,7 +199,7 @@ export function createApiFactory(
|
||||
});
|
||||
},
|
||||
registerDiffInformationCommand: proposedApiFunction(extension, (id: string, callback: (diff: vscode.LineChange[], ...args: any[]) => any, thisArg?: any): vscode.Disposable => {
|
||||
return extHostCommands.registerCommand(id, async (...args: any[]) => {
|
||||
return extHostCommands.registerCommand(true, id, async (...args: any[]) => {
|
||||
let activeTextEditor = extHostEditors.getActiveTextEditor();
|
||||
if (!activeTextEditor) {
|
||||
console.warn('Cannot execute ' + id + ' because there is no active text editor.');
|
||||
@@ -213,6 +225,7 @@ export function createApiFactory(
|
||||
get language() { return Platform.language; },
|
||||
get appName() { return product.nameLong; },
|
||||
get appRoot() { return initData.environment.appRoot; },
|
||||
get logLevel() { return extHostLogService.getLevel(); }
|
||||
});
|
||||
|
||||
// namespace: extensions
|
||||
@@ -234,69 +247,75 @@ export function createApiFactory(
|
||||
createDiagnosticCollection(name?: string): vscode.DiagnosticCollection {
|
||||
return extHostDiagnostics.createDiagnosticCollection(name);
|
||||
},
|
||||
get onDidChangeDiagnostics() {
|
||||
return extHostDiagnostics.onDidChangeDiagnostics;
|
||||
},
|
||||
getDiagnostics: (resource?) => {
|
||||
return <any>extHostDiagnostics.getDiagnostics(resource);
|
||||
},
|
||||
getLanguages(): TPromise<string[]> {
|
||||
return extHostLanguages.getLanguages();
|
||||
},
|
||||
match(selector: vscode.DocumentSelector, document: vscode.TextDocument): number {
|
||||
return score(toLanguageSelector(selector), document.uri, document.languageId);
|
||||
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);
|
||||
}
|
||||
@@ -310,6 +329,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)) {
|
||||
@@ -336,15 +358,18 @@ export function createApiFactory(
|
||||
onDidChangeTextEditorOptions(listener: (e: vscode.TextEditorOptionsChangeEvent) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) {
|
||||
return extHostEditors.onDidChangeTextEditorOptions(listener, thisArgs, disposables);
|
||||
},
|
||||
onDidChangeTextEditorVisibleRanges: proposedApiFunction(extension, (listener: (e: vscode.TextEditorVisibleRangesChangeEvent) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) => {
|
||||
onDidChangeTextEditorVisibleRanges(listener: (e: vscode.TextEditorVisibleRangesChangeEvent) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) {
|
||||
return extHostEditors.onDidChangeTextEditorVisibleRanges(listener, thisArgs, disposables);
|
||||
}),
|
||||
},
|
||||
onDidChangeTextEditorViewColumn(listener, thisArg?, disposables?) {
|
||||
return extHostEditors.onDidChangeTextEditorViewColumn(listener, thisArg, disposables);
|
||||
},
|
||||
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;
|
||||
},
|
||||
@@ -360,7 +385,7 @@ export function createApiFactory(
|
||||
showErrorMessage(message, first, ...rest) {
|
||||
return extHostMessageService.showMessage(extension, Severity.Error, message, first, rest);
|
||||
},
|
||||
showQuickPick(items: any, options: vscode.QuickPickOptions, token?: vscode.CancellationToken) {
|
||||
showQuickPick(items: any, options: vscode.QuickPickOptions, token?: vscode.CancellationToken): any {
|
||||
return extHostQuickOpen.showQuickPick(items, options, token);
|
||||
},
|
||||
showWorkspaceFolderPick(options: vscode.WorkspaceFolderPickOptions) {
|
||||
@@ -385,20 +410,26 @@ export function createApiFactory(
|
||||
console.warn(`[Deprecation Warning] function 'withScmProgress' is deprecated and should no longer be used. Use 'withProgress' instead.`);
|
||||
return extHostProgress.withProgress(extension, { location: extHostTypes.ProgressLocation.SourceControl }, (progress, token) => task({ report(n: number) { /*noop*/ } }));
|
||||
},
|
||||
withProgress<R>(options: vscode.ProgressOptions, task: (progress: vscode.Progress<{ message?: string; percentage?: number }>) => Thenable<R>) {
|
||||
withProgress<R>(options: vscode.ProgressOptions, task: (progress: vscode.Progress<{ message?: string; worked?: number }>, token: vscode.CancellationToken) => Thenable<R>) {
|
||||
return extHostProgress.withProgress(extension, options, task);
|
||||
},
|
||||
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);
|
||||
}
|
||||
return extHostTerminalService.createTerminal(<string>nameOrOptions, shellPath, shellArgs);
|
||||
},
|
||||
registerTreeDataProvider(viewId: string, treeDataProvider: vscode.TreeDataProvider<any>): vscode.TreeView<any> {
|
||||
return extHostTreeViews.registerTreeDataProvider(viewId, treeDataProvider, (fn) => proposedApiFunction(extension, fn));
|
||||
registerTreeDataProvider(viewId: string, treeDataProvider: vscode.TreeDataProvider<any>): vscode.Disposable {
|
||||
return extHostTreeViews.registerTreeDataProvider(viewId, treeDataProvider);
|
||||
},
|
||||
createTreeView(viewId: string, options: { treeDataProvider: vscode.TreeDataProvider<any> }): vscode.TreeView<any> {
|
||||
return extHostTreeViews.createTreeView(viewId, options);
|
||||
},
|
||||
// proposed API
|
||||
sampleFunction: proposedApiFunction(extension, () => {
|
||||
@@ -407,12 +438,11 @@ export function createApiFactory(
|
||||
registerDecorationProvider: proposedApiFunction(extension, (provider: vscode.DecorationProvider) => {
|
||||
return extHostDecorations.registerDecorationProvider(provider, extension.id);
|
||||
}),
|
||||
// {{SQL CARBON EDIT}}
|
||||
createWebview(uri: vscode.Uri, title: string, column: vscode.ViewColumn, options: vscode.WebviewOptions): vscode.Webview {
|
||||
return extHostWebviews.createWebview(uri, title, column, options);
|
||||
},
|
||||
onDidChangeActiveEditor: proposedApiFunction(extension, (listener, thisArg?, disposables?) => {
|
||||
return extHostDocumentsAndEditors.onDidChangeActiveEditor(listener, thisArg, disposables);
|
||||
registerWebviewPanelSerializer: proposedApiFunction(extension, (viewType: string, serializer: vscode.WebviewPanelSerializer) => {
|
||||
return extHostWebviews.registerWebviewPanelSerializer(viewType, serializer);
|
||||
}),
|
||||
registerProtocolHandler: proposedApiFunction(extension, (handler: vscode.ProtocolHandler) => {
|
||||
return extHostUrls.registerProtocolHandler(extension.id, handler);
|
||||
})
|
||||
};
|
||||
|
||||
@@ -512,8 +542,29 @@ export function createApiFactory(
|
||||
registerTaskProvider: (type: string, provider: vscode.TaskProvider) => {
|
||||
return extHostTask.registerTaskProvider(extension, provider);
|
||||
},
|
||||
registerFileSystemProvider: proposedApiFunction(extension, (authority, provider) => {
|
||||
return extHostFileSystem.registerFileSystemProvider(authority, provider);
|
||||
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);
|
||||
},
|
||||
onDidEndTask: (listeners, thisArgs?, disposables?) => {
|
||||
return extHostTask.onDidEndTask(listeners, thisArgs, disposables);
|
||||
},
|
||||
registerFileSystemProvider(scheme, provider, options) {
|
||||
return extHostFileSystem.registerFileSystemProvider(scheme, provider, options);
|
||||
},
|
||||
registerDeprecatedFileSystemProvider: proposedApiFunction(extension, (scheme, provider) => {
|
||||
return extHostFileSystem.registerDeprecatedFileSystemProvider(scheme, provider);
|
||||
}),
|
||||
registerSearchProvider: proposedApiFunction(extension, (scheme, provider) => {
|
||||
return extHostSearch.registerSearchProvider(scheme, provider);
|
||||
})
|
||||
};
|
||||
|
||||
@@ -559,6 +610,7 @@ export function createApiFactory(
|
||||
// {{SQL CARBON EDIT}}
|
||||
// DebugAdapterExecutable: extHostTypes.DebugAdapterExecutable,
|
||||
Diagnostic: extHostTypes.Diagnostic,
|
||||
DiagnosticRelatedInformation: extHostTypes.DiagnosticRelatedInformation,
|
||||
DiagnosticSeverity: extHostTypes.DiagnosticSeverity,
|
||||
Disposable: extHostTypes.Disposable,
|
||||
DocumentHighlight: extHostTypes.DocumentHighlight,
|
||||
@@ -582,6 +634,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,
|
||||
@@ -605,16 +663,19 @@ export function createApiFactory(
|
||||
TaskGroup: extHostTypes.TaskGroup,
|
||||
ProcessExecution: extHostTypes.ProcessExecution,
|
||||
ShellExecution: extHostTypes.ShellExecution,
|
||||
ShellQuoting: extHostTypes.ShellQuoting,
|
||||
TaskScope: extHostTypes.TaskScope,
|
||||
Task: extHostTypes.Task,
|
||||
ConfigurationTarget: extHostTypes.ConfigurationTarget,
|
||||
RelativePattern: extHostTypes.RelativePattern,
|
||||
|
||||
DeprecatedFileChangeType: extHostTypes.DeprecatedFileChangeType,
|
||||
DeprecatedFileType: extHostTypes.DeprecatedFileType,
|
||||
FileChangeType: extHostTypes.FileChangeType,
|
||||
FileType: extHostTypes.FileType,
|
||||
FoldingRangeList: extHostTypes.FoldingRangeList,
|
||||
FileType: files.FileType,
|
||||
FileSystemError: extHostTypes.FileSystemError,
|
||||
FoldingRange: extHostTypes.FoldingRange,
|
||||
FoldingRangeType: extHostTypes.FoldingRangeType
|
||||
FoldingRangeKind: extHostTypes.FoldingRangeKind
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -643,7 +704,7 @@ class Extension<T> implements vscode.Extension<T> {
|
||||
}
|
||||
|
||||
activate(): Thenable<T> {
|
||||
return this._extensionService.activateById(this.id, new ExtensionActivatedByAPI(false)).then(() => this.exports);
|
||||
return this._extensionService.activateByIdWithErrors(this.id, new ExtensionActivatedByAPI(false)).then(() => this.exports);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,22 +42,19 @@ 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, FileWriteOptions, FileType, FileOverwriteOptions } from 'vs/platform/files/common/files';
|
||||
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
import { ParsedArgs } from 'vs/platform/environment/common/environment';
|
||||
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, TaskFilterDTO } from 'vs/workbench/api/shared/tasks';
|
||||
|
||||
export interface IEnvironment {
|
||||
isExtensionDevelopmentDebug: boolean;
|
||||
enableProposedApiForAll: boolean;
|
||||
enableProposedApiFor: string | string[];
|
||||
appRoot: string;
|
||||
appSettingsHome: string;
|
||||
disableExtensions: boolean;
|
||||
userExtensionsHome: string;
|
||||
extensionDevelopmentPath: string;
|
||||
extensionTestsPath: string;
|
||||
}
|
||||
@@ -77,9 +74,8 @@ export interface IInitData {
|
||||
configuration: IConfigurationInitData;
|
||||
telemetryInfo: ITelemetryInfo;
|
||||
windowId: number;
|
||||
args: ParsedArgs;
|
||||
execPath: string;
|
||||
logLevel: LogLevel;
|
||||
logsPath: string;
|
||||
}
|
||||
|
||||
export interface IConfigurationInitData extends IConfigurationData {
|
||||
@@ -257,28 +253,36 @@ export interface ISerializedLanguageConfiguration {
|
||||
};
|
||||
}
|
||||
|
||||
export interface ISerializedDocumentFilter {
|
||||
$serialized: true;
|
||||
language?: string;
|
||||
scheme?: string;
|
||||
pattern?: vscode.GlobPattern;
|
||||
exclusive?: boolean;
|
||||
}
|
||||
|
||||
export interface MainThreadLanguageFeaturesShape extends IDisposable {
|
||||
$unregister(handle: number): void;
|
||||
$registerOutlineSupport(handle: number, selector: vscode.DocumentSelector): void;
|
||||
$registerCodeLensSupport(handle: number, selector: vscode.DocumentSelector, eventHandle: number): void;
|
||||
$registerOutlineSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerCodeLensSupport(handle: number, selector: ISerializedDocumentFilter[], eventHandle: number): void;
|
||||
$emitCodeLensEvent(eventHandle: number, event?: any): void;
|
||||
$registerDeclaractionSupport(handle: number, selector: vscode.DocumentSelector): void;
|
||||
$registerImplementationSupport(handle: number, selector: vscode.DocumentSelector): void;
|
||||
$registerTypeDefinitionSupport(handle: number, selector: vscode.DocumentSelector): void;
|
||||
$registerHoverProvider(handle: number, selector: vscode.DocumentSelector): void;
|
||||
$registerDocumentHighlightProvider(handle: number, selector: vscode.DocumentSelector): void;
|
||||
$registerReferenceSupport(handle: number, selector: vscode.DocumentSelector): void;
|
||||
$registerQuickFixSupport(handle: number, selector: vscode.DocumentSelector): void;
|
||||
$registerDocumentFormattingSupport(handle: number, selector: vscode.DocumentSelector): void;
|
||||
$registerRangeFormattingSupport(handle: number, selector: vscode.DocumentSelector): void;
|
||||
$registerOnTypeFormattingSupport(handle: number, selector: vscode.DocumentSelector, autoFormatTriggerCharacters: string[]): void;
|
||||
$registerDeclaractionSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerImplementationSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerTypeDefinitionSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerHoverProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerDocumentHighlightProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerReferenceSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerQuickFixSupport(handle: number, selector: ISerializedDocumentFilter[], supportedKinds?: string[]): void;
|
||||
$registerDocumentFormattingSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerRangeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerOnTypeFormattingSupport(handle: number, selector: ISerializedDocumentFilter[], autoFormatTriggerCharacters: string[]): void;
|
||||
$registerNavigateTypeSupport(handle: number): void;
|
||||
$registerRenameSupport(handle: number, selector: vscode.DocumentSelector, supportsResolveInitialValues: boolean): void;
|
||||
$registerSuggestSupport(handle: number, selector: vscode.DocumentSelector, triggerCharacters: string[], supportsResolveDetails: boolean): void;
|
||||
$registerSignatureHelpProvider(handle: number, selector: vscode.DocumentSelector, triggerCharacter: string[]): void;
|
||||
$registerDocumentLinkProvider(handle: number, selector: vscode.DocumentSelector): void;
|
||||
$registerDocumentColorProvider(handle: number, selector: vscode.DocumentSelector): void;
|
||||
$registerFoldingProvider(handle: number, selector: vscode.DocumentSelector): void;
|
||||
$registerRenameSupport(handle: number, selector: ISerializedDocumentFilter[], supportsResolveInitialValues: boolean): void;
|
||||
$registerSuggestSupport(handle: number, selector: ISerializedDocumentFilter[], triggerCharacters: string[], supportsResolveDetails: boolean): void;
|
||||
$registerSignatureHelpProvider(handle: number, selector: ISerializedDocumentFilter[], triggerCharacter: string[]): void;
|
||||
$registerDocumentLinkProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerDocumentColorProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$registerFoldingRangeProvider(handle: number, selector: ISerializedDocumentFilter[]): void;
|
||||
$setLanguageConfiguration(handle: number, languageId: string, configuration: ISerializedLanguageConfiguration): void;
|
||||
}
|
||||
|
||||
@@ -316,13 +320,19 @@ 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 {
|
||||
handle: number;
|
||||
}
|
||||
export interface MainThreadQuickOpenShape extends IDisposable {
|
||||
$show(options: IPickOptions): TPromise<number>;
|
||||
$show(options: IPickOptions): TPromise<number | number[]>;
|
||||
$setItems(items: MyQuickPickItems[]): TPromise<any>;
|
||||
$setError(error: Error): TPromise<any>;
|
||||
$input(options: vscode.InputBoxOptions, validateInput: boolean): TPromise<string>;
|
||||
@@ -342,21 +352,35 @@ export interface MainThreadTelemetryShape extends IDisposable {
|
||||
$publicLog(eventName: string, data?: any): void;
|
||||
}
|
||||
|
||||
export type WebviewHandle = number;
|
||||
export type WebviewPanelHandle = string;
|
||||
|
||||
export interface MainThreadWebviewsShape extends IDisposable {
|
||||
$createWebview(handle: WebviewHandle, uri: URI, title: string, column: EditorPosition, options: vscode.WebviewOptions): void;
|
||||
$disposeWebview(handle: WebviewHandle): void;
|
||||
$show(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;
|
||||
$onDidChangeActiveWeview(handle: WebviewHandle | undefined): void;
|
||||
$onDidDisposeWeview(handle: WebviewHandle): Thenable<void>;
|
||||
$onDidChangePosition(handle: WebviewHandle, newPosition: EditorPosition): void;
|
||||
$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 {
|
||||
@@ -372,18 +396,22 @@ export interface IFileChangeDto {
|
||||
}
|
||||
|
||||
export interface MainThreadFileSystemShape extends IDisposable {
|
||||
$registerFileSystemProvider(handle: number, scheme: string): void;
|
||||
$unregisterFileSystemProvider(handle: number): void;
|
||||
|
||||
$onDidAddFileSystemRoot(root: UriComponents): void;
|
||||
$registerFileSystemProvider(handle: number, scheme: string, capabilities: FileSystemProviderCapabilities): void;
|
||||
$unregisterProvider(handle: number): void;
|
||||
$onFileSystemChange(handle: number, resource: IFileChangeDto[]): void;
|
||||
$reportFileChunk(handle: number, session: number, chunk: number[] | null): void;
|
||||
}
|
||||
|
||||
export interface MainThreadSearchShape extends IDisposable {
|
||||
$registerSearchProvider(handle: number, scheme: string): void;
|
||||
$unregisterProvider(handle: number): void;
|
||||
$handleFindMatch(handle: number, session, data: UriComponents | [UriComponents, ILineMatch]): void;
|
||||
}
|
||||
|
||||
export interface MainThreadTaskShape extends IDisposable {
|
||||
$registerTaskProvider(handle: number): TPromise<void>;
|
||||
$fetchTasks(filter?: TaskFilterDTO): TPromise<TaskDTO[]>;
|
||||
$executeTask(task: TaskHandleDTO | TaskDTO): TPromise<TaskExecutionDTO>;
|
||||
$terminateTask(id: string): TPromise<void>;
|
||||
$unregisterTaskProvider(handle: number): TPromise<void>;
|
||||
}
|
||||
|
||||
@@ -454,6 +482,10 @@ 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);
|
||||
$registerDebugConfigurationProvider(type: string, hasProvideMethod: boolean, hasResolveMethod: boolean, hasDebugAdapterExecutable: boolean, handle: number): TPromise<any>;
|
||||
$unregisterDebugConfigurationProvider(handle: number): TPromise<any>;
|
||||
$startDebugging(folder: UriComponents | undefined, nameOrConfig: string | vscode.DebugConfiguration): TPromise<boolean>;
|
||||
@@ -555,16 +587,20 @@ export interface ExtHostWorkspaceShape {
|
||||
}
|
||||
|
||||
export interface ExtHostFileSystemShape {
|
||||
$utimes(handle: number, resource: UriComponents, mtime: number, atime: number): TPromise<IStat>;
|
||||
$stat(handle: number, resource: UriComponents): TPromise<IStat>;
|
||||
$read(handle: number, session: number, offset: number, count: number, resource: UriComponents): TPromise<number>;
|
||||
$write(handle: number, resource: UriComponents, content: number[]): TPromise<void>;
|
||||
$unlink(handle: number, resource: UriComponents): TPromise<void>;
|
||||
$move(handle: number, resource: UriComponents, target: UriComponents): TPromise<IStat>;
|
||||
$mkdir(handle: number, resource: UriComponents): TPromise<IStat>;
|
||||
$readdir(handle: number, resource: UriComponents): TPromise<[UriComponents, IStat][]>;
|
||||
$rmdir(handle: number, resource: UriComponents): TPromise<void>;
|
||||
$findFiles(handle: number, session: number, query: string): TPromise<void>;
|
||||
$readdir(handle: number, resource: UriComponents): TPromise<[string, FileType][]>;
|
||||
$readFile(handle: number, resource: UriComponents): TPromise<string>;
|
||||
$writeFile(handle: number, resource: UriComponents, base64Encoded: string, opts: FileWriteOptions): TPromise<void>;
|
||||
$rename(handle: number, resource: UriComponents, target: UriComponents, opts: FileOverwriteOptions): TPromise<void>;
|
||||
$copy(handle: number, resource: UriComponents, target: UriComponents, opts: FileOverwriteOptions): TPromise<void>;
|
||||
$mkdir(handle: number, resource: UriComponents): TPromise<void>;
|
||||
$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>;
|
||||
}
|
||||
|
||||
@@ -697,7 +733,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>;
|
||||
$resolveInitialRenameValue(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.RenameInitialValue>;
|
||||
$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;
|
||||
@@ -706,7 +742,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): TPromise<modes.IFoldingRangeList>;
|
||||
$provideFoldingRanges(handle: number, resource: UriComponents, context: modes.FoldingContext): TPromise<modes.FoldingRange[]>;
|
||||
}
|
||||
|
||||
export interface ExtHostQuickOpenShape {
|
||||
@@ -714,9 +750,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 {
|
||||
@@ -728,23 +778,26 @@ export interface ExtHostSCMShape {
|
||||
|
||||
export interface ExtHostTaskShape {
|
||||
$provideTasks(handle: number): TPromise<TaskSet>;
|
||||
$taskStarted(execution: TaskExecutionDTO): void;
|
||||
$taskEnded(execution: TaskExecutionDTO): void;
|
||||
}
|
||||
|
||||
export interface IFunctionBreakpointDto {
|
||||
type: 'function';
|
||||
export interface IBreakpointDto {
|
||||
type: string;
|
||||
id?: string;
|
||||
enabled: boolean;
|
||||
condition?: string;
|
||||
hitCondition?: string;
|
||||
logMessage?: string;
|
||||
}
|
||||
|
||||
export interface IFunctionBreakpointDto extends IBreakpointDto {
|
||||
type: 'function';
|
||||
functionName: string;
|
||||
}
|
||||
|
||||
export interface ISourceBreakpointDto {
|
||||
export interface ISourceBreakpointDto extends IBreakpointDto {
|
||||
type: 'source';
|
||||
id?: string;
|
||||
enabled: boolean;
|
||||
condition?: string;
|
||||
hitCondition?: string;
|
||||
uri: UriComponents;
|
||||
line: number;
|
||||
character: number;
|
||||
@@ -764,6 +817,7 @@ export interface ISourceMultiBreakpointDto {
|
||||
enabled: boolean;
|
||||
condition?: string;
|
||||
hitCondition?: string;
|
||||
logMessage?: string;
|
||||
line: number;
|
||||
character: number;
|
||||
}[];
|
||||
@@ -772,6 +826,11 @@ export interface ISourceMultiBreakpointDto {
|
||||
// {{SQL CARBON EDIT}}
|
||||
/*
|
||||
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>;
|
||||
$resolveDebugConfiguration(handle: number, folder: UriComponents | undefined, debugConfiguration: IConfig): TPromise<IConfig>;
|
||||
$provideDebugConfigurations(handle: number, folder: UriComponents | undefined): TPromise<IConfig[]>;
|
||||
$debugAdapterExecutable(handle: number, folder: UriComponents | undefined): TPromise<IAdapterExecutable>;
|
||||
@@ -805,6 +864,10 @@ export interface ExtHostLogServiceShape {
|
||||
$setLevel(level: LogLevel);
|
||||
}
|
||||
|
||||
export interface ExtHostProgressShape {
|
||||
$acceptProgressCanceled(handle: number): void;
|
||||
}
|
||||
|
||||
// --- proxy identifiers
|
||||
|
||||
export const MainContext = {
|
||||
@@ -831,10 +894,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'),
|
||||
};
|
||||
@@ -861,8 +926,11 @@ 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')
|
||||
ExtHostWebviews: createExtId<ExtHostWebviewsShape>('ExtHostWebviews'),
|
||||
ExtHostUrls: createExtId<ExtHostUrlsShape>('ExtHostUrls'),
|
||||
ExtHostProgress: createMainId<ExtHostProgressShape>('ExtHostProgress')
|
||||
};
|
||||
|
||||
@@ -10,25 +10,30 @@ import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import * as vscode from 'vscode';
|
||||
import * as typeConverters from 'vs/workbench/api/node/extHostTypeConverters';
|
||||
import * as types from 'vs/workbench/api/node/extHostTypes';
|
||||
import { IRawColorInfo } from 'vs/workbench/api/node/extHost.protocol';
|
||||
|
||||
import { ISingleEditOperation } from 'vs/editor/common/model';
|
||||
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 {
|
||||
|
||||
static register(commands: ExtHostCommands) {
|
||||
return new ExtHostApiCommands(commands).registerCommands();
|
||||
static register(commands: ExtHostCommands, workspace: ExtHostTask) {
|
||||
return new ExtHostApiCommands(commands, workspace).registerCommands();
|
||||
}
|
||||
|
||||
private _commands: ExtHostCommands;
|
||||
private _tasks: ExtHostTask;
|
||||
private _disposables: IDisposable[] = [];
|
||||
|
||||
private constructor(commands: ExtHostCommands) {
|
||||
private constructor(commands: ExtHostCommands, task: ExtHostTask) {
|
||||
this._commands = commands;
|
||||
this._tasks = task;
|
||||
}
|
||||
|
||||
registerCommands() {
|
||||
@@ -46,6 +51,14 @@ export class ExtHostApiCommands {
|
||||
],
|
||||
returns: 'A promise that resolves to an array of Location-instances.'
|
||||
});
|
||||
this._register('vscode.executeTypeDefinitionProvider', this._executeTypeDefinitionProvider, {
|
||||
description: 'Execute all type definition providers.',
|
||||
args: [
|
||||
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
|
||||
{ name: 'position', description: 'Position of a symbol', constraint: types.Position }
|
||||
],
|
||||
returns: 'A promise that resolves to an array of Location-instances.'
|
||||
});
|
||||
this._register('vscode.executeImplementationProvider', this._executeImplementationProvider, {
|
||||
description: 'Execute all implementation providers.',
|
||||
args: [
|
||||
@@ -108,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.'
|
||||
});
|
||||
@@ -123,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.'
|
||||
});
|
||||
@@ -161,99 +176,94 @@ export class ExtHostApiCommands {
|
||||
],
|
||||
returns: 'A promise that resolves to an array of DocumentLink-instances.'
|
||||
});
|
||||
this._register('vscode.executeTaskProvider', this._executeTaskProvider, {
|
||||
description: 'Execute task provider',
|
||||
args: [],
|
||||
returns: 'An array of task handles'
|
||||
});
|
||||
this._register('vscode.executeDocumentColorProvider', this._executeDocumentColorProvider, {
|
||||
description: 'Execute document color provider.',
|
||||
args: [
|
||||
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
|
||||
],
|
||||
returns: 'A promise that resolves to an array of ColorInformation objects.'
|
||||
});
|
||||
this._register('vscode.executeColorPresentationProvider', this._executeColorPresentationProvider, {
|
||||
description: 'Execute color presentation provider.',
|
||||
args: [
|
||||
{ name: 'color', description: 'The color to show and insert', constraint: types.Color },
|
||||
{ name: 'context', description: 'Context object with uri and range' }
|
||||
],
|
||||
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
|
||||
|
||||
private _register(id: string, handler: (...args: any[]) => any, description?: ICommandHandlerDescription): void {
|
||||
let disposable = this._commands.registerCommand(id, handler, this, description);
|
||||
let disposable = this._commands.registerCommand(false, id, handler, this, description);
|
||||
this._disposables.push(disposable);
|
||||
}
|
||||
|
||||
@@ -280,12 +290,17 @@ export class ExtHostApiCommands {
|
||||
resource,
|
||||
position: position && typeConverters.fromPosition(position)
|
||||
};
|
||||
return this._commands.executeCommand<modes.Location[]>('_executeDefinitionProvider', args).then(value => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(typeConverters.location.to);
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
return this._commands.executeCommand<modes.Location[]>('_executeDefinitionProvider', args)
|
||||
.then(tryMapWith(typeConverters.location.to));
|
||||
}
|
||||
|
||||
private _executeTypeDefinitionProvider(resource: URI, position: types.Position): Thenable<types.Location[]> {
|
||||
const args = {
|
||||
resource,
|
||||
position: position && typeConverters.fromPosition(position)
|
||||
};
|
||||
return this._commands.executeCommand<modes.Location[]>('_executeTypeDefinitionProvider', args)
|
||||
.then(tryMapWith(typeConverters.location.to));
|
||||
}
|
||||
|
||||
private _executeImplementationProvider(resource: URI, position: types.Position): Thenable<types.Location[]> {
|
||||
@@ -293,12 +308,8 @@ export class ExtHostApiCommands {
|
||||
resource,
|
||||
position: position && typeConverters.fromPosition(position)
|
||||
};
|
||||
return this._commands.executeCommand<modes.Location[]>('_executeImplementationProvider', args).then(value => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(typeConverters.location.to);
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
return this._commands.executeCommand<modes.Location[]>('_executeImplementationProvider', args)
|
||||
.then(tryMapWith(typeConverters.location.to));
|
||||
}
|
||||
|
||||
private _executeHoverProvider(resource: URI, position: types.Position): Thenable<types.Hover[]> {
|
||||
@@ -306,12 +317,8 @@ export class ExtHostApiCommands {
|
||||
resource,
|
||||
position: position && typeConverters.fromPosition(position)
|
||||
};
|
||||
return this._commands.executeCommand<modes.Hover[]>('_executeHoverProvider', args).then(value => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(typeConverters.toHover);
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
return this._commands.executeCommand<modes.Hover[]>('_executeHoverProvider', args)
|
||||
.then(tryMapWith(typeConverters.toHover));
|
||||
}
|
||||
|
||||
private _executeDocumentHighlights(resource: URI, position: types.Position): Thenable<types.DocumentHighlight[]> {
|
||||
@@ -319,12 +326,8 @@ export class ExtHostApiCommands {
|
||||
resource,
|
||||
position: position && typeConverters.fromPosition(position)
|
||||
};
|
||||
return this._commands.executeCommand<modes.DocumentHighlight[]>('_executeDocumentHighlights', args).then(value => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(typeConverters.toDocumentHighlight);
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
return this._commands.executeCommand<modes.DocumentHighlight[]>('_executeDocumentHighlights', args)
|
||||
.then(tryMapWith(typeConverters.toDocumentHighlight));
|
||||
}
|
||||
|
||||
private _executeReferenceProvider(resource: URI, position: types.Position): Thenable<types.Location[]> {
|
||||
@@ -332,12 +335,8 @@ export class ExtHostApiCommands {
|
||||
resource,
|
||||
position: position && typeConverters.fromPosition(position)
|
||||
};
|
||||
return this._commands.executeCommand<modes.Location[]>('_executeReferenceProvider', args).then(value => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(typeConverters.location.to);
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
return this._commands.executeCommand<modes.Location[]>('_executeReferenceProvider', args)
|
||||
.then(tryMapWith(typeConverters.location.to));
|
||||
}
|
||||
|
||||
private _executeDocumentRenameProvider(resource: URI, position: types.Position, newName: string): Thenable<types.WorkspaceEdit> {
|
||||
@@ -371,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) {
|
||||
@@ -387,6 +387,32 @@ export class ExtHostApiCommands {
|
||||
});
|
||||
}
|
||||
|
||||
private _executeDocumentColorProvider(resource: URI): Thenable<types.ColorInformation[]> {
|
||||
const args = {
|
||||
resource
|
||||
};
|
||||
return this._commands.executeCommand<IRawColorInfo[]>('_executeDocumentColorProvider', args).then(result => {
|
||||
if (result) {
|
||||
return result.map(ci => ({ range: typeConverters.toRange(ci.range), color: typeConverters.Color.to(ci.color) }));
|
||||
}
|
||||
return [];
|
||||
});
|
||||
}
|
||||
|
||||
private _executeColorPresentationProvider(color: types.Color, context: { uri: URI, range: types.Range }): Thenable<types.ColorPresentation[]> {
|
||||
const args = {
|
||||
resource: context.uri,
|
||||
color: typeConverters.Color.from(color),
|
||||
range: typeConverters.fromRange(context.range),
|
||||
};
|
||||
return this._commands.executeCommand<modes.IColorPresentation[]>('_executeColorPresentationProvider', args).then(result => {
|
||||
if (result) {
|
||||
return result.map(typeConverters.ColorPresentation.to);
|
||||
}
|
||||
return [];
|
||||
});
|
||||
}
|
||||
|
||||
private _executeDocumentSymbolProvider(resource: URI): Thenable<types.SymbolInformation[]> {
|
||||
const args = {
|
||||
resource
|
||||
@@ -404,11 +430,8 @@ export class ExtHostApiCommands {
|
||||
resource,
|
||||
range: typeConverters.fromRange(range)
|
||||
};
|
||||
return this._commands.executeCommand<CustomCodeAction[]>('_executeCodeActionProvider', args).then(value => {
|
||||
if (!Array.isArray(value)) {
|
||||
return undefined;
|
||||
}
|
||||
return value.map(codeAction => {
|
||||
return this._commands.executeCommand<CustomCodeAction[]>('_executeCodeActionProvider', args)
|
||||
.then(tryMapWith(codeAction => {
|
||||
if (codeAction._isSynthetic) {
|
||||
return this._commands.converter.fromInternal(codeAction.command);
|
||||
} else {
|
||||
@@ -424,22 +447,18 @@ export class ExtHostApiCommands {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
private _executeCodeLensProvider(resource: URI): Thenable<vscode.CodeLens[]> {
|
||||
const args = { resource };
|
||||
return this._commands.executeCommand<modes.ICodeLensSymbol[]>('_executeCodeLensProvider', args).then(value => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(item => {
|
||||
return new types.CodeLens(
|
||||
typeConverters.toRange(item.range),
|
||||
this._commands.converter.fromInternal(item.command));
|
||||
});
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
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(
|
||||
typeConverters.toRange(item.range),
|
||||
this._commands.converter.fromInternal(item.command));
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
private _executeFormatDocumentProvider(resource: URI, options: vscode.FormattingOptions): Thenable<vscode.TextEdit[]> {
|
||||
@@ -447,12 +466,8 @@ export class ExtHostApiCommands {
|
||||
resource,
|
||||
options
|
||||
};
|
||||
return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatDocumentProvider', args).then(value => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(edit => new types.TextEdit(typeConverters.toRange(edit.range), edit.text));
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatDocumentProvider', args)
|
||||
.then(tryMapWith(edit => new types.TextEdit(typeConverters.toRange(edit.range), edit.text)));
|
||||
}
|
||||
|
||||
private _executeFormatRangeProvider(resource: URI, range: types.Range, options: vscode.FormattingOptions): Thenable<vscode.TextEdit[]> {
|
||||
@@ -461,12 +476,8 @@ export class ExtHostApiCommands {
|
||||
range: typeConverters.fromRange(range),
|
||||
options
|
||||
};
|
||||
return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatRangeProvider', args).then(value => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(edit => new types.TextEdit(typeConverters.toRange(edit.range), edit.text));
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatRangeProvider', args)
|
||||
.then(tryMapWith(edit => new types.TextEdit(typeConverters.toRange(edit.range), edit.text)));
|
||||
}
|
||||
|
||||
private _executeFormatOnTypeProvider(resource: URI, position: types.Position, ch: string, options: vscode.FormattingOptions): Thenable<vscode.TextEdit[]> {
|
||||
@@ -476,20 +487,25 @@ export class ExtHostApiCommands {
|
||||
ch,
|
||||
options
|
||||
};
|
||||
return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatOnTypeProvider', args).then(value => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(edit => new types.TextEdit(typeConverters.toRange(edit.range), edit.text));
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
return this._commands.executeCommand<ISingleEditOperation[]>('_executeFormatOnTypeProvider', args)
|
||||
.then(tryMapWith(edit => new types.TextEdit(typeConverters.toRange(edit.range), edit.text)));
|
||||
}
|
||||
|
||||
private _executeDocumentLinkProvider(resource: URI): Thenable<vscode.DocumentLink[]> {
|
||||
return this._commands.executeCommand<modes.ILink[]>('_executeLinkProvider', resource).then(value => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(typeConverters.DocumentLink.to);
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
return this._commands.executeCommand<modes.ILink[]>('_executeLinkProvider', resource)
|
||||
.then(tryMapWith(typeConverters.DocumentLink.to));
|
||||
}
|
||||
|
||||
private _executeTaskProvider(): Thenable<vscode.Task[]> {
|
||||
return this._tasks.fetchTasks();
|
||||
}
|
||||
}
|
||||
|
||||
function tryMapWith<T, R>(f: (x: T) => R) {
|
||||
return (value: T[]) => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(f);
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ export class ExtHostCommands implements ExtHostCommandsShape {
|
||||
this._argumentProcessors.push(processor);
|
||||
}
|
||||
|
||||
registerCommand(id: string, callback: <T>(...args: any[]) => T | Thenable<T>, thisArg?: any, description?: ICommandHandlerDescription): extHostTypes.Disposable {
|
||||
registerCommand(global: boolean, id: string, callback: <T>(...args: any[]) => T | Thenable<T>, thisArg?: any, description?: ICommandHandlerDescription): extHostTypes.Disposable {
|
||||
this._logService.trace('ExtHostCommands#registerCommand', id);
|
||||
|
||||
if (!id.trim().length) {
|
||||
@@ -66,11 +66,15 @@ export class ExtHostCommands implements ExtHostCommandsShape {
|
||||
}
|
||||
|
||||
this._commands.set(id, { callback, thisArg, description });
|
||||
this._proxy.$registerCommand(id);
|
||||
if (global) {
|
||||
this._proxy.$registerCommand(id);
|
||||
}
|
||||
|
||||
return new extHostTypes.Disposable(() => {
|
||||
if (this._commands.delete(id)) {
|
||||
this._proxy.$unregisterCommand(id);
|
||||
if (global) {
|
||||
this._proxy.$unregisterCommand(id);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -112,6 +116,7 @@ export class ExtHostCommands implements ExtHostCommandsShape {
|
||||
try {
|
||||
validateConstraint(args[i], description.args[i].constraint);
|
||||
} catch (err) {
|
||||
// {{ SQL CARBON EDIT }} - Add type assertion to fix build break
|
||||
return <any>Promise.reject(new Error(`Running the contributed command:'${id}' failed. Illegal argument '${description.args[i].name}' - ${description.args[i].description}`));
|
||||
}
|
||||
}
|
||||
@@ -122,12 +127,14 @@ export class ExtHostCommands implements ExtHostCommandsShape {
|
||||
return Promise.resolve(result);
|
||||
} catch (err) {
|
||||
this._logService.error(err, id);
|
||||
// {{ SQL CARBON EDIT }} - Add type assertion to fix build break
|
||||
return <any>Promise.reject(new Error(`Running the contributed command:'${id}' failed.`));
|
||||
}
|
||||
}
|
||||
|
||||
$executeContributedCommand<T>(id: string, ...args: any[]): Thenable<T> {
|
||||
if (!this._commands.has(id)) {
|
||||
// {{ SQL CARBON EDIT }} - Add type assertion to fix build break
|
||||
return <any>Promise.reject(new Error(`Contributed command '${id}' does not exist.`));
|
||||
} else {
|
||||
args = args.map(arg => this._argumentProcessors.reduce((r, p) => p.processArgument(r), arg));
|
||||
@@ -161,15 +168,16 @@ export class ExtHostCommands implements ExtHostCommandsShape {
|
||||
|
||||
export class CommandsConverter {
|
||||
|
||||
private readonly _delegatingCommandId: string;
|
||||
private _commands: ExtHostCommands;
|
||||
private _heap: ExtHostHeapService;
|
||||
|
||||
// --- conversion between internal and api commands
|
||||
constructor(commands: ExtHostCommands, heap: ExtHostHeapService) {
|
||||
|
||||
this._delegatingCommandId = `_internal_command_delegation_${Date.now()}`;
|
||||
this._commands = commands;
|
||||
this._heap = heap;
|
||||
this._commands.registerCommand('_internal_command_delegation', this._executeConvertedCommand, this);
|
||||
this._commands.registerCommand(true, this._delegatingCommandId, this._executeConvertedCommand, this);
|
||||
}
|
||||
|
||||
toInternal(command: vscode.Command): modes.Command {
|
||||
@@ -190,7 +198,7 @@ export class CommandsConverter {
|
||||
const id = this._heap.keep(command);
|
||||
ObjectIdentifier.mixin(result, id);
|
||||
|
||||
result.id = '_internal_command_delegation';
|
||||
result.id = this._delegatingCommandId;
|
||||
result.arguments = [id];
|
||||
}
|
||||
|
||||
|
||||
@@ -6,16 +6,19 @@
|
||||
|
||||
import { mixin, deepClone } from 'vs/base/common/objects';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
|
||||
import { ExtHostConfigurationShape, MainThreadConfigurationShape, IWorkspaceConfigurationChangeEventData, IConfigurationInitData } from './extHost.protocol';
|
||||
import { ConfigurationTarget as ExtHostConfigurationTarget } from './extHostTypes';
|
||||
import { IConfigurationData, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
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';
|
||||
|
||||
declare var Proxy: any; // TODO@TypeScript
|
||||
|
||||
function lookUp(tree: any, key: string) {
|
||||
if (key) {
|
||||
@@ -47,7 +50,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
|
||||
constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspace, data: IConfigurationInitData) {
|
||||
this._proxy = proxy;
|
||||
this._extHostWorkspace = extHostWorkspace;
|
||||
this._configuration = Configuration.parse(data);
|
||||
this._configuration = ExtHostConfiguration.parse(data);
|
||||
this._configurationScopes = data.configurationScopes;
|
||||
}
|
||||
|
||||
@@ -56,12 +59,12 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
|
||||
}
|
||||
|
||||
$acceptConfigurationChanged(data: IConfigurationData, eventData: IWorkspaceConfigurationChangeEventData) {
|
||||
this._configuration = Configuration.parse(data);
|
||||
this._configuration = ExtHostConfiguration.parse(data);
|
||||
this._onDidChangeConfiguration.fire(this._toConfigurationChangeEvent(eventData));
|
||||
}
|
||||
|
||||
getConfiguration(section?: string, resource?: URI, extensionId?: string): vscode.WorkspaceConfiguration {
|
||||
const config = deepClone(section
|
||||
const config = this._toReadonlyValue(section
|
||||
? lookUp(this._configuration.getValue(null, { resource }, this._extHostWorkspace.workspace), section)
|
||||
: this._configuration.getValue(null, { resource }, this._extHostWorkspace.workspace));
|
||||
|
||||
@@ -93,6 +96,49 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
|
||||
let result = lookUp(config, key);
|
||||
if (typeof result === 'undefined') {
|
||||
result = defaultValue;
|
||||
} else {
|
||||
let clonedConfig = void 0;
|
||||
const cloneOnWriteProxy = (target: any, accessor: string): any => {
|
||||
let clonedTarget = void 0;
|
||||
const cloneTarget = () => {
|
||||
clonedConfig = clonedConfig ? clonedConfig : deepClone(config);
|
||||
clonedTarget = clonedTarget ? clonedTarget : lookUp(clonedConfig, accessor);
|
||||
};
|
||||
return isObject(target) ?
|
||||
new Proxy(target, {
|
||||
get: (target: any, property: string) => {
|
||||
if (typeof property === 'string' && property.toLowerCase() === 'tojson') {
|
||||
cloneTarget();
|
||||
return () => clonedTarget;
|
||||
}
|
||||
if (clonedConfig) {
|
||||
clonedTarget = clonedTarget ? clonedTarget : lookUp(clonedConfig, accessor);
|
||||
return clonedTarget[property];
|
||||
}
|
||||
const result = target[property];
|
||||
if (typeof property === 'string') {
|
||||
return cloneOnWriteProxy(result, `${accessor}.${property}`);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
set: (target: any, property: string, value: any) => {
|
||||
cloneTarget();
|
||||
clonedTarget[property] = value;
|
||||
return true;
|
||||
},
|
||||
deleteProperty: (target: any, property: string) => {
|
||||
cloneTarget();
|
||||
delete clonedTarget[property];
|
||||
return true;
|
||||
},
|
||||
defineProperty: (target: any, property: string, descriptor: any) => {
|
||||
cloneTarget();
|
||||
Object.defineProperty(clonedTarget, property, descriptor);
|
||||
return true;
|
||||
}
|
||||
}) : target;
|
||||
};
|
||||
result = cloneOnWriteProxy(result, key);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
@@ -128,6 +174,22 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
|
||||
return <vscode.WorkspaceConfiguration>Object.freeze(result);
|
||||
}
|
||||
|
||||
private _toReadonlyValue(result: any): any {
|
||||
const readonlyProxy = (target) => {
|
||||
return isObject(target) ?
|
||||
new Proxy(target, {
|
||||
get: (target: any, property: string) => readonlyProxy(target[property]),
|
||||
set: (target: any, property: string, value: any) => { throw new Error(`TypeError: Cannot assign to read only property '${property}' of object`); },
|
||||
deleteProperty: (target: any, property: string) => { throw new Error(`TypeError: Cannot delete read only property '${property}' of object`); },
|
||||
defineProperty: (target: any, property: string) => { throw new Error(`TypeError: Cannot define property '${property}' for a readonly object`); },
|
||||
setPrototypeOf: (target: any) => { throw new Error(`TypeError: Cannot set prototype for a readonly object`); },
|
||||
isExtensible: () => false,
|
||||
preventExtensions: () => true
|
||||
}) : target;
|
||||
};
|
||||
return readonlyProxy(result);
|
||||
}
|
||||
|
||||
private _validateConfigurationAccess(key: string, resource: URI, extensionId: string): void {
|
||||
const scope = this._configurationScopes[key];
|
||||
const extensionIdText = extensionId ? `[${extensionId}] ` : '';
|
||||
@@ -147,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];
|
||||
@@ -158,4 +220,19 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
|
||||
affectsConfiguration: (section: string, resource?: URI) => event.affectsConfiguration(section, resource)
|
||||
});
|
||||
}
|
||||
|
||||
private static parse(data: IConfigurationData): Configuration {
|
||||
const defaultConfiguration = ExtHostConfiguration.parseConfigurationModel(data.defaults);
|
||||
const userConfiguration = ExtHostConfiguration.parseConfigurationModel(data.user);
|
||||
const workspaceConfiguration = ExtHostConfiguration.parseConfigurationModel(data.workspace);
|
||||
const folders: ResourceMap<ConfigurationModel> = Object.keys(data.folders).reduce((result, key) => {
|
||||
result.set(URI.parse(key), ExtHostConfiguration.parseConfigurationModel(data.folders[key]));
|
||||
return result;
|
||||
}, new ResourceMap<ConfigurationModel>());
|
||||
return new Configuration(defaultConfiguration, userConfiguration, workspaceConfiguration, folders, new ConfigurationModel(), new ResourceMap<ConfigurationModel>(), false);
|
||||
}
|
||||
|
||||
private static parseConfigurationModel(model: IConfigurationModel): ConfigurationModel {
|
||||
return new ConfigurationModel(model.contents, model.keys, model.overrides).freeze();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,43 +7,49 @@
|
||||
// {{SQL CARBON EDIT}}
|
||||
/*
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { asWinJsPromise } from 'vs/base/common/async';
|
||||
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 { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
|
||||
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumentsAndEditors';
|
||||
import { IAdapterExecutable, ITerminalSettings, IDebuggerContribution, IConfig } 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 {
|
||||
|
||||
private _workspace: ExtHostWorkspace;
|
||||
|
||||
private _handleCounter: number;
|
||||
private _handlers: Map<number, vscode.DebugConfigurationProvider>;
|
||||
|
||||
private _debugServiceProxy: MainThreadDebugServiceShape;
|
||||
private _debugSessions: Map<DebugSessionUUID, ExtHostDebugSession> = new Map<DebugSessionUUID, ExtHostDebugSession>();
|
||||
|
||||
private _onDidStartDebugSession: Emitter<vscode.DebugSession>;
|
||||
private readonly _onDidStartDebugSession: Emitter<vscode.DebugSession>;
|
||||
get onDidStartDebugSession(): Event<vscode.DebugSession> { return this._onDidStartDebugSession.event; }
|
||||
|
||||
private _onDidTerminateDebugSession: Emitter<vscode.DebugSession>;
|
||||
private readonly _onDidTerminateDebugSession: Emitter<vscode.DebugSession>;
|
||||
get onDidTerminateDebugSession(): Event<vscode.DebugSession> { return this._onDidTerminateDebugSession.event; }
|
||||
|
||||
private _onDidChangeActiveDebugSession: Emitter<vscode.DebugSession | undefined>;
|
||||
private readonly _onDidChangeActiveDebugSession: Emitter<vscode.DebugSession | undefined>;
|
||||
get onDidChangeActiveDebugSession(): Event<vscode.DebugSession | undefined> { return this._onDidChangeActiveDebugSession.event; }
|
||||
|
||||
private _activeDebugSession: ExtHostDebugSession | undefined;
|
||||
get activeDebugSession(): ExtHostDebugSession | undefined { return this._activeDebugSession; }
|
||||
|
||||
private _onDidReceiveDebugSessionCustomEvent: Emitter<vscode.DebugSessionCustomEvent>;
|
||||
private readonly _onDidReceiveDebugSessionCustomEvent: Emitter<vscode.DebugSessionCustomEvent>;
|
||||
get onDidReceiveDebugSessionCustomEvent(): Event<vscode.DebugSessionCustomEvent> { return this._onDidReceiveDebugSessionCustomEvent.event; }
|
||||
|
||||
private _activeDebugConsole: ExtHostDebugConsole;
|
||||
@@ -52,12 +58,19 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
private _breakpoints: Map<string, vscode.Breakpoint>;
|
||||
private _breakpointEventsActive: boolean;
|
||||
|
||||
private _onDidChangeBreakpoints: Emitter<vscode.BreakpointsChangeEvent>;
|
||||
private readonly _onDidChangeBreakpoints: Emitter<vscode.BreakpointsChangeEvent>;
|
||||
|
||||
private _debugAdapters: Map<number, DebugAdapter>;
|
||||
|
||||
private _variableResolver: IConfigurationResolverService;
|
||||
|
||||
|
||||
constructor(mainContext: IMainContext, workspace: ExtHostWorkspace) {
|
||||
|
||||
this._workspace = workspace;
|
||||
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>();
|
||||
@@ -79,6 +92,86 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
|
||||
this._breakpoints = new Map<string, vscode.Breakpoint>();
|
||||
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> {
|
||||
const mythis = this;
|
||||
|
||||
const da = new class extends DebugAdapter {
|
||||
|
||||
// DA -> VS Code
|
||||
public acceptMessage(message: DebugProtocol.ProtocolMessage) {
|
||||
convertToVSCPaths(message, source => {
|
||||
if (paths.isAbsolute(source.path)) {
|
||||
(<any>source).path = URI.file(source.path);
|
||||
}
|
||||
});
|
||||
mythis._debugServiceProxy.$acceptDAMessage(handle, message);
|
||||
}
|
||||
|
||||
}(debugType, adpaterExecutable, this._extensionService.getAllExtensionDescriptions());
|
||||
|
||||
this._debugAdapters.set(handle, da);
|
||||
da.onError(err => this._debugServiceProxy.$acceptDAError(handle, err.name, err.message, err.stack));
|
||||
da.onExit(code => this._debugServiceProxy.$acceptDAExit(handle, code, null));
|
||||
return da.startSession();
|
||||
}
|
||||
|
||||
public $sendDAMessage(handle: number, message: DebugProtocol.ProtocolMessage): TPromise<void> {
|
||||
// VS Code -> DA
|
||||
convertToDAPaths(message, source => {
|
||||
if (typeof source.path === 'object') {
|
||||
source.path = URI.revive(source.path).fsPath;
|
||||
}
|
||||
});
|
||||
const da = this._debugAdapters.get(handle);
|
||||
if (da) {
|
||||
da.sendMessage(message);
|
||||
}
|
||||
return void 0;
|
||||
}
|
||||
|
||||
public $stopDASession(handle: number): TPromise<void> {
|
||||
const da = this._debugAdapters.get(handle);
|
||||
this._debugAdapters.delete(handle);
|
||||
return da ? da.stopSession() : void 0;
|
||||
}
|
||||
|
||||
private startBreakpoints() {
|
||||
@@ -113,18 +206,15 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
if (!this._breakpoints.has(bpd.id)) {
|
||||
let bp: vscode.Breakpoint;
|
||||
if (bpd.type === 'function') {
|
||||
bp = new FunctionBreakpoint(bpd.functionName, bpd.enabled, bpd.condition, bpd.hitCondition);
|
||||
bp = new FunctionBreakpoint(bpd.functionName, bpd.enabled, bpd.condition, bpd.hitCondition, bpd.logMessage);
|
||||
} else {
|
||||
const uri = URI.revive(bpd.uri);
|
||||
bp = new SourceBreakpoint(new Location(uri, new Position(bpd.line, bpd.character)), bpd.enabled, bpd.condition, bpd.hitCondition);
|
||||
bp = new SourceBreakpoint(new Location(uri, new Position(bpd.line, bpd.character)), bpd.enabled, bpd.condition, bpd.hitCondition, bpd.logMessage);
|
||||
}
|
||||
bp['_id'] = bpd.id;
|
||||
this._breakpoints.set(bpd.id, bp);
|
||||
a.push(bp);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,17 +232,20 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
for (const bpd of delta.changed) {
|
||||
let bp = this._breakpoints.get(bpd.id);
|
||||
if (bp) {
|
||||
if (bpd.type === 'function') {
|
||||
if (bp instanceof FunctionBreakpoint && bpd.type === 'function') {
|
||||
const fbp = <any>bp;
|
||||
fbp.enabled = bpd.enabled;
|
||||
fbp.condition = bpd.condition;
|
||||
fbp.hitCondition = bpd.hitCondition;
|
||||
fbp.logMessage = bpd.logMessage;
|
||||
fbp.functionName = bpd.functionName;
|
||||
} else {
|
||||
} else if (bp instanceof SourceBreakpoint && bpd.type === 'source') {
|
||||
const sbp = <any>bp;
|
||||
sbp.enabled = bpd.enabled;
|
||||
sbp.condition = bpd.condition;
|
||||
sbp.hitCondition = bpd.hitCondition;
|
||||
sbp.logMessage = bpd.logMessage;
|
||||
sbp.location = new Location(URI.revive(bpd.uri), new Position(bpd.line, bpd.character));
|
||||
}
|
||||
c.push(bp);
|
||||
}
|
||||
@@ -207,6 +300,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
enabled: bp.enabled,
|
||||
condition: bp.condition,
|
||||
hitCondition: bp.hitCondition,
|
||||
logMessage: bp.logMessage,
|
||||
line: bp.location.range.start.line,
|
||||
character: bp.location.range.start.character
|
||||
});
|
||||
@@ -215,9 +309,10 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
type: 'function',
|
||||
id: bp['_id'],
|
||||
enabled: bp.enabled,
|
||||
functionName: bp.functionName,
|
||||
hitCondition: bp.hitCondition,
|
||||
condition: bp.condition
|
||||
logMessage: bp.logMessage,
|
||||
condition: bp.condition,
|
||||
functionName: bp.functionName
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,10 @@ export class ExtHostDecorations implements ExtHostDecorationsShape {
|
||||
return TPromise.join(requests.map(request => {
|
||||
const { handle, uri, id } = request;
|
||||
const provider = this._provider.get(handle);
|
||||
if (!provider) {
|
||||
// might have been unregistered in the meantime
|
||||
return void 0;
|
||||
}
|
||||
return asWinJsPromise(token => provider.provideDecoration(URI.revive(uri), token)).then(data => {
|
||||
result[id] = data && <DecorationData>[data.priority, data.bubble, data.title, data.abbreviation, data.color, data.source];
|
||||
}, err => {
|
||||
|
||||
@@ -5,31 +5,36 @@
|
||||
'use strict';
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import { IMarkerData } from 'vs/platform/markers/common/markers';
|
||||
import { IMarkerData, MarkerSeverity } from 'vs/platform/markers/common/markers';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import * as vscode from 'vscode';
|
||||
import { MainContext, MainThreadDiagnosticsShape, ExtHostDiagnosticsShape, IMainContext } from './extHost.protocol';
|
||||
import { DiagnosticSeverity } from './extHostTypes';
|
||||
import * as converter from './extHostTypeConverters';
|
||||
import { mergeSort } from 'vs/base/common/arrays';
|
||||
import { Event, Emitter, debounceEvent, mapEvent } from 'vs/base/common/event';
|
||||
import { keys } from 'vs/base/common/map';
|
||||
|
||||
export class DiagnosticCollection implements vscode.DiagnosticCollection {
|
||||
|
||||
private static readonly _maxDiagnosticsPerFile: number = 250;
|
||||
|
||||
private readonly _name: string;
|
||||
private readonly _onDidChangeDiagnostics: Emitter<(vscode.Uri | string)[]>;
|
||||
|
||||
private _proxy: MainThreadDiagnosticsShape;
|
||||
private _isDisposed = false;
|
||||
private _data = new Map<string, vscode.Diagnostic[]>();
|
||||
|
||||
constructor(name: string, proxy: MainThreadDiagnosticsShape) {
|
||||
constructor(name: string, proxy: MainThreadDiagnosticsShape, onDidChangeDiagnostics: Emitter<(vscode.Uri | string)[]>) {
|
||||
this._name = name;
|
||||
this._proxy = proxy;
|
||||
this._onDidChangeDiagnostics = onDidChangeDiagnostics;
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
if (!this._isDisposed) {
|
||||
this._onDidChangeDiagnostics.fire(keys(this._data));
|
||||
this._proxy.$clear(this.name);
|
||||
this._proxy = undefined;
|
||||
this._data = undefined;
|
||||
@@ -111,7 +116,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
|
||||
orderLoop: for (let i = 0; i < 4; i++) {
|
||||
for (let diagnostic of diagnostics) {
|
||||
if (diagnostic.severity === order[i]) {
|
||||
const len = marker.push(DiagnosticCollection.toMarkerData(diagnostic));
|
||||
const len = marker.push(converter.fromDiagnostic(diagnostic));
|
||||
if (len === DiagnosticCollection._maxDiagnosticsPerFile) {
|
||||
break orderLoop;
|
||||
}
|
||||
@@ -121,7 +126,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
|
||||
|
||||
// add 'signal' marker for showing omitted errors/warnings
|
||||
marker.push({
|
||||
severity: Severity.Error,
|
||||
severity: MarkerSeverity.Error,
|
||||
message: localize({ key: 'limitHit', comment: ['amount of errors/warning skipped due to limits'] }, "Not showing {0} further errors and warnings.", diagnostics.length - DiagnosticCollection._maxDiagnosticsPerFile),
|
||||
startLineNumber: marker[marker.length - 1].startLineNumber,
|
||||
startColumn: marker[marker.length - 1].startColumn,
|
||||
@@ -129,13 +134,14 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
|
||||
endColumn: marker[marker.length - 1].endColumn
|
||||
});
|
||||
} else {
|
||||
marker = diagnostics.map(DiagnosticCollection.toMarkerData);
|
||||
marker = diagnostics.map(converter.fromDiagnostic);
|
||||
}
|
||||
}
|
||||
|
||||
entries.push([uri, marker]);
|
||||
}
|
||||
|
||||
this._onDidChangeDiagnostics.fire(toSync);
|
||||
this._proxy.$changeMany(this.name, entries);
|
||||
}
|
||||
|
||||
@@ -147,6 +153,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
|
||||
|
||||
clear(): void {
|
||||
this._checkDisposed();
|
||||
this._onDidChangeDiagnostics.fire(keys(this._data));
|
||||
this._data.clear();
|
||||
this._proxy.$clear(this.name);
|
||||
}
|
||||
@@ -179,32 +186,6 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
|
||||
}
|
||||
}
|
||||
|
||||
public static toMarkerData(diagnostic: vscode.Diagnostic): IMarkerData {
|
||||
|
||||
let range = diagnostic.range;
|
||||
|
||||
return <IMarkerData>{
|
||||
startLineNumber: range.start.line + 1,
|
||||
startColumn: range.start.character + 1,
|
||||
endLineNumber: range.end.line + 1,
|
||||
endColumn: range.end.character + 1,
|
||||
message: diagnostic.message,
|
||||
source: diagnostic.source,
|
||||
severity: DiagnosticCollection._convertDiagnosticsSeverity(diagnostic.severity),
|
||||
code: String(diagnostic.code)
|
||||
};
|
||||
}
|
||||
|
||||
private static _convertDiagnosticsSeverity(severity: number): Severity {
|
||||
switch (severity) {
|
||||
case 0: return Severity.Error;
|
||||
case 1: return Severity.Warning;
|
||||
case 2: return Severity.Info;
|
||||
case 3: return Severity.Ignore;
|
||||
default: return Severity.Error;
|
||||
}
|
||||
}
|
||||
|
||||
private static _compareIndexedTuplesByUri(a: [vscode.Uri, vscode.Diagnostic[]], b: [vscode.Uri, vscode.Diagnostic[]]): number {
|
||||
if (a[0].toString() < b[0].toString()) {
|
||||
return -1;
|
||||
@@ -220,12 +201,42 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
|
||||
|
||||
private static _idPool: number = 0;
|
||||
|
||||
private _proxy: MainThreadDiagnosticsShape;
|
||||
private _collections: DiagnosticCollection[];
|
||||
private readonly _proxy: MainThreadDiagnosticsShape;
|
||||
private readonly _collections: DiagnosticCollection[] = [];
|
||||
private readonly _onDidChangeDiagnostics = new Emitter<(vscode.Uri | string)[]>();
|
||||
|
||||
static _debouncer(last: (vscode.Uri | string)[], current: (vscode.Uri | string)[]): (vscode.Uri | string)[] {
|
||||
if (!last) {
|
||||
return current;
|
||||
} else {
|
||||
return last.concat(current);
|
||||
}
|
||||
}
|
||||
|
||||
static _mapper(last: (vscode.Uri | string)[]): { uris: vscode.Uri[] } {
|
||||
let uris: vscode.Uri[] = [];
|
||||
let map = new Set<string>();
|
||||
for (const uri of last) {
|
||||
if (typeof uri === 'string') {
|
||||
if (!map.has(uri)) {
|
||||
map.add(uri);
|
||||
uris.push(URI.parse(uri));
|
||||
}
|
||||
} else {
|
||||
if (!map.has(uri.toString())) {
|
||||
map.add(uri.toString());
|
||||
uris.push(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
Object.freeze(uris);
|
||||
return { uris };
|
||||
}
|
||||
|
||||
readonly onDidChangeDiagnostics: Event<vscode.DiagnosticChangeEvent> = mapEvent(debounceEvent(this._onDidChangeDiagnostics.event, ExtHostDiagnostics._debouncer, 50), ExtHostDiagnostics._mapper);
|
||||
|
||||
constructor(mainContext: IMainContext) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadDiagnostics);
|
||||
this._collections = [];
|
||||
}
|
||||
|
||||
createDiagnosticCollection(name: string): vscode.DiagnosticCollection {
|
||||
@@ -233,10 +244,10 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
|
||||
name = '_generated_diagnostic_collection_name_#' + ExtHostDiagnostics._idPool++;
|
||||
}
|
||||
|
||||
const { _collections, _proxy } = this;
|
||||
const { _collections, _proxy, _onDidChangeDiagnostics } = this;
|
||||
const result = new class extends DiagnosticCollection {
|
||||
constructor() {
|
||||
super(name, _proxy);
|
||||
super(name, _proxy, _onDidChangeDiagnostics);
|
||||
_collections.push(this);
|
||||
}
|
||||
dispose() {
|
||||
@@ -251,7 +262,36 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
|
||||
return result;
|
||||
}
|
||||
|
||||
forEach(callback: (collection: DiagnosticCollection) => any): void {
|
||||
this._collections.forEach(callback);
|
||||
getDiagnostics(resource: vscode.Uri): vscode.Diagnostic[];
|
||||
getDiagnostics(): [vscode.Uri, vscode.Diagnostic[]][];
|
||||
getDiagnostics(resource?: vscode.Uri): vscode.Diagnostic[] | [vscode.Uri, vscode.Diagnostic[]][] {
|
||||
if (resource) {
|
||||
return this._getDiagnostics(resource);
|
||||
} else {
|
||||
let index = new Map<string, number>();
|
||||
let res: [vscode.Uri, vscode.Diagnostic[]][] = [];
|
||||
for (const collection of this._collections) {
|
||||
collection.forEach((uri, diagnostics) => {
|
||||
let idx = index.get(uri.toString());
|
||||
if (typeof idx === 'undefined') {
|
||||
idx = res.length;
|
||||
index.set(uri.toString(), idx);
|
||||
res.push([uri, []]);
|
||||
}
|
||||
res[idx][1] = res[idx][1].concat(...diagnostics);
|
||||
});
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
private _getDiagnostics(resource: vscode.Uri): vscode.Diagnostic[] {
|
||||
let res: vscode.Diagnostic[] = [];
|
||||
for (const collection of this._collections) {
|
||||
if (collection.has(resource)) {
|
||||
res = res.concat(collection.get(resource));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import { asWinJsPromise } from 'vs/base/common/async';
|
||||
import { MainContext, ExtHostDocumentContentProvidersShape, MainThreadDocumentContentProvidersShape, IMainContext } from './extHost.protocol';
|
||||
import { ExtHostDocumentsAndEditors } from './extHostDocumentsAndEditors';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
||||
export class ExtHostDocumentContentProvider implements ExtHostDocumentContentProvidersShape {
|
||||
|
||||
@@ -21,11 +22,13 @@ export class ExtHostDocumentContentProvider implements ExtHostDocumentContentPro
|
||||
|
||||
private readonly _documentContentProviders = new Map<number, vscode.TextDocumentContentProvider>();
|
||||
private readonly _proxy: MainThreadDocumentContentProvidersShape;
|
||||
private readonly _documentsAndEditors: ExtHostDocumentsAndEditors;
|
||||
|
||||
constructor(mainContext: IMainContext, documentsAndEditors: ExtHostDocumentsAndEditors) {
|
||||
constructor(
|
||||
mainContext: IMainContext,
|
||||
private readonly _documentsAndEditors: ExtHostDocumentsAndEditors,
|
||||
private readonly _logService: ILogService,
|
||||
) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadDocumentContentProviders);
|
||||
this._documentsAndEditors = documentsAndEditors;
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
@@ -47,6 +50,10 @@ export class ExtHostDocumentContentProvider implements ExtHostDocumentContentPro
|
||||
let subscription: IDisposable;
|
||||
if (typeof provider.onDidChange === 'function') {
|
||||
subscription = provider.onDidChange(uri => {
|
||||
if (uri.scheme !== scheme) {
|
||||
this._logService.warn(`Provider for scheme '${scheme}' is firing event for schema '${uri.scheme}' which will be IGNORED`);
|
||||
return;
|
||||
}
|
||||
if (this._documentsAndEditors.getDocument(uri.toString())) {
|
||||
this.$provideTextDocumentContent(handle, uri).then(value => {
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import * as vscode from 'vscode';
|
||||
import { getWordAtText, ensureValidWordDefinition } from 'vs/editor/common/model/wordHelper';
|
||||
import { MainThreadDocumentsShape } from './extHost.protocol';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
|
||||
const _modeId2WordDefinition = new Map<string, RegExp>();
|
||||
export function setWordDefinitionFor(modeId: string, wordDefinition: RegExp): void {
|
||||
@@ -68,9 +69,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
|
||||
get isUntitled() { return data._uri.scheme !== 'file'; },
|
||||
get isUntitled() { return data._uri.scheme === Schemas.untitled; },
|
||||
get languageId() { return data._languageId; },
|
||||
get version() { return data._versionId; },
|
||||
get isClosed() { return data._isDisposed; },
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import Event from 'vs/base/common/event';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import URI, { UriComponents } from 'vs/base/common/uri';
|
||||
import { sequence, always } from 'vs/base/common/async';
|
||||
import { illegalState } from 'vs/base/common/errors';
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import URI, { UriComponents } from 'vs/base/common/uri';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import * as TypeConverters from './extHostTypeConverters';
|
||||
@@ -137,6 +137,7 @@ export class ExtHostDocuments implements ExtHostDocumentsShape {
|
||||
contentChanges: events.changes.map((change) => {
|
||||
return {
|
||||
range: TypeConverters.toRange(change.range),
|
||||
rangeOffset: change.rangeOffset,
|
||||
rangeLength: change.rangeLength,
|
||||
text: change.text
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { dispose } from 'vs/base/common/lifecycle';
|
||||
import { MainContext, ExtHostDocumentsAndEditorsShape, IDocumentsAndEditorsDelta, IMainContext } from './extHost.protocol';
|
||||
import { ExtHostDocumentData } from './extHostDocumentData';
|
||||
@@ -12,7 +12,6 @@ import { ExtHostTextEditor } from './extHostTextEditor';
|
||||
import * as assert from 'assert';
|
||||
import * as typeConverters from './extHostTypeConverters';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { ExtHostWebview, ExtHostWebviews } from './extHostWebview';
|
||||
import { Disposable } from './extHostTypes';
|
||||
|
||||
export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsShape {
|
||||
@@ -20,7 +19,6 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
|
||||
private _disposables: Disposable[] = [];
|
||||
|
||||
private _activeEditorId: string;
|
||||
private _activeWebview: ExtHostWebview;
|
||||
|
||||
private readonly _editors = new Map<string, ExtHostTextEditor>();
|
||||
private readonly _documents = new Map<string, ExtHostDocumentData>();
|
||||
@@ -29,31 +27,15 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
|
||||
private readonly _onDidRemoveDocuments = new Emitter<ExtHostDocumentData[]>();
|
||||
private readonly _onDidChangeVisibleTextEditors = new Emitter<ExtHostTextEditor[]>();
|
||||
private readonly _onDidChangeActiveTextEditor = new Emitter<ExtHostTextEditor>();
|
||||
private readonly _onDidChangeActiveEditor = new Emitter<ExtHostTextEditor | ExtHostWebview>();
|
||||
|
||||
readonly onDidAddDocuments: Event<ExtHostDocumentData[]> = this._onDidAddDocuments.event;
|
||||
readonly onDidRemoveDocuments: Event<ExtHostDocumentData[]> = this._onDidRemoveDocuments.event;
|
||||
readonly onDidChangeVisibleTextEditors: Event<ExtHostTextEditor[]> = this._onDidChangeVisibleTextEditors.event;
|
||||
readonly onDidChangeActiveTextEditor: Event<ExtHostTextEditor> = this._onDidChangeActiveTextEditor.event;
|
||||
readonly onDidChangeActiveEditor: Event<ExtHostTextEditor | ExtHostWebview> = this._onDidChangeActiveEditor.event;
|
||||
|
||||
constructor(
|
||||
private readonly _mainContext: IMainContext,
|
||||
_extHostWebviews?: ExtHostWebviews
|
||||
) {
|
||||
if (_extHostWebviews) {
|
||||
_extHostWebviews.onDidChangeActiveWebview(webview => {
|
||||
if (webview) {
|
||||
if (webview !== this._activeWebview) {
|
||||
this._onDidChangeActiveEditor.fire(webview);
|
||||
this._activeWebview = webview;
|
||||
}
|
||||
} else {
|
||||
this._activeWebview = webview;
|
||||
}
|
||||
}, this, this._disposables);
|
||||
}
|
||||
}
|
||||
) { }
|
||||
|
||||
dispose() {
|
||||
this._disposables = dispose(this._disposables);
|
||||
@@ -143,9 +125,6 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
|
||||
}
|
||||
if (delta.newActiveEditor !== undefined) {
|
||||
this._onDidChangeActiveTextEditor.fire(this.activeEditor());
|
||||
|
||||
const activeEditor = this.activeEditor();
|
||||
this._onDidChangeActiveEditor.fire(activeEditor || this._activeWebview);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ export interface IExtensionContext {
|
||||
storagePath: string;
|
||||
asAbsolutePath(relativePath: string): string;
|
||||
logger: ExtHostLogger;
|
||||
readonly logDirectory: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,6 +127,7 @@ export class ExtensionActivationTimesBuilder {
|
||||
export class ActivatedExtension {
|
||||
|
||||
public readonly activationFailed: boolean;
|
||||
public readonly activationFailedError: Error;
|
||||
public readonly activationTimes: ExtensionActivationTimes;
|
||||
public readonly module: IExtensionModule;
|
||||
public readonly exports: IExtensionAPI;
|
||||
@@ -133,12 +135,14 @@ export class ActivatedExtension {
|
||||
|
||||
constructor(
|
||||
activationFailed: boolean,
|
||||
activationFailedError: Error,
|
||||
activationTimes: ExtensionActivationTimes,
|
||||
module: IExtensionModule,
|
||||
exports: IExtensionAPI,
|
||||
subscriptions: IDisposable[]
|
||||
) {
|
||||
this.activationFailed = activationFailed;
|
||||
this.activationFailedError = activationFailedError;
|
||||
this.activationTimes = activationTimes;
|
||||
this.module = module;
|
||||
this.exports = exports;
|
||||
@@ -148,13 +152,13 @@ export class ActivatedExtension {
|
||||
|
||||
export class EmptyExtension extends ActivatedExtension {
|
||||
constructor(activationTimes: ExtensionActivationTimes) {
|
||||
super(false, activationTimes, { activate: undefined, deactivate: undefined }, undefined, []);
|
||||
super(false, null, activationTimes, { activate: undefined, deactivate: undefined }, undefined, []);
|
||||
}
|
||||
}
|
||||
|
||||
export class FailedExtension extends ActivatedExtension {
|
||||
constructor(activationTimes: ExtensionActivationTimes) {
|
||||
super(true, activationTimes, { activate: undefined, deactivate: undefined }, undefined, []);
|
||||
constructor(activationError: Error) {
|
||||
super(true, activationError, ExtensionActivationTimes.NONE, { activate: undefined, deactivate: undefined }, undefined, []);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,7 +247,8 @@ export class ExtensionsActivator {
|
||||
if (!depDesc) {
|
||||
// Error condition 1: unknown dependency
|
||||
this._host.showMessage(Severity.Error, nls.localize('unknownDep', "Extension '{1}' failed to activate. Reason: unknown dependency '{0}'.", depId, currentExtension.id));
|
||||
this._activatedExtensions[currentExtension.id] = new FailedExtension(ExtensionActivationTimes.NONE);
|
||||
const error = new Error(`Unknown dependency '${depId}'`);
|
||||
this._activatedExtensions[currentExtension.id] = new FailedExtension(error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -252,7 +257,9 @@ export class ExtensionsActivator {
|
||||
if (dep.activationFailed) {
|
||||
// Error condition 2: a dependency has already failed activation
|
||||
this._host.showMessage(Severity.Error, nls.localize('failedDep1', "Extension '{1}' failed to activate. Reason: dependency '{0}' failed to activate.", depId, currentExtension.id));
|
||||
this._activatedExtensions[currentExtension.id] = new FailedExtension(ExtensionActivationTimes.NONE);
|
||||
const error = new Error(`Dependency ${depId} failed to activate`);
|
||||
(<any>error).detail = dep.activationFailedError;
|
||||
this._activatedExtensions[currentExtension.id] = new FailedExtension(error);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -285,7 +292,8 @@ export class ExtensionsActivator {
|
||||
for (let i = 0, len = extensionDescriptions.length; i < len; i++) {
|
||||
// Error condition 3: dependency loop
|
||||
this._host.showMessage(Severity.Error, nls.localize('failedDep2', "Extension '{0}' failed to activate. Reason: more than 10 levels of dependencies (most likely a dependency loop).", extensionDescriptions[i].id));
|
||||
this._activatedExtensions[extensionDescriptions[i].id] = new FailedExtension(ExtensionActivationTimes.NONE);
|
||||
const error = new Error('More than 10 levels of dependencies (most likely a dependency loop)');
|
||||
this._activatedExtensions[extensionDescriptions[i].id] = new FailedExtension(error);
|
||||
}
|
||||
return TPromise.as(void 0);
|
||||
}
|
||||
@@ -333,7 +341,7 @@ export class ExtensionsActivator {
|
||||
console.error('Activating extension `' + extensionDescription.id + '` failed: ', err.message);
|
||||
console.log('Here is the error stack: ', err.stack);
|
||||
// Treat the extension as being empty
|
||||
return new FailedExtension(ExtensionActivationTimes.NONE);
|
||||
return new FailedExtension(err);
|
||||
}).then((x: ActivatedExtension) => {
|
||||
this._activatedExtensions[extensionDescription.id] = x;
|
||||
delete this._activatingExtensions[extensionDescription.id];
|
||||
|
||||
@@ -22,7 +22,6 @@ import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
|
||||
import { TernarySearchTree } from 'vs/base/common/map';
|
||||
import { Barrier } from 'vs/base/common/async';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService';
|
||||
import URI from 'vs/base/common/uri';
|
||||
|
||||
@@ -142,8 +141,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
extHostContext: IExtHostContext,
|
||||
extHostWorkspace: ExtHostWorkspace,
|
||||
extHostConfiguration: ExtHostConfiguration,
|
||||
extHostLogService: ExtHostLogService,
|
||||
environmentService: IEnvironmentService
|
||||
extHostLogService: ExtHostLogService
|
||||
) {
|
||||
this._barrier = new Barrier();
|
||||
this._registry = new ExtensionDescriptionRegistry(initData.extensions);
|
||||
@@ -212,6 +210,17 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
}
|
||||
}
|
||||
|
||||
public activateByIdWithErrors(extensionId: string, reason: ExtensionActivationReason): TPromise<void> {
|
||||
return this.activateById(extensionId, reason).then(() => {
|
||||
const extension = this._activator.getActivatedExtension(extensionId);
|
||||
if (extension.activationFailed) {
|
||||
// activation failed => bubble up the error as the promise result
|
||||
return TPromise.wrapError(extension.activationFailedError);
|
||||
}
|
||||
return void 0;
|
||||
});
|
||||
}
|
||||
|
||||
public getAllExtensionDescriptions(): IExtensionDescription[] {
|
||||
return this._registry.getAllExtensionDescriptions();
|
||||
}
|
||||
@@ -358,6 +367,10 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
get logger() {
|
||||
checkProposedApiEnabled(extensionDescription);
|
||||
return that._extHostLogService.getExtLogger(extensionDescription.id);
|
||||
},
|
||||
get logDirectory() {
|
||||
checkProposedApiEnabled(extensionDescription);
|
||||
return that._extHostLogService.getLogDirectory(extensionDescription.id);
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -371,7 +384,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
};
|
||||
|
||||
return this._callActivateOptional(logService, extensionId, extensionModule, context, activationTimesBuilder).then((extensionExports) => {
|
||||
return new ActivatedExtension(false, activationTimesBuilder.build(), extensionModule, extensionExports, context.subscriptions);
|
||||
return new ActivatedExtension(false, null, activationTimesBuilder.build(), extensionModule, extensionExports, context.subscriptions);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -423,7 +436,7 @@ function getTelemetryActivationEvent(extensionDescription: IExtensionDescription
|
||||
"TelemetryActivationEvent" : {
|
||||
"id": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
|
||||
"name": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
|
||||
"publisherDisplayName": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
|
||||
"publisherDisplayName": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"activationEvents": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
|
||||
"isBuiltin": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
|
||||
}
|
||||
|
||||
@@ -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 } 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,102 +57,245 @@ class FsLinkProvider implements vscode.DocumentLinkProvider {
|
||||
}
|
||||
}
|
||||
|
||||
class FileSystemProviderShim implements vscode.FileSystemProvider {
|
||||
|
||||
onDidChangeFile: vscode.Event<vscode.FileChangeEvent[]>;
|
||||
|
||||
constructor(private readonly _delegate: vscode.DeprecatedFileSystemProvider) {
|
||||
if (!this._delegate.onDidChange) {
|
||||
this.onDidChangeFile = Event.None;
|
||||
} else {
|
||||
this.onDidChangeFile = mapEvent(this._delegate.onDidChange, old => old.map(FileSystemProviderShim._modernizeFileChange));
|
||||
}
|
||||
}
|
||||
|
||||
watch(uri: vscode.Uri, options: {}): vscode.Disposable {
|
||||
// does nothing because in the old API there was no notion of
|
||||
// watch and provider decide what file events to generate...
|
||||
return { dispose() { } };
|
||||
}
|
||||
|
||||
stat(resource: vscode.Uri): Thenable<vscode.FileStat> {
|
||||
return this._delegate.stat(resource).then(stat => FileSystemProviderShim._modernizeFileStat(stat));
|
||||
}
|
||||
rename(oldUri: vscode.Uri, newUri: vscode.Uri): Thenable<void> {
|
||||
return this._delegate.move(oldUri, newUri).then(stat => void 0);
|
||||
}
|
||||
readDirectory(resource: vscode.Uri): Thenable<[string, vscode.FileType][]> {
|
||||
return this._delegate.readdir(resource).then(tuples => {
|
||||
return tuples.map(tuple => <[string, vscode.FileType]>[path.posix.basename(tuple[0].path), FileSystemProviderShim._modernizeFileStat(tuple[1]).type]);
|
||||
});
|
||||
}
|
||||
|
||||
private static _modernizeFileStat(stat: vscode.DeprecatedFileStat): vscode.FileStat {
|
||||
let { mtime, size, type } = stat;
|
||||
let newType: files.FileType;
|
||||
|
||||
// no support for bitmask, effectively no support for symlinks
|
||||
switch (type) {
|
||||
case DeprecatedFileType.Dir:
|
||||
newType = files.FileType.Directory;
|
||||
break;
|
||||
case DeprecatedFileType.File:
|
||||
newType = files.FileType.File;
|
||||
break;
|
||||
case DeprecatedFileType.Symlink:
|
||||
newType = files.FileType.File & files.FileType.SymbolicLink;
|
||||
break;
|
||||
}
|
||||
return { type: newType, ctime: 0, mtime, size };
|
||||
}
|
||||
|
||||
private static _modernizeFileChange(e: vscode.DeprecatedFileChange): vscode.FileChangeEvent {
|
||||
let { resource, type } = e;
|
||||
let newType: vscode.FileChangeType;
|
||||
switch (type) {
|
||||
case DeprecatedFileChangeType.Updated:
|
||||
newType = FileChangeType.Changed;
|
||||
break;
|
||||
case DeprecatedFileChangeType.Added:
|
||||
newType = FileChangeType.Created;
|
||||
break;
|
||||
case DeprecatedFileChangeType.Deleted:
|
||||
newType = FileChangeType.Deleted;
|
||||
break;
|
||||
|
||||
}
|
||||
return { uri: resource, type: newType };
|
||||
}
|
||||
|
||||
// --- delete/create file or folder
|
||||
|
||||
delete(resource: vscode.Uri): Thenable<void> {
|
||||
return this._delegate.stat(resource).then(stat => {
|
||||
if (stat.type === DeprecatedFileType.Dir) {
|
||||
return this._delegate.rmdir(resource);
|
||||
} else {
|
||||
return this._delegate.unlink(resource);
|
||||
}
|
||||
});
|
||||
}
|
||||
createDirectory(resource: vscode.Uri): Thenable<void> {
|
||||
return this._delegate.mkdir(resource).then(stat => void 0);
|
||||
}
|
||||
|
||||
// --- read/write
|
||||
|
||||
readFile(resource: vscode.Uri): Thenable<Uint8Array> {
|
||||
let chunks: Buffer[] = [];
|
||||
return this._delegate.read(resource, 0, -1, {
|
||||
report(data) {
|
||||
chunks.push(Buffer.from(data));
|
||||
}
|
||||
}).then(() => {
|
||||
return Buffer.concat(chunks);
|
||||
});
|
||||
}
|
||||
|
||||
writeFile(resource: vscode.Uri, content: Uint8Array, options: files.FileWriteOptions): Thenable<void> {
|
||||
return this._delegate.write(resource, content);
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
|
||||
private readonly _proxy: MainThreadFileSystemShape;
|
||||
private readonly _provider = new Map<number, vscode.FileSystemProvider>();
|
||||
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) {
|
||||
registerDeprecatedFileSystemProvider(scheme: string, provider: vscode.DeprecatedFileSystemProvider) {
|
||||
return this.registerFileSystemProvider(scheme, new FileSystemProviderShim(provider), { isCaseSensitive: false });
|
||||
}
|
||||
|
||||
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._provider.set(handle, provider);
|
||||
this._proxy.$registerFileSystemProvider(handle, scheme);
|
||||
if (provider.root) {
|
||||
// todo@remote
|
||||
this._proxy.$onDidAddFileSystemRoot(provider.root);
|
||||
this._usedSchemes.add(scheme);
|
||||
this._fsProvider.set(handle, provider);
|
||||
|
||||
let capabilites = files.FileSystemProviderCapabilities.FileReadWrite;
|
||||
if (options.isCaseSensitive) {
|
||||
capabilites += files.FileSystemProviderCapabilities.PathCaseSensitive;
|
||||
}
|
||||
let reg: IDisposable;
|
||||
if (provider.onDidChange) {
|
||||
reg = provider.onDidChange(event => this._proxy.$onFileSystemChange(handle, <any>event));
|
||||
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._provider.delete(handle);
|
||||
this._proxy.$unregisterFileSystemProvider(handle);
|
||||
this._usedSchemes.delete(scheme);
|
||||
this._fsProvider.delete(handle);
|
||||
this._proxy.$unregisterProvider(handle);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
$utimes(handle: number, resource: UriComponents, mtime: number, atime: number): TPromise<IStat, any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).utimes(URI.revive(resource), mtime, atime));
|
||||
private static _asIStat(stat: vscode.FileStat): files.IStat {
|
||||
const { type, ctime, mtime, size } = stat;
|
||||
return { type, ctime, mtime, size };
|
||||
}
|
||||
$stat(handle: number, resource: UriComponents): TPromise<IStat, any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).stat(URI.revive(resource)));
|
||||
|
||||
$stat(handle: number, resource: UriComponents): TPromise<files.IStat, any> {
|
||||
return asWinJsPromise(token => this._fsProvider.get(handle).stat(URI.revive(resource))).then(ExtHostFileSystem._asIStat);
|
||||
}
|
||||
$read(handle: number, session: number, offset: number, count: number, resource: UriComponents): TPromise<number> {
|
||||
const progress = {
|
||||
report: chunk => {
|
||||
this._proxy.$reportFileChunk(handle, session, [].slice.call(chunk));
|
||||
}
|
||||
};
|
||||
return asWinJsPromise(token => this._provider.get(handle).read(URI.revive(resource), offset, count, progress));
|
||||
|
||||
$readdir(handle: number, resource: UriComponents): TPromise<[string, files.FileType][], any> {
|
||||
return asWinJsPromise(token => this._fsProvider.get(handle).readDirectory(URI.revive(resource)));
|
||||
}
|
||||
$write(handle: number, resource: UriComponents, content: number[]): TPromise<void, any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).write(URI.revive(resource), Buffer.from(content)));
|
||||
|
||||
$readFile(handle: number, resource: UriComponents): TPromise<string> {
|
||||
return asWinJsPromise(token => {
|
||||
return this._fsProvider.get(handle).readFile(URI.revive(resource));
|
||||
}).then(data => {
|
||||
return Buffer.isBuffer(data) ? data.toString('base64') : Buffer.from(data.buffer, data.byteOffset, data.byteLength).toString('base64');
|
||||
});
|
||||
}
|
||||
$unlink(handle: number, resource: UriComponents): TPromise<void, any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).unlink(URI.revive(resource)));
|
||||
|
||||
$writeFile(handle: number, resource: UriComponents, base64Content: string, opts: files.FileWriteOptions): TPromise<void, any> {
|
||||
return asWinJsPromise(token => this._fsProvider.get(handle).writeFile(URI.revive(resource), Buffer.from(base64Content, 'base64'), opts));
|
||||
}
|
||||
$move(handle: number, resource: UriComponents, target: UriComponents): TPromise<IStat, any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).move(URI.revive(resource), URI.revive(target)));
|
||||
|
||||
$delete(handle: number, resource: UriComponents): TPromise<void, any> {
|
||||
return asWinJsPromise(token => this._fsProvider.get(handle).delete(URI.revive(resource), { recursive: true }));
|
||||
}
|
||||
$mkdir(handle: number, resource: UriComponents): TPromise<IStat, any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).mkdir(URI.revive(resource)));
|
||||
|
||||
$rename(handle: number, oldUri: UriComponents, newUri: UriComponents, opts: files.FileOverwriteOptions): TPromise<void, any> {
|
||||
return asWinJsPromise(token => this._fsProvider.get(handle).rename(URI.revive(oldUri), URI.revive(newUri), opts));
|
||||
}
|
||||
$readdir(handle: number, resource: UriComponents): TPromise<[UriComponents, IStat][], any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).readdir(URI.revive(resource)));
|
||||
|
||||
$copy(handle: number, oldUri: UriComponents, newUri: UriComponents, opts: files.FileOverwriteOptions): TPromise<void, any> {
|
||||
return asWinJsPromise(token => this._fsProvider.get(handle).copy(URI.revive(oldUri), URI.revive(newUri), opts));
|
||||
}
|
||||
$rmdir(handle: number, resource: UriComponents): TPromise<void, any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).rmdir(URI.revive(resource)));
|
||||
|
||||
$mkdir(handle: number, resource: UriComponents): TPromise<void, any> {
|
||||
return asWinJsPromise(token => this._fsProvider.get(handle).createDirectory(URI.revive(resource)));
|
||||
}
|
||||
$findFiles(handle: number, session: number, query: string): TPromise<void> {
|
||||
const provider = this._provider.get(handle);
|
||||
if (!provider.findFiles) {
|
||||
return TPromise.as(undefined);
|
||||
|
||||
$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: (uri) => {
|
||||
this._proxy.$handleFindMatch(handle, session, uri);
|
||||
}
|
||||
};
|
||||
return asWinJsPromise(token => provider.findFiles(query, progress, token));
|
||||
}
|
||||
$provideTextSearchResults(handle: number, session: number, pattern: IPatternInfo, options: { includes: string[], excludes: string[] }): TPromise<void> {
|
||||
const provider = this._provider.get(handle);
|
||||
if (!provider.provideTextSearchResults) {
|
||||
return TPromise.as(undefined);
|
||||
}
|
||||
const progress = {
|
||||
report: (data: vscode.TextSearchResult) => {
|
||||
this._proxy.$handleFindMatch(handle, session, [data.uri, {
|
||||
lineNumber: 1 + 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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { Disposable } from './extHostTypes';
|
||||
import { parse, IRelativePattern } from 'vs/base/common/glob';
|
||||
import { Uri, FileSystemWatcher as _FileSystemWatcher } from 'vscode';
|
||||
|
||||
@@ -9,19 +9,20 @@ 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, Color, 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';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
|
||||
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands';
|
||||
import { ExtHostDiagnostics, DiagnosticCollection } from 'vs/workbench/api/node/extHostDiagnostics';
|
||||
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
|
||||
import { asWinJsPromise } from 'vs/base/common/async';
|
||||
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, SymbolInformationDto, SuggestResultDto, WorkspaceSymbolsDto, SuggestionDto, CodeActionDto } from './extHost.protocol';
|
||||
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, SymbolInformationDto, SuggestResultDto, WorkspaceSymbolsDto, SuggestionDto, CodeActionDto, ISerializedDocumentFilter } from './extHost.protocol';
|
||||
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)));
|
||||
}
|
||||
@@ -280,15 +284,11 @@ class CodeActionAdapter {
|
||||
const ran = <vscode.Range>TypeConverters.toRange(range);
|
||||
const allDiagnostics: vscode.Diagnostic[] = [];
|
||||
|
||||
this._diagnostics.forEach(collection => {
|
||||
if (collection.has(resource)) {
|
||||
for (let diagnostic of collection.get(resource)) {
|
||||
if (ran.contains(diagnostic.range)) {
|
||||
allDiagnostics.push(diagnostic);
|
||||
}
|
||||
}
|
||||
for (const diagnostic of this._diagnostics.getDiagnostics(resource)) {
|
||||
if (ran.contains(diagnostic.range)) {
|
||||
allDiagnostics.push(diagnostic);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const codeActionContext: vscode.CodeActionContext = {
|
||||
diagnostics: allDiagnostics,
|
||||
@@ -317,7 +317,7 @@ class CodeActionAdapter {
|
||||
result.push({
|
||||
title: candidate.title,
|
||||
command: candidate.command && this._commands.toInternal(candidate.command),
|
||||
diagnostics: candidate.diagnostics && candidate.diagnostics.map(DiagnosticCollection.toMarkerData),
|
||||
diagnostics: candidate.diagnostics && candidate.diagnostics.map(TypeConverters.fromDiagnostic),
|
||||
edit: candidate.edit && TypeConverters.WorkspaceEdit.from(candidate.edit),
|
||||
kind: candidate.kind && candidate.kind.value
|
||||
});
|
||||
@@ -468,20 +468,16 @@ class NavigateTypeAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
interface RenameProvider2 extends vscode.RenameProvider {
|
||||
resolveInitialRenameValue?(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.ProviderResult<any>;
|
||||
}
|
||||
|
||||
class RenameAdapter {
|
||||
|
||||
static supportsResolving(provider: RenameProvider2): boolean {
|
||||
return typeof provider.resolveInitialRenameValue === 'function';
|
||||
static supportsResolving(provider: vscode.RenameProvider): boolean {
|
||||
return typeof provider.prepareRename === 'function';
|
||||
}
|
||||
|
||||
private _documents: ExtHostDocuments;
|
||||
private _provider: RenameProvider2;
|
||||
private _provider: vscode.RenameProvider;
|
||||
|
||||
constructor(documents: ExtHostDocuments, provider: RenameProvider2) {
|
||||
constructor(documents: ExtHostDocuments, provider: vscode.RenameProvider) {
|
||||
this._documents = documents;
|
||||
this._provider = provider;
|
||||
}
|
||||
@@ -514,24 +510,40 @@ class RenameAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
resolveInitialRenameValue(resource: URI, position: IPosition): TPromise<modes.RenameInitialValue> {
|
||||
if (typeof this._provider.resolveInitialRenameValue !== 'function') {
|
||||
resolveRenameLocation(resource: URI, position: IPosition): TPromise<modes.RenameLocation> {
|
||||
if (typeof this._provider.prepareRename !== 'function') {
|
||||
return TPromise.as(undefined);
|
||||
}
|
||||
|
||||
let doc = this._documents.getDocumentData(resource).document;
|
||||
let pos = TypeConverters.toPosition(position);
|
||||
|
||||
return asWinJsPromise(token => this._provider.resolveInitialRenameValue(doc, pos, token)).then((value) => {
|
||||
return <modes.RenameInitialValue>{
|
||||
range: TypeConverters.fromRange(value.range),
|
||||
text: value.text
|
||||
};
|
||||
return asWinJsPromise(token => this._provider.prepareRename(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.contains(pos)) {
|
||||
console.warn('INVALID rename location: range must contain position');
|
||||
return undefined;
|
||||
}
|
||||
return { range: TypeConverters.fromRange(range), text };
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class SuggestAdapter {
|
||||
|
||||
static supportsResolving(provider: vscode.CompletionItemProvider): boolean {
|
||||
@@ -785,7 +797,7 @@ class ColorProviderAdapter {
|
||||
|
||||
const colorInfos: IRawColorInfo[] = colors.map(ci => {
|
||||
return {
|
||||
color: [ci.color.red, ci.color.green, ci.color.blue, ci.color.alpha] as [number, number, number, number],
|
||||
color: TypeConverters.Color.from(ci.color),
|
||||
range: TypeConverters.fromRange(ci.range)
|
||||
};
|
||||
});
|
||||
@@ -797,7 +809,7 @@ class ColorProviderAdapter {
|
||||
provideColorPresentations(resource: URI, raw: IRawColorInfo): TPromise<modes.IColorPresentation[]> {
|
||||
const document = this._documents.getDocumentData(resource).document;
|
||||
const range = TypeConverters.toRange(raw.range);
|
||||
const color = new Color(raw.color[0], raw.color[1], raw.color[2], raw.color[3]);
|
||||
const color = TypeConverters.Color.to(raw.color);
|
||||
return asWinJsPromise(token => this._provider.provideColorPresentations(color, { document, range }, token)).then(value => {
|
||||
return value.map(TypeConverters.ColorPresentation.from);
|
||||
});
|
||||
@@ -808,16 +820,16 @@ class FoldingProviderAdapter {
|
||||
|
||||
constructor(
|
||||
private _documents: ExtHostDocuments,
|
||||
private _provider: vscode.FoldingProvider
|
||||
private _provider: vscode.FoldingRangeProvider
|
||||
) { }
|
||||
|
||||
provideFoldingRanges(resource: URI): 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, 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);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -828,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;
|
||||
@@ -841,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;
|
||||
@@ -853,6 +872,42 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
this._diagnostics = diagnostics;
|
||||
}
|
||||
|
||||
private _transformDocumentSelector(selector: vscode.DocumentSelector): ISerializedDocumentFilter[] {
|
||||
if (Array.isArray(selector)) {
|
||||
return selector.map(sel => this._doTransformDocumentSelector(sel));
|
||||
}
|
||||
|
||||
return [this._doTransformDocumentSelector(selector)];
|
||||
}
|
||||
|
||||
private _doTransformDocumentSelector(selector: string | vscode.DocumentFilter): ISerializedDocumentFilter {
|
||||
if (typeof selector === 'string') {
|
||||
return {
|
||||
$serialized: true,
|
||||
language: selector
|
||||
};
|
||||
}
|
||||
|
||||
if (selector) {
|
||||
return {
|
||||
$serialized: true,
|
||||
language: selector.language,
|
||||
scheme: this._transformScheme(selector.scheme),
|
||||
pattern: selector.pattern,
|
||||
exclusive: selector.exclusive
|
||||
};
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private _transformScheme(scheme: string): string {
|
||||
if (this._schemeTransformer && typeof scheme === 'string') {
|
||||
return this._schemeTransformer.transformOutgoing(scheme);
|
||||
}
|
||||
return scheme;
|
||||
}
|
||||
|
||||
private _createDisposable(handle: number): Disposable {
|
||||
return new Disposable(() => {
|
||||
this._adapter.delete(handle);
|
||||
@@ -882,7 +937,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
|
||||
registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new OutlineAdapter(this._documents, provider));
|
||||
this._proxy.$registerOutlineSupport(handle, selector);
|
||||
this._proxy.$registerOutlineSupport(handle, this._transformDocumentSelector(selector));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
@@ -897,7 +952,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
const eventHandle = typeof provider.onDidChangeCodeLenses === 'function' ? this._nextHandle() : undefined;
|
||||
|
||||
this._adapter.set(handle, new CodeLensAdapter(this._documents, this._commands.converter, this._heapService, provider));
|
||||
this._proxy.$registerCodeLensSupport(handle, selector, eventHandle);
|
||||
this._proxy.$registerCodeLensSupport(handle, this._transformDocumentSelector(selector), eventHandle);
|
||||
let result = this._createDisposable(handle);
|
||||
|
||||
if (eventHandle !== undefined) {
|
||||
@@ -920,7 +975,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
|
||||
registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new DefinitionAdapter(this._documents, provider));
|
||||
this._proxy.$registerDeclaractionSupport(handle, selector);
|
||||
this._proxy.$registerDeclaractionSupport(handle, this._transformDocumentSelector(selector));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
@@ -930,7 +985,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
|
||||
registerImplementationProvider(selector: vscode.DocumentSelector, provider: vscode.ImplementationProvider): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new ImplementationAdapter(this._documents, provider));
|
||||
this._proxy.$registerImplementationSupport(handle, selector);
|
||||
this._proxy.$registerImplementationSupport(handle, this._transformDocumentSelector(selector));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
@@ -940,7 +995,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
|
||||
registerTypeDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.TypeDefinitionProvider): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new TypeDefinitionAdapter(this._documents, provider));
|
||||
this._proxy.$registerTypeDefinitionSupport(handle, selector);
|
||||
this._proxy.$registerTypeDefinitionSupport(handle, this._transformDocumentSelector(selector));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
@@ -952,7 +1007,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
|
||||
registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider, extensionId?: string): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new HoverAdapter(this._documents, provider));
|
||||
this._proxy.$registerHoverProvider(handle, selector);
|
||||
this._proxy.$registerHoverProvider(handle, this._transformDocumentSelector(selector));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
@@ -964,7 +1019,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
|
||||
registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new DocumentHighlightAdapter(this._documents, provider));
|
||||
this._proxy.$registerDocumentHighlightProvider(handle, selector);
|
||||
this._proxy.$registerDocumentHighlightProvider(handle, this._transformDocumentSelector(selector));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
@@ -976,7 +1031,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
|
||||
registerReferenceProvider(selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new ReferenceAdapter(this._documents, provider));
|
||||
this._proxy.$registerReferenceSupport(handle, selector);
|
||||
this._proxy.$registerReferenceSupport(handle, this._transformDocumentSelector(selector));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
@@ -986,9 +1041,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, selector);
|
||||
this._proxy.$registerQuickFixSupport(handle, this._transformDocumentSelector(selector), metadata && metadata.providedCodeActionKinds ? metadata.providedCodeActionKinds.map(kind => kind.value) : undefined);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
@@ -1001,7 +1056,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
|
||||
registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new DocumentFormattingAdapter(this._documents, provider));
|
||||
this._proxy.$registerDocumentFormattingSupport(handle, selector);
|
||||
this._proxy.$registerDocumentFormattingSupport(handle, this._transformDocumentSelector(selector));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
@@ -1011,7 +1066,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
|
||||
registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new RangeFormattingAdapter(this._documents, provider));
|
||||
this._proxy.$registerRangeFormattingSupport(handle, selector);
|
||||
this._proxy.$registerRangeFormattingSupport(handle, this._transformDocumentSelector(selector));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
@@ -1021,7 +1076,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
|
||||
registerOnTypeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, triggerCharacters: string[]): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new OnTypeFormattingAdapter(this._documents, provider));
|
||||
this._proxy.$registerOnTypeFormattingSupport(handle, selector, triggerCharacters);
|
||||
this._proxy.$registerOnTypeFormattingSupport(handle, this._transformDocumentSelector(selector), triggerCharacters);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
@@ -1051,9 +1106,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, selector, canUseProposedApi && RenameAdapter.supportsResolving(provider));
|
||||
this._proxy.$registerRenameSupport(handle, this._transformDocumentSelector(selector), RenameAdapter.supportsResolving(provider));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
@@ -1061,15 +1116,15 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
return this._withAdapter(handle, RenameAdapter, adapter => adapter.provideRenameEdits(URI.revive(resource), position, newName));
|
||||
}
|
||||
|
||||
$resolveInitialRenameValue(handle: number, resource: URI, position: IPosition): TPromise<modes.RenameInitialValue> {
|
||||
return this._withAdapter(handle, RenameAdapter, adapter => adapter.resolveInitialRenameValue(resource, position));
|
||||
$resolveRenameLocation(handle: number, resource: URI, position: IPosition): TPromise<modes.RenameLocation> {
|
||||
return this._withAdapter(handle, RenameAdapter, adapter => adapter.resolveRenameLocation(URI.revive(resource), position));
|
||||
}
|
||||
|
||||
// --- suggestion
|
||||
|
||||
registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new SuggestAdapter(this._documents, this._commands.converter, provider));
|
||||
this._proxy.$registerSuggestSupport(handle, selector, triggerCharacters, SuggestAdapter.supportsResolving(provider));
|
||||
this._proxy.$registerSuggestSupport(handle, this._transformDocumentSelector(selector), triggerCharacters, SuggestAdapter.supportsResolving(provider));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
@@ -1089,7 +1144,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
|
||||
registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, triggerCharacters: string[]): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new SignatureHelpAdapter(this._documents, provider));
|
||||
this._proxy.$registerSignatureHelpProvider(handle, selector, triggerCharacters);
|
||||
this._proxy.$registerSignatureHelpProvider(handle, this._transformDocumentSelector(selector), triggerCharacters);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
@@ -1101,7 +1156,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
|
||||
registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new LinkProviderAdapter(this._documents, this._heapService, provider));
|
||||
this._proxy.$registerDocumentLinkProvider(handle, selector);
|
||||
this._proxy.$registerDocumentLinkProvider(handle, this._transformDocumentSelector(selector));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
@@ -1115,7 +1170,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
|
||||
registerColorProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new ColorProviderAdapter(this._documents, provider));
|
||||
this._proxy.$registerDocumentColorProvider(handle, selector);
|
||||
this._proxy.$registerDocumentColorProvider(handle, this._transformDocumentSelector(selector));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
@@ -1127,14 +1182,14 @@ 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, selector);
|
||||
this._proxy.$registerFoldingRangeProvider(handle, this._transformDocumentSelector(selector));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideFoldingRanges(handle: number, resource: UriComponents): TPromise<modes.IFoldingRangeList> {
|
||||
return this._withAdapter(handle, FoldingProviderAdapter, adapter => adapter.provideFoldingRanges(URI.revive(resource)));
|
||||
$provideFoldingRanges(handle: number, resource: UriComponents, context: vscode.FoldingContext): TPromise<modes.FoldingRange[]> {
|
||||
return this._withAdapter(handle, FoldingProviderAdapter, adapter => adapter.provideFoldingRanges(URI.revive(resource), context));
|
||||
}
|
||||
|
||||
// --- configuration
|
||||
|
||||
@@ -5,15 +5,10 @@
|
||||
'use strict';
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { join } from 'vs/base/common/paths';
|
||||
import { mkdirp, dirExists } from 'vs/base/node/pfs';
|
||||
import Event from 'vs/base/common/event';
|
||||
import { LogLevel } from 'vs/workbench/api/node/extHostTypes';
|
||||
import { ILogService, DelegatedLogService } from 'vs/platform/log/common/log';
|
||||
import { createSpdLogService } from 'vs/platform/log/node/spdlogService';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
import { ExtHostLogServiceShape } from 'vs/workbench/api/node/extHost.protocol';
|
||||
|
||||
|
||||
@@ -24,9 +19,9 @@ export class ExtHostLogService extends DelegatedLogService implements ILogServic
|
||||
constructor(
|
||||
private _windowId: number,
|
||||
logLevel: LogLevel,
|
||||
private _environmentService: IEnvironmentService
|
||||
private _logsPath: string
|
||||
) {
|
||||
super(createSpdLogService(`exthost${_windowId}`, logLevel, _environmentService.logsPath));
|
||||
super(createSpdLogService(`exthost${_windowId}`, logLevel, _logsPath));
|
||||
}
|
||||
|
||||
$setLevel(level: LogLevel): void {
|
||||
@@ -42,40 +37,23 @@ export class ExtHostLogService extends DelegatedLogService implements ILogServic
|
||||
return logger;
|
||||
}
|
||||
|
||||
getLogDirectory(extensionID: string): string {
|
||||
return join(this._logsPath, `${extensionID}_${this._windowId}`);
|
||||
}
|
||||
|
||||
private createLogger(extensionID: string): ExtHostLogger {
|
||||
const logsDirPath = join(this._environmentService.logsPath, `${extensionID}_${this._windowId}`);
|
||||
const logsDirPath = this.getLogDirectory(extensionID);
|
||||
const logService = createSpdLogService(extensionID, this.getLevel(), logsDirPath);
|
||||
this._register(this.onDidChangeLogLevel(level => logService.setLevel(level)));
|
||||
return new ExtHostLogger(logService, logsDirPath);
|
||||
return new ExtHostLogger(logService);
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostLogger implements vscode.Logger {
|
||||
|
||||
constructor(
|
||||
private readonly _logService: ILogService,
|
||||
private readonly _logDirectory: string
|
||||
) {
|
||||
}
|
||||
|
||||
get onDidChangeLogLevel(): Event<LogLevel> {
|
||||
return this._logService.onDidChangeLogLevel;
|
||||
}
|
||||
|
||||
get currentLevel(): LogLevel { return this._logService.getLevel(); }
|
||||
|
||||
@memoize
|
||||
get logDirectory(): TPromise<string> {
|
||||
return dirExists(this._logDirectory).then(exists => {
|
||||
if (exists) {
|
||||
return TPromise.wrap(null);
|
||||
} else {
|
||||
return mkdirp(this._logDirectory);
|
||||
}
|
||||
}).then(() => {
|
||||
return this._logDirectory;
|
||||
});
|
||||
}
|
||||
private readonly _logService: ILogService
|
||||
) { }
|
||||
|
||||
trace(message: string, ...args: any[]): void {
|
||||
return this._logService.trace(message, ...args);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
'use strict';
|
||||
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import vscode = require('vscode');
|
||||
import * as vscode from 'vscode';
|
||||
import { MainContext, MainThreadMessageServiceShape, MainThreadMessageOptions, IMainContext } from './extHost.protocol';
|
||||
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
|
||||
|
||||
|
||||
@@ -4,16 +4,20 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { Progress, ProgressOptions, CancellationToken } from 'vscode';
|
||||
import { MainThreadProgressShape } from './extHost.protocol';
|
||||
import { ProgressOptions } from 'vscode';
|
||||
import { MainThreadProgressShape, ExtHostProgressShape } from './extHost.protocol';
|
||||
import { ProgressLocation } from './extHostTypeConverters';
|
||||
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IProgressStep } from 'vs/platform/progress/common/progress';
|
||||
import { IProgressStep, Progress } from 'vs/platform/progress/common/progress';
|
||||
import { localize } from 'vs/nls';
|
||||
import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { debounce } from 'vs/base/common/decorators';
|
||||
|
||||
export class ExtHostProgress {
|
||||
export class ExtHostProgress implements ExtHostProgressShape {
|
||||
|
||||
private _proxy: MainThreadProgressShape;
|
||||
private _handles: number = 0;
|
||||
private _mapHandleToCancellationSource: Map<number, CancellationTokenSource> = new Map();
|
||||
|
||||
constructor(proxy: MainThreadProgressShape) {
|
||||
this._proxy = proxy;
|
||||
@@ -21,30 +25,66 @@ export class ExtHostProgress {
|
||||
|
||||
withProgress<R>(extension: IExtensionDescription, options: ProgressOptions, task: (progress: Progress<IProgressStep>, token: CancellationToken) => Thenable<R>): Thenable<R> {
|
||||
const handle = this._handles++;
|
||||
const { title, location } = options;
|
||||
this._proxy.$startProgress(handle, { location: ProgressLocation.from(location), title, tooltip: extension.name });
|
||||
return this._withProgress(handle, task);
|
||||
const { title, location, cancellable } = options;
|
||||
const source = localize('extensionSource', "{0} (Extension)", extension.displayName || extension.name);
|
||||
this._proxy.$startProgress(handle, { location: ProgressLocation.from(location), title, source, cancellable });
|
||||
return this._withProgress(handle, task, cancellable);
|
||||
}
|
||||
|
||||
private _withProgress<R>(handle: number, task: (progress: Progress<IProgressStep>, token: CancellationToken) => Thenable<R>): Thenable<R> {
|
||||
private _withProgress<R>(handle: number, task: (progress: Progress<IProgressStep>, token: CancellationToken) => Thenable<R>, cancellable: boolean): Thenable<R> {
|
||||
let source: CancellationTokenSource;
|
||||
if (cancellable) {
|
||||
source = new CancellationTokenSource();
|
||||
this._mapHandleToCancellationSource.set(handle, source);
|
||||
}
|
||||
|
||||
const progress = {
|
||||
report: (p: IProgressStep) => {
|
||||
this._proxy.$progressReport(handle, p);
|
||||
const progressEnd = (handle: number): void => {
|
||||
this._proxy.$progressEnd(handle);
|
||||
this._mapHandleToCancellationSource.delete(handle);
|
||||
if (source) {
|
||||
source.dispose();
|
||||
}
|
||||
};
|
||||
|
||||
let p: Thenable<R>;
|
||||
|
||||
try {
|
||||
p = task(progress, null);
|
||||
p = task(new ProgressCallback(this._proxy, handle), cancellable ? source.token : CancellationToken.None);
|
||||
} catch (err) {
|
||||
this._proxy.$progressEnd(handle);
|
||||
progressEnd(handle);
|
||||
throw err;
|
||||
}
|
||||
|
||||
p.then(result => this._proxy.$progressEnd(handle), err => this._proxy.$progressEnd(handle));
|
||||
p.then(result => progressEnd(handle), err => progressEnd(handle));
|
||||
return p;
|
||||
}
|
||||
|
||||
public $acceptProgressCanceled(handle: number): void {
|
||||
const source = this._mapHandleToCancellationSource.get(handle);
|
||||
if (source) {
|
||||
source.cancel();
|
||||
this._mapHandleToCancellationSource.delete(handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mergeProgress(result: IProgressStep, currentValue: IProgressStep): IProgressStep {
|
||||
result.message = currentValue.message;
|
||||
if (typeof currentValue.increment === 'number' && typeof result.message === 'number') {
|
||||
result.increment += currentValue.increment;
|
||||
} else if (typeof currentValue.increment === 'number') {
|
||||
result.increment = currentValue.increment;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
class ProgressCallback extends Progress<IProgressStep> {
|
||||
constructor(private _proxy: MainThreadProgressShape, private _handle: number) {
|
||||
super(p => this.throttledReport(p));
|
||||
}
|
||||
|
||||
@debounce(100, (result: IProgressStep, currentValue: IProgressStep) => mergeProgress(result, currentValue), () => Object.create(null))
|
||||
throttledReport(p: IProgressStep): void {
|
||||
this._proxy.$progressReport(this._handle, p);
|
||||
}
|
||||
}
|
||||
@@ -29,9 +29,10 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
|
||||
this._commands = commands;
|
||||
}
|
||||
|
||||
showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Thenable<QuickPickItem[]>, options: QuickPickOptions & { canSelectMany: true; }, token?: CancellationToken): Thenable<QuickPickItem[] | undefined>;
|
||||
showQuickPick(itemsOrItemsPromise: string[] | Thenable<string[]>, options?: QuickPickOptions, token?: CancellationToken): Thenable<string | undefined>;
|
||||
showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Thenable<QuickPickItem[]>, options?: QuickPickOptions, token?: CancellationToken): Thenable<QuickPickItem | undefined>;
|
||||
showQuickPick(itemsOrItemsPromise: Item[] | Thenable<Item[]>, options?: QuickPickOptions, token: CancellationToken = CancellationToken.None): Thenable<Item | undefined> {
|
||||
showQuickPick(itemsOrItemsPromise: Item[] | Thenable<Item[]>, options?: QuickPickOptions, token: CancellationToken = CancellationToken.None): Thenable<Item | Item[] | undefined> {
|
||||
|
||||
// clear state from last invocation
|
||||
this._onDidSelectItem = undefined;
|
||||
@@ -43,7 +44,8 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
|
||||
placeHolder: options && options.placeHolder,
|
||||
matchOnDescription: options && options.matchOnDescription,
|
||||
matchOnDetail: options && options.matchOnDetail,
|
||||
ignoreFocusLost: options && options.ignoreFocusOut
|
||||
ignoreFocusLost: options && options.ignoreFocusOut,
|
||||
canSelectMany: options && options.canPickMany
|
||||
});
|
||||
|
||||
const promise = TPromise.any(<TPromise<number | Item[]>[]>[quickPickWidget, itemsPromise]).then(values => {
|
||||
@@ -60,6 +62,7 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
|
||||
let label: string;
|
||||
let description: string;
|
||||
let detail: string;
|
||||
let picked: boolean;
|
||||
|
||||
if (typeof item === 'string') {
|
||||
label = item;
|
||||
@@ -67,12 +70,14 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
|
||||
label = item.label;
|
||||
description = item.description;
|
||||
detail = item.detail;
|
||||
picked = item.picked;
|
||||
}
|
||||
pickItems.push({
|
||||
label,
|
||||
description,
|
||||
handle,
|
||||
detail
|
||||
detail,
|
||||
picked
|
||||
});
|
||||
}
|
||||
|
||||
@@ -89,6 +94,8 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
|
||||
return quickPickWidget.then(handle => {
|
||||
if (typeof handle === 'number') {
|
||||
return items[handle];
|
||||
} else if (Array.isArray(handle)) {
|
||||
return handle.map(h => items[h]);
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
@@ -98,7 +105,7 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
|
||||
return TPromise.wrapError(err);
|
||||
});
|
||||
});
|
||||
return wireCancellationToken<Item>(token, promise, true);
|
||||
return wireCancellationToken<Item | Item[]>(token, promise, true);
|
||||
}
|
||||
|
||||
$onItemSelected(handle: number): void {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import URI, { UriComponents } from 'vs/base/common/uri';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import Event, { Emitter, once } from 'vs/base/common/event';
|
||||
import { Event, Emitter, once } from 'vs/base/common/event';
|
||||
import { debounce } from 'vs/base/common/decorators';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { asWinJsPromise } from 'vs/base/common/async';
|
||||
|
||||
64
src/vs/workbench/api/node/extHostSearch.ts
Normal file
64
src/vs/workbench/api/node/extHostSearch.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. 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));
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,12 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import URI from 'vs/base/common/uri';
|
||||
import URI, { UriComponents } from 'vs/base/common/uri';
|
||||
import * as nls from 'vs/nls';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import * as Objects from 'vs/base/common/objects';
|
||||
import { asWinJsPromise } from 'vs/base/common/async';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
|
||||
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import * as TaskSystem from 'vs/workbench/parts/tasks/common/tasks';
|
||||
@@ -18,7 +19,12 @@ import { MainContext, MainThreadTaskShape, ExtHostTaskShape, IMainContext } from
|
||||
import * as types from 'vs/workbench/api/node/extHostTypes';
|
||||
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
|
||||
import * as vscode from 'vscode';
|
||||
import {
|
||||
TaskDefinitionDTO, TaskExecutionDTO, TaskPresentationOptionsDTO, ProcessExecutionOptionsDTO, ProcessExecutionDTO,
|
||||
ShellExecutionOptionsDTO, ShellExecutionDTO, TaskDTO, TaskHandleDTO, TaskFilterDTO
|
||||
} from '../shared/tasks';
|
||||
|
||||
export { TaskExecutionDTO };
|
||||
|
||||
/*
|
||||
namespace ProblemPattern {
|
||||
@@ -278,20 +284,43 @@ namespace CommandOptions {
|
||||
}
|
||||
}
|
||||
|
||||
namespace ShellQuoteOptions {
|
||||
export function from(value: vscode.ShellQuotingOptions): TaskSystem.ShellQuotingOptions {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
escape: value.escape,
|
||||
strong: value.strong,
|
||||
weak: value.strong
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace ShellConfiguration {
|
||||
export function from(value: { executable?: string, shellArgs?: string[] }): TaskSystem.ShellConfiguration {
|
||||
export function from(value: { executable?: string, shellArgs?: string[], quotes?: vscode.ShellQuotingOptions }): TaskSystem.ShellConfiguration {
|
||||
if (value === void 0 || value === null || !value.executable) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let result: TaskSystem.ShellConfiguration = {
|
||||
executable: value.executable,
|
||||
args: Strings.from(value.shellArgs)
|
||||
args: Strings.from(value.shellArgs),
|
||||
quoting: ShellQuoteOptions.from(value.quotes)
|
||||
};
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ShellString {
|
||||
export function from(value: (string | vscode.ShellQuotedString)[]): TaskSystem.CommandString[] {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return value.slice(0);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Tasks {
|
||||
|
||||
export function from(tasks: vscode.Task[], rootFolder: vscode.WorkspaceFolder, extension: IExtensionDescription): TaskSystem.ContributedTask[] {
|
||||
@@ -396,19 +425,292 @@ namespace Tasks {
|
||||
}
|
||||
|
||||
function getShellCommand(value: vscode.ShellExecution): TaskSystem.CommandConfiguration {
|
||||
if (typeof value.commandLine !== 'string') {
|
||||
if (value.args) {
|
||||
if (typeof value.command !== 'string' && typeof value.command.value !== 'string') {
|
||||
return undefined;
|
||||
}
|
||||
let result: TaskSystem.CommandConfiguration = {
|
||||
name: value.command,
|
||||
args: ShellString.from(value.args),
|
||||
runtime: TaskSystem.RuntimeType.Shell,
|
||||
presentation: undefined
|
||||
};
|
||||
if (value.options) {
|
||||
result.options = CommandOptions.from(value.options);
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
if (typeof value.commandLine !== 'string') {
|
||||
return undefined;
|
||||
}
|
||||
let result: TaskSystem.CommandConfiguration = {
|
||||
name: value.commandLine,
|
||||
runtime: TaskSystem.RuntimeType.Shell,
|
||||
presentation: undefined
|
||||
};
|
||||
if (value.options) {
|
||||
result.options = CommandOptions.from(value.options);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace TaskDefinitionDTO {
|
||||
export function from(value: vscode.TaskDefinition): TaskDefinitionDTO {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
let result: TaskSystem.CommandConfiguration = {
|
||||
name: value.commandLine,
|
||||
runtime: TaskSystem.RuntimeType.Shell,
|
||||
presentation: undefined
|
||||
return value;
|
||||
}
|
||||
export function to(value: TaskDefinitionDTO): vscode.TaskDefinition {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
namespace TaskPresentationOptionsDTO {
|
||||
export function from(value: vscode.TaskPresentationOptions): TaskPresentationOptionsDTO {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
export function to(value: TaskPresentationOptionsDTO): vscode.TaskPresentationOptions {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ProcessExecutionOptionsDTO {
|
||||
export function from(value: vscode.ProcessExecutionOptions): ProcessExecutionOptionsDTO {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
export function to(value: ProcessExecutionOptionsDTO): vscode.ProcessExecutionOptions {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ProcessExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO): value is ProcessExecutionDTO {
|
||||
let candidate = value as ProcessExecutionDTO;
|
||||
return candidate && !!candidate.process;
|
||||
}
|
||||
export function from(value: vscode.ProcessExecution): ProcessExecutionDTO {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
let result: ProcessExecutionDTO = {
|
||||
process: value.process,
|
||||
args: value.args
|
||||
};
|
||||
if (value.options) {
|
||||
result.options = CommandOptions.from(value.options);
|
||||
result.options = ProcessExecutionOptionsDTO.from(value.options);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
export function to(value: ProcessExecutionDTO): types.ProcessExecution {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return new types.ProcessExecution(value.process, value.args, value.options);
|
||||
}
|
||||
}
|
||||
|
||||
namespace ShellExecutionOptionsDTO {
|
||||
export function from(value: vscode.ShellExecutionOptions): ShellExecutionOptionsDTO {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
export function to(value: ShellExecutionOptionsDTO): vscode.ShellExecutionOptions {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
namespace ShellExecutionDTO {
|
||||
export function is(value: ShellExecutionDTO | ProcessExecutionDTO): value is ShellExecutionDTO {
|
||||
let candidate = value as ShellExecutionDTO;
|
||||
return candidate && (!!candidate.commandLine || !!candidate.command);
|
||||
}
|
||||
export function from(value: vscode.ShellExecution): ShellExecutionDTO {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
let result: ShellExecutionDTO = {
|
||||
};
|
||||
if (value.commandLine !== void 0) {
|
||||
result.commandLine = value.commandLine;
|
||||
} else {
|
||||
result.command = value.command;
|
||||
result.args = value.args;
|
||||
}
|
||||
if (value.options) {
|
||||
result.options = ShellExecutionOptionsDTO.from(value.options);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
export function to(value: ShellExecutionDTO): types.ShellExecution {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
if (value.commandLine) {
|
||||
return new types.ShellExecution(value.commandLine, value.options);
|
||||
} else {
|
||||
return new types.ShellExecution(value.command, value.args ? value.args : [], value.options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace TaskHandleDTO {
|
||||
export function from(value: types.Task): TaskHandleDTO {
|
||||
let folder: UriComponents;
|
||||
if (value.scope !== void 0 && typeof value.scope !== 'number') {
|
||||
folder = value.scope.uri;
|
||||
}
|
||||
return {
|
||||
id: value._id,
|
||||
workspaceFolder: folder
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
namespace TaskDTO {
|
||||
|
||||
export function from(value: vscode.Task, extension: IExtensionDescription): TaskDTO {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
let execution: ShellExecutionDTO | ProcessExecutionDTO;
|
||||
if (value.execution instanceof types.ProcessExecution) {
|
||||
execution = ProcessExecutionDTO.from(value.execution);
|
||||
} else if (value.execution instanceof types.ShellExecution) {
|
||||
execution = ShellExecutionDTO.from(value.execution);
|
||||
}
|
||||
let definition: TaskDefinitionDTO = TaskDefinitionDTO.from(value.definition);
|
||||
let scope: number | UriComponents;
|
||||
if (value.scope) {
|
||||
if (typeof value.scope === 'number') {
|
||||
scope = value.scope;
|
||||
} else {
|
||||
scope = value.scope.uri.toJSON();
|
||||
}
|
||||
}
|
||||
if (!definition || !scope) {
|
||||
return undefined;
|
||||
}
|
||||
let group = (value.group as types.TaskGroup) ? (value.group as types.TaskGroup).id : undefined;
|
||||
let result: TaskDTO = {
|
||||
_id: (value as types.Task)._id,
|
||||
definition,
|
||||
name: value.name,
|
||||
source: {
|
||||
extensionId: extension.id,
|
||||
label: value.source,
|
||||
scope: scope
|
||||
},
|
||||
execution,
|
||||
isBackground: value.isBackground,
|
||||
group: group,
|
||||
presentationOptions: TaskPresentationOptionsDTO.from(value.presentationOptions),
|
||||
problemMatchers: value.problemMatchers,
|
||||
hasDefinedMatchers: (value as types.Task).hasDefinedMatchers
|
||||
};
|
||||
return result;
|
||||
}
|
||||
export function to(value: TaskDTO, workspace: ExtHostWorkspace): types.Task {
|
||||
if (value === void 0 || value === null) {
|
||||
return undefined;
|
||||
}
|
||||
let execution: types.ShellExecution | types.ProcessExecution;
|
||||
if (ProcessExecutionDTO.is(value.execution)) {
|
||||
execution = ProcessExecutionDTO.to(value.execution);
|
||||
} else if (ShellExecutionDTO.is(value.execution)) {
|
||||
execution = ShellExecutionDTO.to(value.execution);
|
||||
}
|
||||
let definition: vscode.TaskDefinition = TaskDefinitionDTO.to(value.definition);
|
||||
let scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder;
|
||||
if (value.source) {
|
||||
if (value.source.scope !== void 0) {
|
||||
if (typeof value.source.scope === 'number') {
|
||||
scope = value.source.scope;
|
||||
} else {
|
||||
scope = workspace.resolveWorkspaceFolder(URI.revive(value.source.scope));
|
||||
}
|
||||
} else {
|
||||
scope = types.TaskScope.Workspace;
|
||||
}
|
||||
}
|
||||
if (!definition || !scope) {
|
||||
return undefined;
|
||||
}
|
||||
let result = new types.Task(definition, scope, value.name, value.source.label, execution, value.problemMatchers);
|
||||
if (value.isBackground !== void 0) {
|
||||
result.isBackground = value.isBackground;
|
||||
}
|
||||
if (value.group !== void 0) {
|
||||
result.group = types.TaskGroup.from(value.group);
|
||||
}
|
||||
if (value.presentationOptions) {
|
||||
result.presentationOptions = TaskPresentationOptionsDTO.to(value.presentationOptions);
|
||||
}
|
||||
if (value._id) {
|
||||
result._id = value._id;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
}
|
||||
|
||||
get task(): vscode.Task {
|
||||
return this._task;
|
||||
}
|
||||
|
||||
public terminate(): void {
|
||||
this._tasks.terminateTask(this);
|
||||
}
|
||||
}
|
||||
|
||||
namespace TaskExecutionDTO {
|
||||
export function to(value: TaskExecutionDTO, tasks: ExtHostTask): vscode.TaskExecution {
|
||||
return new TaskExecutionImpl(value.id, TaskDTO.to(value.task, tasks.extHostWorkspace), tasks);
|
||||
}
|
||||
export function from(value: vscode.TaskExecution): TaskExecutionDTO {
|
||||
return {
|
||||
id: (value as TaskExecutionImpl)._id,
|
||||
task: undefined
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
interface HandlerData {
|
||||
@@ -422,12 +724,21 @@ 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>();
|
||||
|
||||
constructor(mainContext: IMainContext, extHostWorkspace: ExtHostWorkspace) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadTask);
|
||||
this._extHostWorkspace = extHostWorkspace;
|
||||
this._handleCounter = 0;
|
||||
this._handlers = new Map<number, HandlerData>();
|
||||
this._taskExecutions = new Map<string, TaskExecutionImpl>();
|
||||
}
|
||||
|
||||
public get extHostWorkspace(): ExtHostWorkspace {
|
||||
return this._extHostWorkspace;
|
||||
}
|
||||
|
||||
public registerTaskProvider(extension: IExtensionDescription, provider: vscode.TaskProvider): vscode.Disposable {
|
||||
@@ -443,6 +754,69 @@ export class ExtHostTask implements ExtHostTaskShape {
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
if (task) {
|
||||
result.push(task);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
public executeTask(extension: IExtensionDescription, task: vscode.Task): Thenable<vscode.TaskExecution> {
|
||||
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 => this.getTaskExecution(value, task));
|
||||
} else {
|
||||
let dto = TaskDTO.from(task, extension);
|
||||
if (dto === void 0) {
|
||||
// {{ SQL CARBON EDIT }} - Add type assertion to fix build break
|
||||
return Promise.reject<vscode.TaskExecution>(new Error('Task is not valid'));
|
||||
}
|
||||
return this._proxy.$executeTask(dto).then(value => this.getTaskExecution(value, task));
|
||||
}
|
||||
}
|
||||
|
||||
public $taskStarted(execution: TaskExecutionDTO): void {
|
||||
this._onDidExecuteTask.fire({
|
||||
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;
|
||||
}
|
||||
|
||||
public terminateTask(execution: vscode.TaskExecution): TPromise<void> {
|
||||
if (!(execution instanceof TaskExecutionImpl)) {
|
||||
throw new Error('No valid task execution provided');
|
||||
}
|
||||
return this._proxy.$terminateTask((execution as TaskExecutionImpl)._id);
|
||||
}
|
||||
|
||||
public $taskEnded(execution: TaskExecutionDTO): void {
|
||||
const _execution = this.getTaskExecution(execution);
|
||||
this._taskExecutions.delete(execution.id);
|
||||
this._onDidTerminateTask.fire({
|
||||
execution: _execution
|
||||
});
|
||||
}
|
||||
|
||||
get onDidEndTask(): Event<vscode.TaskEndEvent> {
|
||||
return this._onDidTerminateTask.event;
|
||||
}
|
||||
|
||||
public $provideTasks(handle: number): TPromise<TaskSystem.TaskSet> {
|
||||
let handler = this._handlers.get(handle);
|
||||
if (!handler) {
|
||||
@@ -460,4 +834,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,19 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import vscode = require('vscode');
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IMainContext } from './extHost.protocol';
|
||||
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, 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 _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[];
|
||||
|
||||
|
||||
@@ -313,8 +313,6 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
|
||||
|
||||
export class ExtHostTextEditor implements vscode.TextEditor {
|
||||
|
||||
public readonly editorType = 'texteditor';
|
||||
|
||||
private readonly _proxy: MainThreadTextEditorsShape;
|
||||
private readonly _id: string;
|
||||
private readonly _documentData: ExtHostDocumentData;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { toThenable } from 'vs/base/common/async';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { TextEditorSelectionChangeKind } from './extHostTypes';
|
||||
|
||||
@@ -38,14 +38,22 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
|
||||
});
|
||||
}
|
||||
|
||||
registerTreeDataProvider<T>(id: string, dataProvider: vscode.TreeDataProvider<T>, proposedApiFunction: <U>(fn: U) => U): vscode.TreeView<T> {
|
||||
const treeView = this.createExtHostTreeViewer(id, dataProvider);
|
||||
registerTreeDataProvider<T>(id: string, treeDataProvider: vscode.TreeDataProvider<T>): vscode.Disposable {
|
||||
const treeView = this.createTreeView(id, { treeDataProvider });
|
||||
return { dispose: () => treeView.dispose() };
|
||||
}
|
||||
|
||||
createTreeView<T>(viewId: string, options: { treeDataProvider: vscode.TreeDataProvider<T> }): vscode.TreeView<T> {
|
||||
if (!options || !options.treeDataProvider) {
|
||||
throw new Error('Options with treeDataProvider is mandatory');
|
||||
}
|
||||
const treeView = this.createExtHostTreeViewer(viewId, options.treeDataProvider);
|
||||
return {
|
||||
reveal: proposedApiFunction((element: T, options?: { select?: boolean }): Thenable<void> => {
|
||||
reveal: (element: T, options?: { select?: boolean }): Thenable<void> => {
|
||||
return treeView.reveal(element, options);
|
||||
}),
|
||||
},
|
||||
dispose: () => {
|
||||
this.treeViews.delete(id);
|
||||
this.treeViews.delete(viewId);
|
||||
treeView.dispose();
|
||||
}
|
||||
};
|
||||
@@ -144,7 +152,7 @@ class ExtHostTreeView<T> extends Disposable {
|
||||
|
||||
private resolveTreeNode(element: T, parent?: TreeNode): TPromise<TreeNode> {
|
||||
return asWinJsPromise(() => this.dataProvider.getTreeItem(element))
|
||||
.then(extTreeItem => this.createHandle(element, extTreeItem, parent))
|
||||
.then(extTreeItem => this.createHandle(element, extTreeItem, parent, true))
|
||||
.then(handle => this.getChildren(parent ? parent.item.handle : null)
|
||||
.then(() => {
|
||||
const cachedElement = this.getExtensionElement(handle);
|
||||
@@ -295,7 +303,7 @@ class ExtHostTreeView<T> extends Disposable {
|
||||
return item;
|
||||
}
|
||||
|
||||
private createHandle(element: T, { id, label, resourceUri }: vscode.TreeItem, parent?: TreeNode): TreeItemHandle {
|
||||
private createHandle(element: T, { id, label, resourceUri }: vscode.TreeItem, parent: TreeNode, first?: boolean): TreeItemHandle {
|
||||
if (id) {
|
||||
return `${ExtHostTreeView.ID_HANDLE_PREFIX}/${id}`;
|
||||
}
|
||||
@@ -308,7 +316,7 @@ class ExtHostTreeView<T> extends Disposable {
|
||||
|
||||
for (let counter = 0; counter <= childrenNodes.length; counter++) {
|
||||
const handle = `${prefix}/${counter}:${elementId}`;
|
||||
if (!this.elements.has(handle) || existingHandle === handle) {
|
||||
if (first || !this.elements.has(handle) || existingHandle === handle) {
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import * as types from './extHostTypes';
|
||||
import { Position as EditorPosition, ITextEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
@@ -21,6 +20,7 @@ import * as htmlContent from 'vs/base/common/htmlContent';
|
||||
import { IRelativePattern } from 'vs/base/common/glob';
|
||||
import { LanguageSelector, LanguageFilter } from 'vs/editor/common/modes/languageSelector';
|
||||
import { WorkspaceEditDto, ResourceTextEditDto } from 'vs/workbench/api/node/extHost.protocol';
|
||||
import { MarkerSeverity, IRelatedInformation, IMarkerData } from 'vs/platform/markers/common/markers';
|
||||
|
||||
export interface PositionLike {
|
||||
line: number;
|
||||
@@ -83,34 +83,58 @@ export function fromPosition(position: types.Position): IPosition {
|
||||
return { lineNumber: position.line + 1, column: position.character + 1 };
|
||||
}
|
||||
|
||||
export function fromDiagnosticSeverity(value: number): Severity {
|
||||
switch (value) {
|
||||
case types.DiagnosticSeverity.Error:
|
||||
return Severity.Error;
|
||||
case types.DiagnosticSeverity.Warning:
|
||||
return Severity.Warning;
|
||||
case types.DiagnosticSeverity.Information:
|
||||
return Severity.Info;
|
||||
case types.DiagnosticSeverity.Hint:
|
||||
return Severity.Ignore;
|
||||
}
|
||||
return Severity.Error;
|
||||
export function fromDiagnostic(value: vscode.Diagnostic): IMarkerData {
|
||||
return {
|
||||
...fromRange(value.range),
|
||||
message: value.message,
|
||||
source: value.source,
|
||||
code: String(value.code),
|
||||
severity: fromDiagnosticSeverity(value.severity),
|
||||
relatedInformation: value.relatedInformation && value.relatedInformation.map(fromDiagnosticRelatedInformation)
|
||||
};
|
||||
}
|
||||
|
||||
export function toDiagnosticSeverty(value: Severity): types.DiagnosticSeverity {
|
||||
export function fromDiagnosticRelatedInformation(value: types.DiagnosticRelatedInformation): IRelatedInformation {
|
||||
return {
|
||||
...fromRange(value.location.range),
|
||||
message: value.message,
|
||||
resource: value.location.uri
|
||||
};
|
||||
}
|
||||
|
||||
export function toDiagnosticRelatedInformation(value: IRelatedInformation): types.DiagnosticRelatedInformation {
|
||||
return new types.DiagnosticRelatedInformation(new types.Location(value.resource, toRange(value)), value.message);
|
||||
}
|
||||
|
||||
export function fromDiagnosticSeverity(value: number): MarkerSeverity {
|
||||
switch (value) {
|
||||
case Severity.Info:
|
||||
case types.DiagnosticSeverity.Error:
|
||||
return MarkerSeverity.Error;
|
||||
case types.DiagnosticSeverity.Warning:
|
||||
return MarkerSeverity.Warning;
|
||||
case types.DiagnosticSeverity.Information:
|
||||
return MarkerSeverity.Info;
|
||||
case types.DiagnosticSeverity.Hint:
|
||||
return MarkerSeverity.Hint;
|
||||
}
|
||||
return MarkerSeverity.Error;
|
||||
}
|
||||
|
||||
export function toDiagnosticSeverty(value: MarkerSeverity): types.DiagnosticSeverity {
|
||||
switch (value) {
|
||||
case MarkerSeverity.Info:
|
||||
return types.DiagnosticSeverity.Information;
|
||||
case Severity.Warning:
|
||||
case MarkerSeverity.Warning:
|
||||
return types.DiagnosticSeverity.Warning;
|
||||
case Severity.Error:
|
||||
case MarkerSeverity.Error:
|
||||
return types.DiagnosticSeverity.Error;
|
||||
case Severity.Ignore:
|
||||
case MarkerSeverity.Hint:
|
||||
return types.DiagnosticSeverity.Hint;
|
||||
}
|
||||
return types.DiagnosticSeverity.Error;
|
||||
}
|
||||
|
||||
|
||||
export function fromViewColumn(column?: vscode.ViewColumn): EditorPosition {
|
||||
let editorColumn = EditorPosition.ONE;
|
||||
if (typeof column !== 'number') {
|
||||
@@ -220,7 +244,7 @@ export const TextEdit = {
|
||||
range: fromRange(edit.range)
|
||||
};
|
||||
},
|
||||
to(edit: modes.TextEdit): vscode.TextEdit {
|
||||
to(edit: modes.TextEdit): types.TextEdit {
|
||||
let result = new types.TextEdit(toRange(edit.range), edit.text);
|
||||
result.newEol = EndOfLine.to(edit.eol);
|
||||
return result;
|
||||
@@ -522,12 +546,15 @@ export namespace DocumentLink {
|
||||
}
|
||||
|
||||
export namespace ColorPresentation {
|
||||
export function to(colorPresentation: modes.IColorPresentation): vscode.ColorPresentation {
|
||||
return {
|
||||
label: colorPresentation.label,
|
||||
textEdit: colorPresentation.textEdit ? TextEdit.to(colorPresentation.textEdit) : undefined,
|
||||
additionalTextEdits: colorPresentation.additionalTextEdits ? colorPresentation.additionalTextEdits.map(value => TextEdit.to(value)) : undefined
|
||||
};
|
||||
export function to(colorPresentation: modes.IColorPresentation): types.ColorPresentation {
|
||||
let cp = new types.ColorPresentation(colorPresentation.label);
|
||||
if (colorPresentation.textEdit) {
|
||||
cp.textEdit = TextEdit.to(colorPresentation.textEdit);
|
||||
}
|
||||
if (colorPresentation.additionalTextEdits) {
|
||||
cp.additionalTextEdits = colorPresentation.additionalTextEdits.map(value => TextEdit.to(value));
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
|
||||
export function from(colorPresentation: vscode.ColorPresentation): modes.IColorPresentation {
|
||||
@@ -539,6 +566,15 @@ export namespace ColorPresentation {
|
||||
}
|
||||
}
|
||||
|
||||
export namespace Color {
|
||||
export function to(c: [number, number, number, number]): types.Color {
|
||||
return new types.Color(c[0], c[1], c[2], c[3]);
|
||||
}
|
||||
export function from(color: types.Color): [number, number, number, number] {
|
||||
return [color.red, color.green, color.blue, color.alpha];
|
||||
}
|
||||
}
|
||||
|
||||
export namespace TextDocumentSaveReason {
|
||||
|
||||
export function to(reason: SaveReason): vscode.TextDocumentSaveReason {
|
||||
@@ -581,16 +617,35 @@ export namespace ProgressLocation {
|
||||
switch (loc) {
|
||||
case types.ProgressLocation.SourceControl: return MainProgressLocation.Scm;
|
||||
case types.ProgressLocation.Window: return MainProgressLocation.Window;
|
||||
case types.ProgressLocation.Notification: return MainProgressLocation.Notification;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
let range: modes.FoldingRange = { start: r.start + 1, end: r.end + 1 };
|
||||
if (r.kind) {
|
||||
range.kind = FoldingRangeKind.from(r.kind);
|
||||
}
|
||||
return range;
|
||||
}
|
||||
}
|
||||
|
||||
export namespace FoldingRangeKind {
|
||||
export function from(kind: vscode.FoldingRangeKind | undefined): modes.FoldingRangeKind | undefined {
|
||||
if (kind) {
|
||||
switch (kind) {
|
||||
case types.FoldingRangeKind.Comment:
|
||||
return modes.FoldingRangeKind.Comment;
|
||||
case types.FoldingRangeKind.Imports:
|
||||
return modes.FoldingRangeKind.Imports;
|
||||
case types.FoldingRangeKind.Region:
|
||||
return modes.FoldingRangeKind.Region;
|
||||
}
|
||||
}
|
||||
return void 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -641,7 +696,8 @@ function doToLanguageSelector(selector: string | vscode.DocumentFilter): string
|
||||
return {
|
||||
language: selector.language,
|
||||
scheme: selector.scheme,
|
||||
pattern: toGlobPattern(selector.pattern)
|
||||
pattern: toGlobPattern(selector.pattern),
|
||||
exclusive: selector.exclusive
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -718,6 +718,27 @@ export class Location {
|
||||
}
|
||||
}
|
||||
|
||||
export class DiagnosticRelatedInformation {
|
||||
|
||||
static is(thing: any): thing is DiagnosticRelatedInformation {
|
||||
if (!thing) {
|
||||
return false;
|
||||
}
|
||||
return typeof (<DiagnosticRelatedInformation>thing).message === 'string'
|
||||
&& (<DiagnosticRelatedInformation>thing).location
|
||||
&& Range.isRange((<DiagnosticRelatedInformation>thing).location.range)
|
||||
&& URI.isUri((<DiagnosticRelatedInformation>thing).location.uri);
|
||||
}
|
||||
|
||||
location: Location;
|
||||
message: string;
|
||||
|
||||
constructor(location: Location, message: string) {
|
||||
this.location = location;
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
|
||||
export class Diagnostic {
|
||||
|
||||
range: Range;
|
||||
@@ -725,6 +746,7 @@ export class Diagnostic {
|
||||
source: string;
|
||||
code: string | number;
|
||||
severity: DiagnosticSeverity;
|
||||
relatedInformation: DiagnosticRelatedInformation[];
|
||||
|
||||
constructor(range: Range, message: string, severity: DiagnosticSeverity = DiagnosticSeverity.Error) {
|
||||
this.range = range;
|
||||
@@ -854,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;
|
||||
|
||||
@@ -881,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
|
||||
@@ -1235,6 +1291,21 @@ export class TaskGroup implements vscode.TaskGroup {
|
||||
|
||||
public static Test: TaskGroup = new TaskGroup('test', 'Test');
|
||||
|
||||
public static from(value: string) {
|
||||
switch (value) {
|
||||
case 'clean':
|
||||
return TaskGroup.Clean;
|
||||
case 'build':
|
||||
return TaskGroup.Build;
|
||||
case 'rebuild':
|
||||
return TaskGroup.Rebuild;
|
||||
case 'test':
|
||||
return TaskGroup.Test;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
constructor(id: string, _label: string) {
|
||||
if (typeof id !== 'string') {
|
||||
throw illegalArgument('name');
|
||||
@@ -1306,19 +1377,49 @@ export class ProcessExecution implements vscode.ProcessExecution {
|
||||
set options(value: vscode.ProcessExecutionOptions) {
|
||||
this._options = value;
|
||||
}
|
||||
|
||||
public computeId(): string {
|
||||
const hash = crypto.createHash('md5');
|
||||
hash.update('process');
|
||||
if (this._process !== void 0) {
|
||||
hash.update(this._process);
|
||||
}
|
||||
if (this._args && this._args.length > 0) {
|
||||
for (let arg of this._args) {
|
||||
hash.update(arg);
|
||||
}
|
||||
}
|
||||
return hash.digest('hex');
|
||||
}
|
||||
}
|
||||
|
||||
export class ShellExecution implements vscode.ShellExecution {
|
||||
|
||||
private _commandLine: string;
|
||||
private _command: string | vscode.ShellQuotedString;
|
||||
private _args: (string | vscode.ShellQuotedString)[];
|
||||
private _options: vscode.ShellExecutionOptions;
|
||||
|
||||
constructor(commandLine: string, options?: vscode.ShellExecutionOptions) {
|
||||
if (typeof commandLine !== 'string') {
|
||||
throw illegalArgument('commandLine');
|
||||
constructor(commandLine: string, options?: vscode.ShellExecutionOptions);
|
||||
constructor(command: string | vscode.ShellQuotedString, args: (string | vscode.ShellQuotedString)[], options?: vscode.ShellExecutionOptions);
|
||||
constructor(arg0: string | vscode.ShellQuotedString, arg1?: vscode.ShellExecutionOptions | (string | vscode.ShellQuotedString)[], arg2?: vscode.ShellExecutionOptions) {
|
||||
if (Array.isArray(arg1)) {
|
||||
if (!arg0) {
|
||||
throw illegalArgument('command can\'t be undefined or null');
|
||||
}
|
||||
if (typeof arg0 !== 'string' && typeof arg0.value !== 'string') {
|
||||
throw illegalArgument('command');
|
||||
}
|
||||
this._command = arg0;
|
||||
this._args = arg1 as (string | vscode.ShellQuotedString)[];
|
||||
this._options = arg2;
|
||||
} else {
|
||||
if (typeof arg0 !== 'string') {
|
||||
throw illegalArgument('commandLine');
|
||||
}
|
||||
this._commandLine = arg0;
|
||||
this._options = arg1;
|
||||
}
|
||||
this._commandLine = commandLine;
|
||||
this._options = options;
|
||||
}
|
||||
|
||||
get commandLine(): string {
|
||||
@@ -1332,6 +1433,25 @@ export class ShellExecution implements vscode.ShellExecution {
|
||||
this._commandLine = value;
|
||||
}
|
||||
|
||||
get command(): string | vscode.ShellQuotedString {
|
||||
return this._command;
|
||||
}
|
||||
|
||||
set command(value: string | vscode.ShellQuotedString) {
|
||||
if (typeof value !== 'string' && typeof value.value !== 'string') {
|
||||
throw illegalArgument('command');
|
||||
}
|
||||
this._command = value;
|
||||
}
|
||||
|
||||
get args(): (string | vscode.ShellQuotedString)[] {
|
||||
return this._args;
|
||||
}
|
||||
|
||||
set args(value: (string | vscode.ShellQuotedString)[]) {
|
||||
this._args = value || [];
|
||||
}
|
||||
|
||||
get options(): vscode.ShellExecutionOptions {
|
||||
return this._options;
|
||||
}
|
||||
@@ -1339,6 +1459,29 @@ export class ShellExecution implements vscode.ShellExecution {
|
||||
set options(value: vscode.ShellExecutionOptions) {
|
||||
this._options = value;
|
||||
}
|
||||
|
||||
public computeId(): string {
|
||||
const hash = crypto.createHash('md5');
|
||||
hash.update('shell');
|
||||
if (this._commandLine !== void 0) {
|
||||
hash.update(this._commandLine);
|
||||
}
|
||||
if (this._command !== void 0) {
|
||||
hash.update(typeof this._command === 'string' ? this._command : this._command.value);
|
||||
}
|
||||
if (this._args && this._args.length > 0) {
|
||||
for (let arg of this._args) {
|
||||
hash.update(typeof arg === 'string' ? arg : arg.value);
|
||||
}
|
||||
}
|
||||
return hash.digest('hex');
|
||||
}
|
||||
}
|
||||
|
||||
export enum ShellQuoting {
|
||||
Escape = 1,
|
||||
Strong = 2,
|
||||
Weak = 3
|
||||
}
|
||||
|
||||
export enum TaskScope {
|
||||
@@ -1348,6 +1491,8 @@ export enum TaskScope {
|
||||
|
||||
export class Task implements vscode.Task {
|
||||
|
||||
private __id: string;
|
||||
|
||||
private _definition: vscode.TaskDefinition;
|
||||
private _definitionKey: string;
|
||||
private _scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder;
|
||||
@@ -1396,6 +1541,35 @@ export class Task implements vscode.Task {
|
||||
this._isBackground = false;
|
||||
}
|
||||
|
||||
get _id(): string {
|
||||
return this.__id;
|
||||
}
|
||||
|
||||
set _id(value: string) {
|
||||
this.__id = value;
|
||||
}
|
||||
|
||||
private clear(): void {
|
||||
if (this.__id === void 0) {
|
||||
return;
|
||||
}
|
||||
this.__id = undefined;
|
||||
this._scope = undefined;
|
||||
this._definitionKey = undefined;
|
||||
this._definition = undefined;
|
||||
if (this._execution instanceof ProcessExecution) {
|
||||
this._definition = {
|
||||
type: 'process',
|
||||
id: this._execution.computeId()
|
||||
};
|
||||
} else if (this._execution instanceof ShellExecution) {
|
||||
this._definition = {
|
||||
type: 'shell',
|
||||
id: this._execution.computeId()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
get definition(): vscode.TaskDefinition {
|
||||
return this._definition;
|
||||
}
|
||||
@@ -1404,6 +1578,7 @@ export class Task implements vscode.Task {
|
||||
if (value === void 0 || value === null) {
|
||||
throw illegalArgument('Kind can\'t be undefined or null');
|
||||
}
|
||||
this.clear();
|
||||
this._definitionKey = undefined;
|
||||
this._definition = value;
|
||||
}
|
||||
@@ -1422,6 +1597,7 @@ export class Task implements vscode.Task {
|
||||
}
|
||||
|
||||
set target(value: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder) {
|
||||
this.clear();
|
||||
this._scope = value;
|
||||
}
|
||||
|
||||
@@ -1433,6 +1609,7 @@ export class Task implements vscode.Task {
|
||||
if (typeof value !== 'string') {
|
||||
throw illegalArgument('name');
|
||||
}
|
||||
this.clear();
|
||||
this._name = value;
|
||||
}
|
||||
|
||||
@@ -1444,6 +1621,7 @@ export class Task implements vscode.Task {
|
||||
if (value === null) {
|
||||
value = undefined;
|
||||
}
|
||||
this.clear();
|
||||
this._execution = value;
|
||||
}
|
||||
|
||||
@@ -1457,6 +1635,7 @@ export class Task implements vscode.Task {
|
||||
this._hasDefinedMatchers = false;
|
||||
return;
|
||||
}
|
||||
this.clear();
|
||||
this._problemMatchers = value;
|
||||
this._hasDefinedMatchers = true;
|
||||
}
|
||||
@@ -1473,6 +1652,7 @@ export class Task implements vscode.Task {
|
||||
if (value !== true && value !== false) {
|
||||
value = false;
|
||||
}
|
||||
this.clear();
|
||||
this._isBackground = value;
|
||||
}
|
||||
|
||||
@@ -1484,6 +1664,7 @@ export class Task implements vscode.Task {
|
||||
if (typeof value !== 'string' || value.length === 0) {
|
||||
throw illegalArgument('source must be a string of length > 0');
|
||||
}
|
||||
this.clear();
|
||||
this._source = value;
|
||||
}
|
||||
|
||||
@@ -1496,6 +1677,7 @@ export class Task implements vscode.Task {
|
||||
this._group = undefined;
|
||||
return;
|
||||
}
|
||||
this.clear();
|
||||
this._group = value;
|
||||
}
|
||||
|
||||
@@ -1507,6 +1689,7 @@ export class Task implements vscode.Task {
|
||||
if (value === null) {
|
||||
value = undefined;
|
||||
}
|
||||
this.clear();
|
||||
this._presentationOptions = value;
|
||||
}
|
||||
}
|
||||
@@ -1515,6 +1698,7 @@ export class Task implements vscode.Task {
|
||||
export enum ProgressLocation {
|
||||
SourceControl = 1,
|
||||
Window = 10,
|
||||
Notification = 15
|
||||
}
|
||||
|
||||
export class TreeItem {
|
||||
@@ -1600,8 +1784,9 @@ export class Breakpoint {
|
||||
readonly enabled: boolean;
|
||||
readonly condition?: string;
|
||||
readonly hitCondition?: string;
|
||||
readonly logMessage?: string;
|
||||
|
||||
protected constructor(enabled?: boolean, condition?: string, hitCondition?: string) {
|
||||
protected constructor(enabled?: boolean, condition?: string, hitCondition?: string, logMessage?: string) {
|
||||
this.enabled = typeof enabled === 'boolean' ? enabled : true;
|
||||
if (typeof condition === 'string') {
|
||||
this.condition = condition;
|
||||
@@ -1609,14 +1794,17 @@ export class Breakpoint {
|
||||
if (typeof hitCondition === 'string') {
|
||||
this.hitCondition = hitCondition;
|
||||
}
|
||||
if (typeof logMessage === 'string') {
|
||||
this.logMessage = logMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class SourceBreakpoint extends Breakpoint {
|
||||
readonly location: Location;
|
||||
|
||||
constructor(location: Location, enabled?: boolean, condition?: string, hitCondition?: string) {
|
||||
super(enabled, condition, hitCondition);
|
||||
constructor(location: Location, enabled?: boolean, condition?: string, hitCondition?: string, logMessage?: string) {
|
||||
super(enabled, condition, hitCondition, logMessage);
|
||||
if (location === null) {
|
||||
throw illegalArgument('location');
|
||||
}
|
||||
@@ -1627,8 +1815,8 @@ export class SourceBreakpoint extends Breakpoint {
|
||||
export class FunctionBreakpoint extends Breakpoint {
|
||||
readonly functionName: string;
|
||||
|
||||
constructor(functionName: string, enabled?: boolean, condition?: string, hitCondition?: string) {
|
||||
super(enabled, condition, hitCondition);
|
||||
constructor(functionName: string, enabled?: boolean, condition?: string, hitCondition?: string, logMessage?: string) {
|
||||
super(enabled, condition, hitCondition, logMessage);
|
||||
if (!functionName) {
|
||||
throw illegalArgument('functionName');
|
||||
}
|
||||
@@ -1661,59 +1849,85 @@ 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);
|
||||
}
|
||||
static NoPermissions(messageOrUri?: string | URI): FileSystemError {
|
||||
return new FileSystemError(messageOrUri, 'NoPermissions', FileSystemError.NoPermissions);
|
||||
}
|
||||
static Unavailable(messageOrUri?: string | URI): FileSystemError {
|
||||
return new FileSystemError(messageOrUri, 'Unavailable', FileSystemError.Unavailable);
|
||||
}
|
||||
|
||||
constructor(uriOrMessage?: string | URI, code?: string, terminator?: Function) {
|
||||
super(URI.isUri(uriOrMessage) ? uriOrMessage.toString(true) : uriOrMessage);
|
||||
this.name = code ? `${code} (FileSystemError)` : `FileSystemError`;
|
||||
|
||||
// workaround when extending builtin objects and when compiling to ES5, see:
|
||||
// https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
|
||||
if (typeof (<any>Object).setPrototypeOf === 'function') {
|
||||
(<any>Object).setPrototypeOf(this, FileSystemError.prototype);
|
||||
}
|
||||
|
||||
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 {
|
||||
/**
|
||||
* Folding range for a comment
|
||||
*/
|
||||
Comment = 'comment',
|
||||
/**
|
||||
* Folding range for a imports or includes
|
||||
*/
|
||||
Imports = 'imports',
|
||||
/**
|
||||
* Folding range for a region (e.g. `#region`)
|
||||
*/
|
||||
Region = 'region'
|
||||
export enum FoldingRangeKind {
|
||||
Comment = 1,
|
||||
Imports = 2,
|
||||
Region = 3
|
||||
}
|
||||
|
||||
//#endregion
|
||||
//#endregion
|
||||
|
||||
53
src/vs/workbench/api/node/extHostUrls.ts
Normal file
53
src/vs/workbench/api/node/extHostUrls.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. 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 handles = new Set<string>();
|
||||
private handlers = new Map<number, vscode.ProtocolHandler>();
|
||||
|
||||
constructor(
|
||||
mainContext: IMainContext
|
||||
) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadUrls);
|
||||
}
|
||||
|
||||
registerProtocolHandler(extensionId: string, handler: vscode.ProtocolHandler): vscode.Disposable {
|
||||
if (this.handles.has(extensionId)) {
|
||||
throw new Error(`Protocol handler already registered for extension ${extensionId}`);
|
||||
}
|
||||
|
||||
const handle = ExtHostUrls.HandlePool++;
|
||||
this.handles.add(extensionId);
|
||||
this.handlers.set(handle, handler);
|
||||
this._proxy.$registerProtocolHandler(handle, extensionId);
|
||||
|
||||
return toDisposable(() => {
|
||||
this.handles.delete(extensionId);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -3,71 +3,36 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { MainContext, MainThreadWebviewsShape, IMainContext, ExtHostWebviewsShape, WebviewHandle } from './extHost.protocol';
|
||||
import { MainContext, MainThreadWebviewsShape, IMainContext, ExtHostWebviewsShape, WebviewPanelHandle } from './extHost.protocol';
|
||||
import * as vscode from 'vscode';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
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 {
|
||||
public readonly editorType = 'webview';
|
||||
|
||||
private _title: string;
|
||||
private readonly _handle: WebviewPanelHandle;
|
||||
private readonly _proxy: MainThreadWebviewsShape;
|
||||
private _html: string;
|
||||
private _options: vscode.WebviewOptions;
|
||||
private _isDisposed: boolean = false;
|
||||
private _viewColumn: vscode.ViewColumn;
|
||||
|
||||
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 onDidChangeViewColumnEmitter = new Emitter<vscode.ViewColumn>();
|
||||
public readonly onDidChangeViewColumn: Event<vscode.ViewColumn> = this.onDidChangeViewColumnEmitter.event;
|
||||
readonly _onMessageEmitter = new Emitter<any>();
|
||||
public readonly onDidReceiveMessage: Event<any> = this._onMessageEmitter.event;
|
||||
|
||||
constructor(
|
||||
private readonly _handle: WebviewHandle,
|
||||
private readonly _proxy: MainThreadWebviewsShape,
|
||||
private readonly _uri: vscode.Uri,
|
||||
viewColumn: vscode.ViewColumn,
|
||||
handle: WebviewPanelHandle,
|
||||
proxy: MainThreadWebviewsShape,
|
||||
options: vscode.WebviewOptions
|
||||
) {
|
||||
this._viewColumn = viewColumn;
|
||||
this._handle = handle;
|
||||
this._proxy = proxy;
|
||||
this._options = options;
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
if (this._isDisposed) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._isDisposed = true;
|
||||
this._proxy.$disposeWebview(this._handle);
|
||||
|
||||
this.onDisposeEmitter.dispose();
|
||||
this.onMessageEmitter.dispose();
|
||||
this.onDidChangeViewColumnEmitter.dispose();
|
||||
}
|
||||
|
||||
get uri(): vscode.Uri {
|
||||
this.assertNotDisposed();
|
||||
return this._uri;
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -88,22 +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;
|
||||
}
|
||||
|
||||
set viewColumn(value: vscode.ViewColumn) {
|
||||
_setViewColumn(value: vscode.ViewColumn) {
|
||||
this.assertNotDisposed();
|
||||
this._viewColumn = value;
|
||||
}
|
||||
|
||||
public postMessage(message: any): Thenable<boolean> {
|
||||
return this._proxy.$sendMessage(this._handle, message);
|
||||
get visible(): boolean {
|
||||
this.assertNotDisposed();
|
||||
return this._visible;
|
||||
}
|
||||
|
||||
public show(viewColumn: vscode.ViewColumn): void {
|
||||
this._proxy.$show(this._handle, typeConverters.fromViewColumn(viewColumn));
|
||||
_setVisible(value: boolean) {
|
||||
this.assertNotDisposed();
|
||||
this._visible = value;
|
||||
}
|
||||
|
||||
public postMessage(message: any): Thenable<boolean> {
|
||||
this.assertNotDisposed();
|
||||
return this._proxy.$postMessage(this._handle, message);
|
||||
}
|
||||
|
||||
public reveal(viewColumn?: vscode.ViewColumn): void {
|
||||
this.assertNotDisposed();
|
||||
this._proxy.$reveal(this._handle, viewColumn ? typeConverters.fromViewColumn(viewColumn) : undefined);
|
||||
}
|
||||
|
||||
private assertNotDisposed() {
|
||||
@@ -114,11 +184,12 @@ export class ExtHostWebview implements vscode.Webview {
|
||||
}
|
||||
|
||||
export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
private static handlePool = 0;
|
||||
private static webviewHandlePool = 1;
|
||||
|
||||
private readonly _proxy: MainThreadWebviewsShape;
|
||||
|
||||
private readonly _webviews = new Map<WebviewHandle, ExtHostWebview>();
|
||||
private readonly _webviewPanels = new Map<WebviewPanelHandle, ExtHostWebviewPanel>();
|
||||
private readonly _serializers = new Map<string, vscode.WebviewPanelSerializer>();
|
||||
|
||||
constructor(
|
||||
mainContext: IMainContext
|
||||
@@ -127,54 +198,103 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
}
|
||||
|
||||
createWebview(
|
||||
uri: vscode.Uri,
|
||||
viewType: string,
|
||||
title: string,
|
||||
viewColumn: vscode.ViewColumn,
|
||||
options: vscode.WebviewOptions
|
||||
): vscode.Webview {
|
||||
const handle = ExtHostWebviews.handlePool++;
|
||||
this._proxy.$createWebview(handle, uri, title, typeConverters.fromViewColumn(viewColumn), options);
|
||||
options: (vscode.WebviewPanelOptions & vscode.WebviewOptions) | undefined,
|
||||
extensionFolderPath: string
|
||||
): vscode.WebviewPanel {
|
||||
options = options || {};
|
||||
const handle = ExtHostWebviews.webviewHandlePool++ + '';
|
||||
this._proxy.$createWebviewPanel(handle, viewType, title, typeConverters.fromViewColumn(viewColumn), options, extensionFolderPath);
|
||||
|
||||
const webview = new ExtHostWebview(handle, this._proxy, uri, 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;
|
||||
}
|
||||
|
||||
$onMessage(handle: WebviewHandle, message: any): void {
|
||||
const webview = this.getWebview(handle);
|
||||
if (webview) {
|
||||
webview.onMessageEmitter.fire(message);
|
||||
registerWebviewPanelSerializer(
|
||||
viewType: string,
|
||||
serializer: vscode.WebviewPanelSerializer
|
||||
): vscode.Disposable {
|
||||
if (this._serializers.has(viewType)) {
|
||||
throw new Error(`Serializer for '${viewType}' already registered`);
|
||||
}
|
||||
|
||||
this._serializers.set(viewType, serializer);
|
||||
this._proxy.$registerSerializer(viewType);
|
||||
|
||||
return new Disposable(() => {
|
||||
this._serializers.delete(viewType);
|
||||
this._proxy.$unregisterSerializer(viewType);
|
||||
});
|
||||
}
|
||||
|
||||
$onMessage(handle: WebviewPanelHandle, message: any): void {
|
||||
const panel = this.getWebviewPanel(handle);
|
||||
if (panel) {
|
||||
panel.webview._onMessageEmitter.fire(message);
|
||||
}
|
||||
}
|
||||
|
||||
$onDidChangeActiveWeview(handle: WebviewHandle | undefined): void {
|
||||
this._onDidChangeActiveWebview.fire(this.getWebview(handle));
|
||||
}
|
||||
|
||||
$onDidDisposeWeview(handle: WebviewHandle): Thenable<void> {
|
||||
const webview = this.getWebview(handle);
|
||||
if (webview) {
|
||||
webview.onDisposeEmitter.fire();
|
||||
this._webviews.delete(handle);
|
||||
}
|
||||
return TPromise.as(void 0);
|
||||
}
|
||||
|
||||
$onDidChangePosition(handle: WebviewHandle, newPosition: Position): void {
|
||||
const webview = this.getWebview(handle);
|
||||
if (webview) {
|
||||
const newViewColumn = typeConverters.toViewColumn(newPosition);
|
||||
if (webview.viewColumn !== newViewColumn) {
|
||||
webview.viewColumn = newViewColumn;
|
||||
webview.onDidChangeViewColumnEmitter.fire(newViewColumn);
|
||||
$onDidChangeWebviewPanelViewState(handle: WebviewPanelHandle, visible: boolean, position: Position): void {
|
||||
const panel = this.getWebviewPanel(handle);
|
||||
if (panel) {
|
||||
const viewColumn = typeConverters.toViewColumn(position);
|
||||
if (panel.visible !== visible || panel.viewColumn !== viewColumn) {
|
||||
panel._setVisible(visible);
|
||||
panel._setViewColumn(viewColumn);
|
||||
panel._onDidChangeViewStateEmitter.fire({ webviewPanel: panel });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly _onDidChangeActiveWebview = new Emitter<ExtHostWebview | undefined>();
|
||||
public readonly onDidChangeActiveWebview = this._onDidChangeActiveWebview.event;
|
||||
$onDidDisposeWebviewPanel(handle: WebviewPanelHandle): Thenable<void> {
|
||||
const panel = this.getWebviewPanel(handle);
|
||||
if (panel) {
|
||||
panel.dispose();
|
||||
this._webviewPanels.delete(handle);
|
||||
}
|
||||
return TPromise.as(void 0);
|
||||
}
|
||||
|
||||
private getWebview(handle: WebviewHandle) {
|
||||
return this._webviews.get(handle);
|
||||
$deserializeWebviewPanel(
|
||||
webviewHandle: WebviewPanelHandle,
|
||||
viewType: string,
|
||||
title: string,
|
||||
state: any,
|
||||
position: Position,
|
||||
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 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);
|
||||
}
|
||||
|
||||
$serializeWebviewPanel(
|
||||
webviewHandle: WebviewPanelHandle
|
||||
): Thenable<any> {
|
||||
const panel = this.getWebviewPanel(webviewHandle);
|
||||
if (!panel) {
|
||||
return TPromise.as(undefined);
|
||||
}
|
||||
|
||||
const serialzer = this._serializers.get(panel.viewType);
|
||||
if (!serialzer) {
|
||||
return TPromise.as(undefined);
|
||||
}
|
||||
|
||||
return serialzer.serializeWebviewPanel(panel);
|
||||
}
|
||||
|
||||
private getWebviewPanel(handle: WebviewPanelHandle): ExtHostWebviewPanel | undefined {
|
||||
return this._webviewPanels.get(handle);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { ExtHostWindowShape, MainContext, MainThreadWindowShape, IMainContext } from './extHost.protocol';
|
||||
import { WindowState } from 'vscode';
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
'use strict';
|
||||
|
||||
import URI from 'vs/base/common/uri';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { normalize } from 'vs/base/common/paths';
|
||||
import { delta as arrayDelta } from 'vs/base/common/arrays';
|
||||
import { relative, dirname } from 'path';
|
||||
import { relative, posix } from 'path';
|
||||
import { Workspace, WorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkspaceData, ExtHostWorkspaceShape, MainContext, MainThreadWorkspaceShape, IMainContext, MainThreadMessageServiceShape } from './extHost.protocol';
|
||||
import * as vscode from 'vscode';
|
||||
@@ -121,10 +121,14 @@ class ExtHostWorkspaceImpl extends Workspace {
|
||||
getWorkspaceFolder(uri: URI, resolveParent?: boolean): vscode.WorkspaceFolder {
|
||||
if (resolveParent && this._structure.get(uri.toString())) {
|
||||
// `uri` is a workspace folder so we check for its parent
|
||||
uri = uri.with({ path: dirname(uri.path) });
|
||||
uri = uri.with({ path: posix.dirname(uri.path) });
|
||||
}
|
||||
return this._structure.findSubstr(uri.toString());
|
||||
}
|
||||
|
||||
resolveWorkspaceFolder(uri: URI): vscode.WorkspaceFolder {
|
||||
return this._structure.get(uri.toString());
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostWorkspace implements ExtHostWorkspaceShape {
|
||||
@@ -239,6 +243,13 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
|
||||
return this._actualWorkspace.getWorkspaceFolder(uri, resolveParent);
|
||||
}
|
||||
|
||||
resolveWorkspaceFolder(uri: vscode.Uri): vscode.WorkspaceFolder {
|
||||
if (!this._actualWorkspace) {
|
||||
return undefined;
|
||||
}
|
||||
return this._actualWorkspace.resolveWorkspaceFolder(uri);
|
||||
}
|
||||
|
||||
getPath(): string {
|
||||
|
||||
// this is legacy from the days before having
|
||||
@@ -352,7 +363,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
|
||||
if (token) {
|
||||
token.onCancellationRequested(() => this._proxy.$cancelSearch(requestId));
|
||||
}
|
||||
return result.then(data => data.map(URI.revive));
|
||||
return result.then(data => Array.isArray(data) ? data.map(URI.revive) : []);
|
||||
}
|
||||
|
||||
saveAll(includeUntitled?: boolean): Thenable<boolean> {
|
||||
|
||||
Reference in New Issue
Block a user