mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-21 01:25:37 -05:00
Merge VS Code 1.21 source code (#1067)
* Initial VS Code 1.21 file copy with patches * A few more merges * Post npm install * Fix batch of build breaks * Fix more build breaks * Fix more build errors * Fix more build breaks * Runtime fixes 1 * Get connection dialog working with some todos * Fix a few packaging issues * Copy several node_modules to package build to fix loader issues * Fix breaks from master * A few more fixes * Make tests pass * First pass of license header updates * Second pass of license header updates * Fix restore dialog issues * Remove add additional themes menu items * fix select box issues where the list doesn't show up * formatting * Fix editor dispose issue * Copy over node modules to correct location on all platforms
This commit is contained in:
@@ -40,38 +40,45 @@ import { ExtHostWindow } from 'vs/workbench/api/node/extHostWindow';
|
||||
import * as extHostTypes from 'vs/workbench/api/node/extHostTypes';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import EditorCommon = require('vs/editor/common/editorCommon');
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
|
||||
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 { MainContext, ExtHostContext, IInitData } from './extHost.protocol';
|
||||
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';
|
||||
import { ExtHostThreadService } from 'vs/workbench/services/thread/node/extHostThreadService';
|
||||
import { ProxyIdentifier } from 'vs/workbench/services/thread/common/threadService';
|
||||
import { ProxyIdentifier } from 'vs/workbench/services/extensions/node/proxyIdentifier';
|
||||
import { ExtHostDialogs } from 'vs/workbench/api/node/extHostDialogs';
|
||||
import { ExtHostFileSystem } from 'vs/workbench/api/node/extHostFileSystem';
|
||||
import { FileChangeType, FileType } from 'vs/platform/files/common/files';
|
||||
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 { ILogService } from 'vs/platform/log/common/log';
|
||||
import { OverviewRulerLane } from 'vs/editor/common/model';
|
||||
import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService';
|
||||
import { ExtHostWebviews } from 'vs/workbench/api/node/extHostWebview';
|
||||
|
||||
export interface IExtensionApiFactory {
|
||||
(extension: IExtensionDescription): typeof vscode;
|
||||
}
|
||||
|
||||
export function checkProposedApiEnabled(extension: IExtensionDescription): void {
|
||||
if (!extension.enableProposedApi) {
|
||||
throwProposedApiError(extension);
|
||||
}
|
||||
}
|
||||
|
||||
function throwProposedApiError(extension: IExtensionDescription): never {
|
||||
throw new Error(`[${extension.id}]: Proposed API is only available when running out of dev or with the following command line switch: --enable-proposed-api ${extension.id}`);
|
||||
}
|
||||
|
||||
function proposedApiFunction<T>(extension: IExtensionDescription, fn: T): T {
|
||||
if (extension.enableProposedApi) {
|
||||
return fn;
|
||||
} else {
|
||||
return <any>(() => {
|
||||
throw new Error(`[${extension.id}]: Proposed API is only available when running out of dev or with the following command line switch: --enable-proposed-api ${extension.id}`);
|
||||
});
|
||||
return <any>throwProposedApiError;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,49 +87,51 @@ function proposedApiFunction<T>(extension: IExtensionDescription, fn: T): T {
|
||||
*/
|
||||
export function createApiFactory(
|
||||
initData: IInitData,
|
||||
threadService: ExtHostThreadService,
|
||||
rpcProtocol: IExtHostContext,
|
||||
extHostWorkspace: ExtHostWorkspace,
|
||||
extHostConfiguration: ExtHostConfiguration,
|
||||
extensionService: ExtHostExtensionService,
|
||||
logService: ILogService
|
||||
extHostLogService: ExtHostLogService
|
||||
): IExtensionApiFactory {
|
||||
|
||||
// Addressable instances
|
||||
const extHostHeapService = threadService.set(ExtHostContext.ExtHostHeapService, new ExtHostHeapService());
|
||||
const extHostDecorations = threadService.set(ExtHostContext.ExtHostDecorations, new ExtHostDecorations(threadService));
|
||||
const extHostDocumentsAndEditors = threadService.set(ExtHostContext.ExtHostDocumentsAndEditors, new ExtHostDocumentsAndEditors(threadService));
|
||||
const extHostDocuments = threadService.set(ExtHostContext.ExtHostDocuments, new ExtHostDocuments(threadService, extHostDocumentsAndEditors));
|
||||
const extHostDocumentContentProviders = threadService.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(threadService, extHostDocumentsAndEditors));
|
||||
const extHostDocumentSaveParticipant = threadService.set(ExtHostContext.ExtHostDocumentSaveParticipant, new ExtHostDocumentSaveParticipant(extHostDocuments, threadService.get(MainContext.MainThreadEditors)));
|
||||
const extHostEditors = threadService.set(ExtHostContext.ExtHostEditors, new ExtHostEditors(threadService, extHostDocumentsAndEditors));
|
||||
const extHostCommands = threadService.set(ExtHostContext.ExtHostCommands, new ExtHostCommands(threadService, extHostHeapService, logService));
|
||||
const extHostTreeViews = threadService.set(ExtHostContext.ExtHostTreeViews, new ExtHostTreeViews(threadService.get(MainContext.MainThreadTreeViews), extHostCommands));
|
||||
threadService.set(ExtHostContext.ExtHostWorkspace, extHostWorkspace);
|
||||
rpcProtocol.set(ExtHostContext.ExtHostLogService, extHostLogService);
|
||||
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 extHostDocuments = rpcProtocol.set(ExtHostContext.ExtHostDocuments, new ExtHostDocuments(rpcProtocol, extHostDocumentsAndEditors));
|
||||
const extHostDocumentContentProviders = rpcProtocol.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(rpcProtocol, extHostDocumentsAndEditors));
|
||||
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));
|
||||
const extHostTreeViews = rpcProtocol.set(ExtHostContext.ExtHostTreeViews, new ExtHostTreeViews(rpcProtocol.getProxy(MainContext.MainThreadTreeViews), extHostCommands));
|
||||
rpcProtocol.set(ExtHostContext.ExtHostWorkspace, extHostWorkspace);
|
||||
// {{SQL CARBON EDIT}}
|
||||
//const extHostDebugService = threadService.set(ExtHostContext.ExtHostDebugService, new ExtHostDebugService(threadService, extHostWorkspace));
|
||||
threadService.set(ExtHostContext.ExtHostConfiguration, extHostConfiguration);
|
||||
const extHostDiagnostics = threadService.set(ExtHostContext.ExtHostDiagnostics, new ExtHostDiagnostics(threadService));
|
||||
const languageFeatures = threadService.set(ExtHostContext.ExtHostLanguageFeatures, new ExtHostLanguageFeatures(threadService, extHostDocuments, extHostCommands, extHostHeapService, extHostDiagnostics));
|
||||
const extHostFileSystem = threadService.set(ExtHostContext.ExtHostFileSystem, new ExtHostFileSystem(threadService));
|
||||
const extHostFileSystemEvent = threadService.set(ExtHostContext.ExtHostFileSystemEventService, new ExtHostFileSystemEventService());
|
||||
const extHostQuickOpen = threadService.set(ExtHostContext.ExtHostQuickOpen, new ExtHostQuickOpen(threadService, extHostWorkspace, extHostCommands));
|
||||
const extHostTerminalService = threadService.set(ExtHostContext.ExtHostTerminalService, new ExtHostTerminalService(threadService));
|
||||
const extHostSCM = threadService.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(threadService, extHostCommands, logService));
|
||||
const extHostTask = threadService.set(ExtHostContext.ExtHostTask, new ExtHostTask(threadService, extHostWorkspace));
|
||||
const extHostWindow = threadService.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(threadService));
|
||||
threadService.set(ExtHostContext.ExtHostExtensionService, extensionService);
|
||||
//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 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 extHostSCM = rpcProtocol.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(rpcProtocol, extHostCommands, extHostLogService));
|
||||
const extHostTask = rpcProtocol.set(ExtHostContext.ExtHostTask, new ExtHostTask(rpcProtocol, extHostWorkspace));
|
||||
const extHostWindow = rpcProtocol.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(rpcProtocol));
|
||||
rpcProtocol.set(ExtHostContext.ExtHostExtensionService, extensionService);
|
||||
|
||||
// Check that no named customers are missing
|
||||
const expected: ProxyIdentifier<any>[] = Object.keys(ExtHostContext).map((key) => ExtHostContext[key]);
|
||||
threadService.assertRegistered(expected);
|
||||
rpcProtocol.assertRegistered(expected);
|
||||
|
||||
// Other instances
|
||||
const extHostMessageService = new ExtHostMessageService(threadService);
|
||||
const extHostDialogs = new ExtHostDialogs(threadService);
|
||||
const extHostStatusBar = new ExtHostStatusBar(threadService);
|
||||
const extHostProgress = new ExtHostProgress(threadService.get(MainContext.MainThreadProgress));
|
||||
const extHostOutputService = new ExtHostOutputService(threadService);
|
||||
const extHostLanguages = new ExtHostLanguages(threadService);
|
||||
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);
|
||||
@@ -232,61 +241,64 @@ export function createApiFactory(
|
||||
return score(toLanguageSelector(selector), document.uri, document.languageId);
|
||||
},
|
||||
registerCodeActionsProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable {
|
||||
return languageFeatures.registerCodeActionProvider(selector, provider);
|
||||
return extHostLanguageFeatures.registerCodeActionProvider(selector, provider);
|
||||
},
|
||||
registerCodeLensProvider(selector: vscode.DocumentSelector, provider: vscode.CodeLensProvider): vscode.Disposable {
|
||||
return languageFeatures.registerCodeLensProvider(selector, provider);
|
||||
return extHostLanguageFeatures.registerCodeLensProvider(selector, provider);
|
||||
},
|
||||
registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable {
|
||||
return languageFeatures.registerDefinitionProvider(selector, provider);
|
||||
return extHostLanguageFeatures.registerDefinitionProvider(selector, provider);
|
||||
},
|
||||
registerImplementationProvider(selector: vscode.DocumentSelector, provider: vscode.ImplementationProvider): vscode.Disposable {
|
||||
return languageFeatures.registerImplementationProvider(selector, provider);
|
||||
return extHostLanguageFeatures.registerImplementationProvider(selector, provider);
|
||||
},
|
||||
registerTypeDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.TypeDefinitionProvider): vscode.Disposable {
|
||||
return languageFeatures.registerTypeDefinitionProvider(selector, provider);
|
||||
return extHostLanguageFeatures.registerTypeDefinitionProvider(selector, provider);
|
||||
},
|
||||
registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider): vscode.Disposable {
|
||||
return languageFeatures.registerHoverProvider(selector, provider, extension.id);
|
||||
return extHostLanguageFeatures.registerHoverProvider(selector, provider, extension.id);
|
||||
},
|
||||
registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable {
|
||||
return languageFeatures.registerDocumentHighlightProvider(selector, provider);
|
||||
return extHostLanguageFeatures.registerDocumentHighlightProvider(selector, provider);
|
||||
},
|
||||
registerReferenceProvider(selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable {
|
||||
return languageFeatures.registerReferenceProvider(selector, provider);
|
||||
return extHostLanguageFeatures.registerReferenceProvider(selector, provider);
|
||||
},
|
||||
registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable {
|
||||
return languageFeatures.registerRenameProvider(selector, provider);
|
||||
return extHostLanguageFeatures.registerRenameProvider(selector, provider, extension.enableProposedApi);
|
||||
},
|
||||
registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable {
|
||||
return languageFeatures.registerDocumentSymbolProvider(selector, provider);
|
||||
return extHostLanguageFeatures.registerDocumentSymbolProvider(selector, provider);
|
||||
},
|
||||
registerWorkspaceSymbolProvider(provider: vscode.WorkspaceSymbolProvider): vscode.Disposable {
|
||||
return languageFeatures.registerWorkspaceSymbolProvider(provider);
|
||||
return extHostLanguageFeatures.registerWorkspaceSymbolProvider(provider);
|
||||
},
|
||||
registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable {
|
||||
return languageFeatures.registerDocumentFormattingEditProvider(selector, provider);
|
||||
return extHostLanguageFeatures.registerDocumentFormattingEditProvider(selector, provider);
|
||||
},
|
||||
registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable {
|
||||
return languageFeatures.registerDocumentRangeFormattingEditProvider(selector, provider);
|
||||
return extHostLanguageFeatures.registerDocumentRangeFormattingEditProvider(selector, provider);
|
||||
},
|
||||
registerOnTypeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, firstTriggerCharacter: string, ...moreTriggerCharacters: string[]): vscode.Disposable {
|
||||
return languageFeatures.registerOnTypeFormattingEditProvider(selector, provider, [firstTriggerCharacter].concat(moreTriggerCharacters));
|
||||
return extHostLanguageFeatures.registerOnTypeFormattingEditProvider(selector, provider, [firstTriggerCharacter].concat(moreTriggerCharacters));
|
||||
},
|
||||
registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, ...triggerCharacters: string[]): vscode.Disposable {
|
||||
return languageFeatures.registerSignatureHelpProvider(selector, provider, triggerCharacters);
|
||||
return extHostLanguageFeatures.registerSignatureHelpProvider(selector, provider, triggerCharacters);
|
||||
},
|
||||
registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, ...triggerCharacters: string[]): vscode.Disposable {
|
||||
return languageFeatures.registerCompletionItemProvider(selector, provider, triggerCharacters);
|
||||
return extHostLanguageFeatures.registerCompletionItemProvider(selector, provider, triggerCharacters);
|
||||
},
|
||||
registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable {
|
||||
return languageFeatures.registerDocumentLinkProvider(selector, provider);
|
||||
return extHostLanguageFeatures.registerDocumentLinkProvider(selector, provider);
|
||||
},
|
||||
registerColorProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable {
|
||||
return languageFeatures.registerColorProvider(selector, provider);
|
||||
return extHostLanguageFeatures.registerColorProvider(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 languageFeatures.setLanguageConfiguration(language, configuration);
|
||||
return extHostLanguageFeatures.setLanguageConfiguration(language, configuration);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -324,6 +336,9 @@ 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[]) => {
|
||||
return extHostEditors.onDidChangeTextEditorVisibleRanges(listener, thisArgs, disposables);
|
||||
}),
|
||||
onDidChangeTextEditorViewColumn(listener, thisArg?, disposables?) {
|
||||
return extHostEditors.onDidChangeTextEditorViewColumn(listener, thisArg, disposables);
|
||||
},
|
||||
@@ -382,8 +397,8 @@ export function createApiFactory(
|
||||
}
|
||||
return extHostTerminalService.createTerminal(<string>nameOrOptions, shellPath, shellArgs);
|
||||
},
|
||||
registerTreeDataProvider(viewId: string, treeDataProvider: vscode.TreeDataProvider<any>): vscode.Disposable {
|
||||
return extHostTreeViews.registerTreeDataProvider(viewId, treeDataProvider);
|
||||
registerTreeDataProvider(viewId: string, treeDataProvider: vscode.TreeDataProvider<any>): vscode.TreeView<any> {
|
||||
return extHostTreeViews.registerTreeDataProvider(viewId, treeDataProvider, (fn) => proposedApiFunction(extension, fn));
|
||||
},
|
||||
// proposed API
|
||||
sampleFunction: proposedApiFunction(extension, () => {
|
||||
@@ -391,6 +406,12 @@ export function createApiFactory(
|
||||
}),
|
||||
registerDecorationProvider: proposedApiFunction(extension, (provider: vscode.DecorationProvider) => {
|
||||
return extHostDecorations.registerDecorationProvider(provider, extension.id);
|
||||
}),
|
||||
createWebview: proposedApiFunction(extension, (uri: vscode.Uri, title: string, column: vscode.ViewColumn, options: vscode.WebviewOptions) => {
|
||||
return extHostWebviews.createWebview(uri, title, column, options);
|
||||
}),
|
||||
onDidChangeActiveEditor: proposedApiFunction(extension, (listener, thisArg?, disposables?) => {
|
||||
return extHostDocumentsAndEditors.onDidChangeActiveEditor(listener, thisArg, disposables);
|
||||
})
|
||||
};
|
||||
|
||||
@@ -414,6 +435,9 @@ export function createApiFactory(
|
||||
set name(value) {
|
||||
throw errors.readonly();
|
||||
},
|
||||
updateWorkspaceFolders: (index, deleteCount, ...workspaceFoldersToAdd) => {
|
||||
return extHostWorkspace.updateWorkspaceFolders(extension, index, deleteCount || 0, ...workspaceFoldersToAdd);
|
||||
},
|
||||
onDidChangeWorkspaceFolders: function (listener, thisArgs?, disposables?) {
|
||||
return extHostWorkspace.onDidChangeWorkspace(listener, thisArgs, disposables);
|
||||
},
|
||||
@@ -421,7 +445,7 @@ export function createApiFactory(
|
||||
return extHostWorkspace.getRelativePath(pathOrUri, includeWorkspace);
|
||||
},
|
||||
findFiles: (include, exclude, maxResults?, token?) => {
|
||||
return extHostWorkspace.findFiles(toGlobPattern(include), toGlobPattern(exclude), maxResults, token);
|
||||
return extHostWorkspace.findFiles(toGlobPattern(include), toGlobPattern(exclude), maxResults, extension.id, token);
|
||||
},
|
||||
saveAll: (includeUntitled?) => {
|
||||
return extHostWorkspace.saveAll(includeUntitled);
|
||||
@@ -472,7 +496,7 @@ export function createApiFactory(
|
||||
return extHostDocuments.onDidSaveDocument(listener, thisArgs, disposables);
|
||||
},
|
||||
onWillSaveTextDocument: (listener, thisArgs?, disposables?) => {
|
||||
return extHostDocumentSaveParticipant.onWillSaveTextDocumentEvent(listener, thisArgs, disposables);
|
||||
return extHostDocumentSaveParticipant.getOnWillSaveTextDocumentEvent(extension)(listener, thisArgs, disposables);
|
||||
},
|
||||
onDidChangeConfiguration: (listener: (_: any) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) => {
|
||||
return extHostConfiguration.onDidChangeConfiguration(listener, thisArgs, disposables);
|
||||
@@ -521,6 +545,7 @@ export function createApiFactory(
|
||||
Breakpoint: extHostTypes.Breakpoint,
|
||||
CancellationTokenSource: CancellationTokenSource,
|
||||
CodeAction: extHostTypes.CodeAction,
|
||||
CodeActionKind: extHostTypes.CodeActionKind,
|
||||
CodeLens: extHostTypes.CodeLens,
|
||||
Color: extHostTypes.Color,
|
||||
ColorPresentation: extHostTypes.ColorPresentation,
|
||||
@@ -530,6 +555,8 @@ export function createApiFactory(
|
||||
CompletionItemKind: extHostTypes.CompletionItemKind,
|
||||
CompletionList: extHostTypes.CompletionList,
|
||||
CompletionTriggerKind: extHostTypes.CompletionTriggerKind,
|
||||
// {{SQL CARBON EDIT}}
|
||||
// DebugAdapterExecutable: extHostTypes.DebugAdapterExecutable,
|
||||
Diagnostic: extHostTypes.Diagnostic,
|
||||
DiagnosticSeverity: extHostTypes.DiagnosticSeverity,
|
||||
Disposable: extHostTypes.Disposable,
|
||||
@@ -541,8 +568,9 @@ export function createApiFactory(
|
||||
Hover: extHostTypes.Hover,
|
||||
IndentAction: languageConfiguration.IndentAction,
|
||||
Location: extHostTypes.Location,
|
||||
LogLevel: extHostTypes.LogLevel,
|
||||
MarkdownString: extHostTypes.MarkdownString,
|
||||
OverviewRulerLane: EditorCommon.OverviewRulerLane,
|
||||
OverviewRulerLane: OverviewRulerLane,
|
||||
ParameterInformation: extHostTypes.ParameterInformation,
|
||||
Position: extHostTypes.Position,
|
||||
Range: extHostTypes.Range,
|
||||
@@ -554,6 +582,7 @@ export function createApiFactory(
|
||||
StatusBarAlignment: extHostTypes.StatusBarAlignment,
|
||||
SymbolInformation: extHostTypes.SymbolInformation,
|
||||
SymbolKind: extHostTypes.SymbolKind,
|
||||
SourceControlInputBoxValidationType: extHostTypes.SourceControlInputBoxValidationType,
|
||||
TextDocumentSaveReason: extHostTypes.TextDocumentSaveReason,
|
||||
TextEdit: extHostTypes.TextEdit,
|
||||
TextEditorCursorStyle: TextEditorCursorStyle,
|
||||
@@ -566,6 +595,7 @@ export function createApiFactory(
|
||||
WorkspaceEdit: extHostTypes.WorkspaceEdit,
|
||||
ProgressLocation: extHostTypes.ProgressLocation,
|
||||
TreeItemCollapsibleState: extHostTypes.TreeItemCollapsibleState,
|
||||
ThemeIcon: extHostTypes.ThemeIcon,
|
||||
TreeItem: extHostTypes.TreeItem,
|
||||
ThemeColor: extHostTypes.ThemeColor,
|
||||
// functions
|
||||
@@ -579,9 +609,11 @@ export function createApiFactory(
|
||||
ConfigurationTarget: extHostTypes.ConfigurationTarget,
|
||||
RelativePattern: extHostTypes.RelativePattern,
|
||||
|
||||
// TODO@JOH,remote
|
||||
FileChangeType: <any>FileChangeType,
|
||||
FileType: <any>FileType
|
||||
FileChangeType: extHostTypes.FileChangeType,
|
||||
FileType: extHostTypes.FileType,
|
||||
FoldingRangeList: extHostTypes.FoldingRangeList,
|
||||
FoldingRange: extHostTypes.FoldingRange,
|
||||
FoldingRangeType: extHostTypes.FoldingRangeType
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,21 +4,17 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import {
|
||||
createMainContextProxyIdentifier as createMainId,
|
||||
createExtHostContextProxyIdentifier as createExtId,
|
||||
ProxyIdentifier
|
||||
} from 'vs/workbench/services/thread/common/threadService';
|
||||
import { createMainContextProxyIdentifier as createMainId, createExtHostContextProxyIdentifier as createExtId, ProxyIdentifier, IRPCProtocol } from 'vs/workbench/services/extensions/node/proxyIdentifier';
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import URI from 'vs/base/common/uri';
|
||||
import URI, { UriComponents } from 'vs/base/common/uri';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
|
||||
import { IMarkerData } from 'vs/platform/markers/common/markers';
|
||||
import { Position as EditorPosition } from 'vs/platform/editor/common/editor';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { StatusbarAlignment as MainThreadStatusBarAlignment } from 'vs/platform/statusbar/common/statusbar';
|
||||
import { ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
|
||||
@@ -26,9 +22,9 @@ import { IProgressOptions, IProgressStep } from 'vs/platform/progress/common/pro
|
||||
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import { ITextSource } from 'vs/editor/common/model/textSource';
|
||||
|
||||
import { IConfigurationData, ConfigurationTarget, IConfigurationModel } from 'vs/platform/configuration/common/configuration';
|
||||
import { IConfig, IAdapterExecutable } 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';
|
||||
@@ -37,7 +33,7 @@ import { EndOfLine, TextEditorLineNumbersStyle } from 'vs/workbench/api/node/ext
|
||||
|
||||
|
||||
import { TaskSet } from 'vs/workbench/parts/tasks/common/tasks';
|
||||
import { IModelChangedEvent } from 'vs/editor/common/model/mirrorModel';
|
||||
import { IModelChangedEvent } from 'vs/editor/common/model/mirrorTextModel';
|
||||
import { IPosition } from 'vs/editor/common/core/position';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
import { ISelection, Selection } from 'vs/editor/common/core/selection';
|
||||
@@ -46,10 +42,13 @@ 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 { IWorkspaceFolderData } from 'vs/platform/workspace/common/workspace';
|
||||
import { IStat, IFileChange } from 'vs/platform/files/common/files';
|
||||
import { IStat, FileChangeType } 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';
|
||||
|
||||
export interface IEnvironment {
|
||||
isExtensionDevelopmentDebug: boolean;
|
||||
@@ -66,7 +65,8 @@ export interface IEnvironment {
|
||||
export interface IWorkspaceData {
|
||||
id: string;
|
||||
name: string;
|
||||
folders: IWorkspaceFolderData[];
|
||||
folders: { uri: UriComponents, name: string, index: number }[];
|
||||
configuration?: UriComponents;
|
||||
}
|
||||
|
||||
export interface IInitData {
|
||||
@@ -79,10 +79,11 @@ export interface IInitData {
|
||||
windowId: number;
|
||||
args: ParsedArgs;
|
||||
execPath: string;
|
||||
logLevel: LogLevel;
|
||||
}
|
||||
|
||||
export interface IConfigurationInitData extends IConfigurationData {
|
||||
configurationScopes: ConfigurationScope[];
|
||||
configurationScopes: { [key: string]: ConfigurationScope };
|
||||
}
|
||||
|
||||
export interface IWorkspaceConfigurationChangeEventData {
|
||||
@@ -90,46 +91,33 @@ export interface IWorkspaceConfigurationChangeEventData {
|
||||
changedConfigurationByResource: { [folder: string]: IConfigurationModel };
|
||||
}
|
||||
|
||||
export interface IExtHostContext {
|
||||
/**
|
||||
* Returns a proxy to an object addressable/named in the extension host process.
|
||||
*/
|
||||
get<T>(identifier: ProxyIdentifier<T>): T;
|
||||
|
||||
/**
|
||||
* Register manually created instance.
|
||||
*/
|
||||
set<T, R extends T>(identifier: ProxyIdentifier<T>, instance: R): R;
|
||||
export interface IExtHostContext extends IRPCProtocol {
|
||||
}
|
||||
|
||||
export interface IMainContext {
|
||||
/**
|
||||
* Returns a proxy to an object addressable/named in the main/renderer process.
|
||||
*/
|
||||
get<T>(identifier: ProxyIdentifier<T>): T;
|
||||
export interface IMainContext extends IRPCProtocol {
|
||||
}
|
||||
|
||||
// --- main thread
|
||||
|
||||
export interface MainThreadCommandsShape extends IDisposable {
|
||||
$registerCommand(id: string): TPromise<any>;
|
||||
$unregisterCommand(id: string): TPromise<any>;
|
||||
$registerCommand(id: string): void;
|
||||
$unregisterCommand(id: string): void;
|
||||
$executeCommand<T>(id: string, args: any[]): Thenable<T>;
|
||||
$getCommands(): Thenable<string[]>;
|
||||
}
|
||||
|
||||
export interface MainThreadConfigurationShape extends IDisposable {
|
||||
$updateConfigurationOption(target: ConfigurationTarget, key: string, value: any, resource: URI): TPromise<void>;
|
||||
$removeConfigurationOption(target: ConfigurationTarget, key: string, resource: URI): TPromise<void>;
|
||||
$updateConfigurationOption(target: ConfigurationTarget, key: string, value: any, resource: UriComponents): TPromise<void>;
|
||||
$removeConfigurationOption(target: ConfigurationTarget, key: string, resource: UriComponents): TPromise<void>;
|
||||
}
|
||||
|
||||
export interface MainThreadDiagnosticsShape extends IDisposable {
|
||||
$changeMany(owner: string, entries: [URI, IMarkerData[]][]): TPromise<any>;
|
||||
$clear(owner: string): TPromise<any>;
|
||||
$changeMany(owner: string, entries: [UriComponents, IMarkerData[]][]): void;
|
||||
$clear(owner: string): void;
|
||||
}
|
||||
|
||||
export interface MainThreadDialogOpenOptions {
|
||||
defaultUri?: URI;
|
||||
defaultUri?: UriComponents;
|
||||
openLabel?: string;
|
||||
canSelectFiles?: boolean;
|
||||
canSelectFolders?: boolean;
|
||||
@@ -138,37 +126,32 @@ export interface MainThreadDialogOpenOptions {
|
||||
}
|
||||
|
||||
export interface MainThreadDialogSaveOptions {
|
||||
defaultUri?: URI;
|
||||
defaultUri?: UriComponents;
|
||||
saveLabel?: string;
|
||||
filters?: { [name: string]: string[] };
|
||||
}
|
||||
|
||||
export interface MainThreadDiaglogsShape extends IDisposable {
|
||||
$showOpenDialog(options: MainThreadDialogOpenOptions): TPromise<string[]>;
|
||||
$showSaveDialog(options: MainThreadDialogSaveOptions): TPromise<string>;
|
||||
$showOpenDialog(options: MainThreadDialogOpenOptions): Thenable<string[]>;
|
||||
$showSaveDialog(options: MainThreadDialogSaveOptions): Thenable<string>;
|
||||
}
|
||||
|
||||
export interface MainThreadDecorationsShape extends IDisposable {
|
||||
$registerDecorationProvider(handle: number, label: string): void;
|
||||
$unregisterDecorationProvider(handle: number): void;
|
||||
$onDidChange(handle: number, resources: URI[]): void;
|
||||
$onDidChange(handle: number, resources: UriComponents[]): void;
|
||||
}
|
||||
|
||||
export interface MainThreadDocumentContentProvidersShape extends IDisposable {
|
||||
$registerTextContentProvider(handle: number, scheme: string): void;
|
||||
$unregisterTextContentProvider(handle: number): void;
|
||||
$onVirtualDocumentChange(uri: URI, value: ITextSource): void;
|
||||
$onVirtualDocumentChange(uri: UriComponents, value: string): void;
|
||||
}
|
||||
|
||||
export interface MainThreadDocumentsShape extends IDisposable {
|
||||
$tryCreateDocument(options?: { language?: string; content?: string; }): TPromise<any>;
|
||||
$tryOpenDocument(uri: URI): TPromise<any>;
|
||||
$trySaveDocument(uri: URI): TPromise<boolean>;
|
||||
}
|
||||
|
||||
export interface ISelectionChangeEvent {
|
||||
selections: Selection[];
|
||||
source?: string;
|
||||
$tryCreateDocument(options?: { language?: string; content?: string; }): TPromise<UriComponents>;
|
||||
$tryOpenDocument(uri: UriComponents): TPromise<void>;
|
||||
$trySaveDocument(uri: UriComponents): TPromise<boolean>;
|
||||
}
|
||||
|
||||
export interface ITextEditorConfigurationUpdate {
|
||||
@@ -201,8 +184,6 @@ export interface IApplyEditsOptions extends IUndoStopOptions {
|
||||
setEndOfLine: EndOfLine;
|
||||
}
|
||||
|
||||
|
||||
|
||||
export interface ITextDocumentShowOptions {
|
||||
position?: EditorPosition;
|
||||
preserveFocus?: boolean;
|
||||
@@ -210,64 +191,95 @@ export interface ITextDocumentShowOptions {
|
||||
selection?: IRange;
|
||||
}
|
||||
|
||||
export interface IWorkspaceResourceEdit {
|
||||
resource: URI;
|
||||
modelVersionId?: number;
|
||||
edits: {
|
||||
range?: IRange;
|
||||
newText: string;
|
||||
newEol?: editorCommon.EndOfLineSequence;
|
||||
}[];
|
||||
}
|
||||
|
||||
export interface MainThreadEditorsShape extends IDisposable {
|
||||
$tryShowTextDocument(resource: URI, options: ITextDocumentShowOptions): TPromise<string>;
|
||||
export interface MainThreadTextEditorsShape extends IDisposable {
|
||||
$tryShowTextDocument(resource: UriComponents, options: ITextDocumentShowOptions): TPromise<string>;
|
||||
$registerTextEditorDecorationType(key: string, options: editorCommon.IDecorationRenderOptions): void;
|
||||
$removeTextEditorDecorationType(key: string): void;
|
||||
$tryShowEditor(id: string, position: EditorPosition): TPromise<void>;
|
||||
$tryHideEditor(id: string): TPromise<void>;
|
||||
$trySetOptions(id: string, options: ITextEditorConfigurationUpdate): TPromise<any>;
|
||||
$trySetDecorations(id: string, key: string, ranges: editorCommon.IDecorationOptions[]): TPromise<any>;
|
||||
$trySetDecorationsFast(id: string, key: string, ranges: string): TPromise<any>;
|
||||
$tryRevealRange(id: string, range: IRange, revealType: TextEditorRevealType): TPromise<any>;
|
||||
$trySetSelections(id: string, selections: ISelection[]): TPromise<any>;
|
||||
$tryApplyEdits(id: string, modelVersionId: number, edits: editorCommon.ISingleEditOperation[], opts: IApplyEditsOptions): TPromise<boolean>;
|
||||
$tryApplyWorkspaceEdit(workspaceResourceEdits: IWorkspaceResourceEdit[]): TPromise<boolean>;
|
||||
$tryInsertSnippet(id: string, template: string, selections: IRange[], opts: IUndoStopOptions): TPromise<any>;
|
||||
$trySetOptions(id: string, options: ITextEditorConfigurationUpdate): TPromise<void>;
|
||||
$trySetDecorations(id: string, key: string, ranges: editorCommon.IDecorationOptions[]): TPromise<void>;
|
||||
$trySetDecorationsFast(id: string, key: string, ranges: number[]): TPromise<void>;
|
||||
$tryRevealRange(id: string, range: IRange, revealType: TextEditorRevealType): TPromise<void>;
|
||||
$trySetSelections(id: string, selections: ISelection[]): TPromise<void>;
|
||||
$tryApplyEdits(id: string, modelVersionId: number, edits: ISingleEditOperation[], opts: IApplyEditsOptions): TPromise<boolean>;
|
||||
$tryApplyWorkspaceEdit(workspaceEditDto: WorkspaceEditDto): TPromise<boolean>;
|
||||
$tryInsertSnippet(id: string, template: string, selections: IRange[], opts: IUndoStopOptions): TPromise<boolean>;
|
||||
$getDiffInformation(id: string): TPromise<editorCommon.ILineChange[]>;
|
||||
}
|
||||
|
||||
export interface MainThreadTreeViewsShape extends IDisposable {
|
||||
$registerView(treeViewId: string): void;
|
||||
$registerTreeViewDataProvider(treeViewId: string): void;
|
||||
$refresh(treeViewId: string, itemsToRefresh?: { [treeItemHandle: string]: ITreeItem }): void;
|
||||
$reveal(treeViewId: string, treeItem: ITreeItem, parentChain: ITreeItem[], options?: { select?: boolean }): TPromise<void>;
|
||||
}
|
||||
|
||||
export interface MainThreadErrorsShape extends IDisposable {
|
||||
$onUnexpectedError(err: any | SerializedError): void;
|
||||
}
|
||||
|
||||
export interface ISerializedRegExp {
|
||||
pattern: string;
|
||||
flags?: string;
|
||||
}
|
||||
export interface ISerializedIndentationRule {
|
||||
decreaseIndentPattern: ISerializedRegExp;
|
||||
increaseIndentPattern: ISerializedRegExp;
|
||||
indentNextLinePattern?: ISerializedRegExp;
|
||||
unIndentedLinePattern?: ISerializedRegExp;
|
||||
}
|
||||
export interface ISerializedOnEnterRule {
|
||||
beforeText: ISerializedRegExp;
|
||||
afterText?: ISerializedRegExp;
|
||||
action: EnterAction;
|
||||
}
|
||||
export interface ISerializedLanguageConfiguration {
|
||||
comments?: CommentRule;
|
||||
brackets?: CharacterPair[];
|
||||
wordPattern?: ISerializedRegExp;
|
||||
indentationRules?: ISerializedIndentationRule;
|
||||
onEnterRules?: ISerializedOnEnterRule[];
|
||||
__electricCharacterSupport?: {
|
||||
brackets?: any;
|
||||
docComment?: {
|
||||
scope: string;
|
||||
open: string;
|
||||
lineStart: string;
|
||||
close?: string;
|
||||
};
|
||||
};
|
||||
__characterPairSupport?: {
|
||||
autoClosingPairs: {
|
||||
open: string;
|
||||
close: string;
|
||||
notIn?: string[];
|
||||
}[];
|
||||
};
|
||||
}
|
||||
|
||||
export interface MainThreadLanguageFeaturesShape extends IDisposable {
|
||||
$unregister(handle: number): TPromise<any>;
|
||||
$registerOutlineSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
|
||||
$registerCodeLensSupport(handle: number, selector: vscode.DocumentSelector, eventHandle: number): TPromise<any>;
|
||||
$emitCodeLensEvent(eventHandle: number, event?: any): TPromise<any>;
|
||||
$registerDeclaractionSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
|
||||
$registerImplementationSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
|
||||
$registerTypeDefinitionSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
|
||||
$registerHoverProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
|
||||
$registerDocumentHighlightProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
|
||||
$registerReferenceSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
|
||||
$registerQuickFixSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
|
||||
$registerDocumentFormattingSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
|
||||
$registerRangeFormattingSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
|
||||
$registerOnTypeFormattingSupport(handle: number, selector: vscode.DocumentSelector, autoFormatTriggerCharacters: string[]): TPromise<any>;
|
||||
$registerNavigateTypeSupport(handle: number): TPromise<any>;
|
||||
$registerRenameSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
|
||||
$registerSuggestSupport(handle: number, selector: vscode.DocumentSelector, triggerCharacters: string[], supportsResolveDetails: boolean): TPromise<any>;
|
||||
$registerSignatureHelpProvider(handle: number, selector: vscode.DocumentSelector, triggerCharacter: string[]): TPromise<any>;
|
||||
$registerDocumentLinkProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
|
||||
$registerDocumentColorProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any>;
|
||||
$setLanguageConfiguration(handle: number, languageId: string, configuration: vscode.LanguageConfiguration): TPromise<any>;
|
||||
$unregister(handle: number): void;
|
||||
$registerOutlineSupport(handle: number, selector: vscode.DocumentSelector): void;
|
||||
$registerCodeLensSupport(handle: number, selector: vscode.DocumentSelector, 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;
|
||||
$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;
|
||||
$setLanguageConfiguration(handle: number, languageId: string, configuration: ISerializedLanguageConfiguration): void;
|
||||
}
|
||||
|
||||
export interface MainThreadLanguagesShape extends IDisposable {
|
||||
@@ -299,7 +311,7 @@ export interface MainThreadProgressShape extends IDisposable {
|
||||
}
|
||||
|
||||
export interface MainThreadTerminalServiceShape extends IDisposable {
|
||||
$createTerminal(name?: string, shellPath?: string, shellArgs?: string[], env?: { [key: string]: string }, waitOnExit?: boolean): TPromise<number>;
|
||||
$createTerminal(name?: string, shellPath?: string, shellArgs?: string[], cwd?: string, env?: { [key: string]: string }, waitOnExit?: boolean): TPromise<number>;
|
||||
$dispose(terminalId: number): void;
|
||||
$hide(terminalId: number): void;
|
||||
$sendText(terminalId: number, text: string, addNewLine: boolean): void;
|
||||
@@ -323,33 +335,56 @@ export interface MainThreadStatusBarShape extends IDisposable {
|
||||
|
||||
export interface MainThreadStorageShape extends IDisposable {
|
||||
$getValue<T>(shared: boolean, key: string): TPromise<T>;
|
||||
$setValue(shared: boolean, key: string, value: any): TPromise<any>;
|
||||
$setValue(shared: boolean, key: string, value: any): TPromise<void>;
|
||||
}
|
||||
|
||||
export interface MainThreadTelemetryShape extends IDisposable {
|
||||
$publicLog(eventName: string, data?: any): void;
|
||||
}
|
||||
|
||||
export type WebviewHandle = number;
|
||||
|
||||
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>;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
export interface MainThreadWorkspaceShape extends IDisposable {
|
||||
$startSearch(includePattern: string, includeFolder: string, excludePattern: string, maxResults: number, requestId: number): Thenable<URI[]>;
|
||||
$startSearch(includePattern: string, includeFolder: string, excludePatternOrDisregardExcludes: string | false, maxResults: number, requestId: number): Thenable<UriComponents[]>;
|
||||
$cancelSearch(requestId: number): Thenable<boolean>;
|
||||
$saveAll(includeUntitled?: boolean): Thenable<boolean>;
|
||||
$updateWorkspaceFolders(extensionName: string, index: number, deleteCount: number, workspaceFoldersToAdd: { uri: UriComponents, name?: string }[]): Thenable<void>;
|
||||
}
|
||||
|
||||
export interface IFileChangeDto {
|
||||
resource: UriComponents;
|
||||
type: FileChangeType;
|
||||
}
|
||||
|
||||
export interface MainThreadFileSystemShape extends IDisposable {
|
||||
$registerFileSystemProvider(handle: number, scheme: string): void;
|
||||
$unregisterFileSystemProvider(handle: number): void;
|
||||
|
||||
$onDidAddFileSystemRoot(root: URI): void;
|
||||
$onFileSystemChange(handle: number, resource: IFileChange[]): void;
|
||||
$reportFileChunk(handle: number, resource: URI, chunk: number[] | null): void;
|
||||
$onDidAddFileSystemRoot(root: UriComponents): void;
|
||||
$onFileSystemChange(handle: number, resource: IFileChangeDto[]): void;
|
||||
$reportFileChunk(handle: number, session: number, chunk: number[] | null): void;
|
||||
|
||||
$handleSearchProgress(handle: number, session: number, resource: URI): void;
|
||||
$handleFindMatch(handle: number, session, data: UriComponents | [UriComponents, ILineMatch]): void;
|
||||
}
|
||||
|
||||
export interface MainThreadTaskShape extends IDisposable {
|
||||
$registerTaskProvider(handle: number): TPromise<any>;
|
||||
$unregisterTaskProvider(handle: number): TPromise<any>;
|
||||
$registerTaskProvider(handle: number): TPromise<void>;
|
||||
$unregisterTaskProvider(handle: number): TPromise<void>;
|
||||
}
|
||||
|
||||
export interface MainThreadExtensionServiceShape extends IDisposable {
|
||||
@@ -374,7 +409,7 @@ export interface SCMGroupFeatures {
|
||||
|
||||
export type SCMRawResource = [
|
||||
number /*handle*/,
|
||||
string /*resourceUri*/,
|
||||
UriComponents /*resourceUri*/,
|
||||
string[] /*icons: light, dark*/,
|
||||
string /*tooltip*/,
|
||||
boolean /*strike through*/,
|
||||
@@ -397,7 +432,7 @@ export type SCMRawResourceSplices = [
|
||||
];
|
||||
|
||||
export interface MainThreadSCMShape extends IDisposable {
|
||||
$registerSourceControl(handle: number, id: string, label: string, rootUri: string | undefined): void;
|
||||
$registerSourceControl(handle: number, id: string, label: string, rootUri: UriComponents | undefined): void;
|
||||
$updateSourceControl(handle: number, features: SCMProviderFeatures): void;
|
||||
$unregisterSourceControl(handle: number): void;
|
||||
|
||||
@@ -410,6 +445,7 @@ export interface MainThreadSCMShape extends IDisposable {
|
||||
|
||||
$setInputBoxValue(sourceControlHandle: number, value: string): void;
|
||||
$setInputBoxPlaceholder(sourceControlHandle: number, placeholder: string): void;
|
||||
$setValidationProviderIsEnabled(sourceControlHandle: number, enabled: boolean): void;
|
||||
}
|
||||
|
||||
|
||||
@@ -418,12 +454,14 @@ export interface MainThreadSCMShape extends IDisposable {
|
||||
export type DebugSessionUUID = string;
|
||||
|
||||
export interface MainThreadDebugServiceShape extends IDisposable {
|
||||
$registerDebugConfigurationProvider(type: string, hasProvideMethod: boolean, hasResolveMethod: boolean, handle: number): TPromise<any>;
|
||||
$registerDebugConfigurationProvider(type: string, hasProvideMethod: boolean, hasResolveMethod: boolean, hasDebugAdapterExecutable: boolean, handle: number): TPromise<any>;
|
||||
$unregisterDebugConfigurationProvider(handle: number): TPromise<any>;
|
||||
$startDebugging(folder: URI | undefined, nameOrConfig: string | vscode.DebugConfiguration): TPromise<boolean>;
|
||||
$startDebugging(folder: UriComponents | undefined, nameOrConfig: string | vscode.DebugConfiguration): TPromise<boolean>;
|
||||
$customDebugAdapterRequest(id: DebugSessionUUID, command: string, args: any): TPromise<any>;
|
||||
$appendDebugConsole(value: string): TPromise<any>;
|
||||
$startBreakpointEvents(): TPromise<any>;
|
||||
$registerBreakpoints(breakpoints: (ISourceMultiBreakpointDto | IFunctionBreakpointDto)[]): TPromise<void>;
|
||||
$unregisterBreakpoints(breakpointIds: string[], functionBreakpointIds: string[]): TPromise<void>;
|
||||
}
|
||||
// {{SQL CARBON EDIT}}
|
||||
*/
|
||||
@@ -436,7 +474,7 @@ export interface MainThreadWindowShape extends IDisposable {
|
||||
|
||||
export interface ExtHostCommandsShape {
|
||||
$executeContributedCommand<T>(id: string, ...args: any[]): Thenable<T>;
|
||||
$getContributedCommandHandlerDescriptions(): TPromise<{ [id: string]: string | ICommandHandlerDescription }>;
|
||||
$getContributedCommandHandlerDescriptions(): Thenable<{ [id: string]: string | ICommandHandlerDescription }>;
|
||||
}
|
||||
|
||||
export interface ExtHostConfigurationShape {
|
||||
@@ -448,11 +486,11 @@ export interface ExtHostDiagnosticsShape {
|
||||
}
|
||||
|
||||
export interface ExtHostDocumentContentProvidersShape {
|
||||
$provideTextDocumentContent(handle: number, uri: URI): TPromise<string>;
|
||||
$provideTextDocumentContent(handle: number, uri: UriComponents): TPromise<string>;
|
||||
}
|
||||
|
||||
export interface IModelAddedData {
|
||||
url: URI;
|
||||
uri: UriComponents;
|
||||
versionId: number;
|
||||
lines: string[];
|
||||
EOL: string;
|
||||
@@ -460,34 +498,44 @@ export interface IModelAddedData {
|
||||
isDirty: boolean;
|
||||
}
|
||||
export interface ExtHostDocumentsShape {
|
||||
$acceptModelModeChanged(strURL: string, oldModeId: string, newModeId: string): void;
|
||||
$acceptModelSaved(strURL: string): void;
|
||||
$acceptDirtyStateChanged(strURL: string, isDirty: boolean): void;
|
||||
$acceptModelChanged(strURL: string, e: IModelChangedEvent, isDirty: boolean): void;
|
||||
$acceptModelModeChanged(strURL: UriComponents, oldModeId: string, newModeId: string): void;
|
||||
$acceptModelSaved(strURL: UriComponents): void;
|
||||
$acceptDirtyStateChanged(strURL: UriComponents, isDirty: boolean): void;
|
||||
$acceptModelChanged(strURL: UriComponents, e: IModelChangedEvent, isDirty: boolean): void;
|
||||
}
|
||||
|
||||
export interface ExtHostDocumentSaveParticipantShape {
|
||||
$participateInSave(resource: URI, reason: SaveReason): TPromise<boolean[]>;
|
||||
$participateInSave(resource: UriComponents, reason: SaveReason): Thenable<boolean[]>;
|
||||
}
|
||||
|
||||
export interface ITextEditorAddData {
|
||||
id: string;
|
||||
document: URI;
|
||||
documentUri: UriComponents;
|
||||
options: IResolvedTextEditorConfiguration;
|
||||
selections: ISelection[];
|
||||
visibleRanges: IRange[];
|
||||
editorPosition: EditorPosition;
|
||||
}
|
||||
export interface ITextEditorPositionData {
|
||||
[id: string]: EditorPosition;
|
||||
}
|
||||
export interface IEditorPropertiesChangeData {
|
||||
options: IResolvedTextEditorConfiguration | null;
|
||||
selections: ISelectionChangeEvent | null;
|
||||
visibleRanges: IRange[] | null;
|
||||
}
|
||||
export interface ISelectionChangeEvent {
|
||||
selections: Selection[];
|
||||
source?: string;
|
||||
}
|
||||
|
||||
export interface ExtHostEditorsShape {
|
||||
$acceptOptionsChanged(id: string, opts: IResolvedTextEditorConfiguration): void;
|
||||
$acceptSelectionsChanged(id: string, event: ISelectionChangeEvent): void;
|
||||
$acceptEditorPropertiesChanged(id: string, props: IEditorPropertiesChangeData): void;
|
||||
$acceptEditorPositionData(data: ITextEditorPositionData): void;
|
||||
}
|
||||
|
||||
export interface IDocumentsAndEditorsDelta {
|
||||
removedDocuments?: string[];
|
||||
removedDocuments?: UriComponents[];
|
||||
addedDocuments?: IModelAddedData[];
|
||||
removedEditors?: string[];
|
||||
addedEditors?: ITextEditorAddData[];
|
||||
@@ -499,8 +547,7 @@ export interface ExtHostDocumentsAndEditorsShape {
|
||||
}
|
||||
|
||||
export interface ExtHostTreeViewsShape {
|
||||
$getElements(treeViewId: string): TPromise<ITreeItem[]>;
|
||||
$getChildren(treeViewId: string, treeItemHandle: string): TPromise<ITreeItem[]>;
|
||||
$getChildren(treeViewId: string, treeItemHandle?: string): TPromise<ITreeItem[]>;
|
||||
}
|
||||
|
||||
export interface ExtHostWorkspaceShape {
|
||||
@@ -508,16 +555,17 @@ export interface ExtHostWorkspaceShape {
|
||||
}
|
||||
|
||||
export interface ExtHostFileSystemShape {
|
||||
$utimes(handle: number, resource: URI, mtime: number, atime: number): TPromise<IStat>;
|
||||
$stat(handle: number, resource: URI): TPromise<IStat>;
|
||||
$read(handle: number, offset: number, count: number, resource: URI): TPromise<number>;
|
||||
$write(handle: number, resource: URI, content: number[]): TPromise<void>;
|
||||
$unlink(handle: number, resource: URI): TPromise<void>;
|
||||
$move(handle: number, resource: URI, target: URI): TPromise<IStat>;
|
||||
$mkdir(handle: number, resource: URI): TPromise<IStat>;
|
||||
$readdir(handle: number, resource: URI): TPromise<[URI, IStat][]>;
|
||||
$rmdir(handle: number, resource: URI): TPromise<void>;
|
||||
$fileFiles(handle: number, session: number, query: string): TPromise<void>;
|
||||
$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>;
|
||||
$provideTextSearchResults(handle: number, session: number, pattern: IPatternInfo, options: { includes: string[], excludes: string[] }): TPromise<void>;
|
||||
}
|
||||
|
||||
export interface ExtHostExtensionServiceShape {
|
||||
@@ -525,9 +573,9 @@ export interface ExtHostExtensionServiceShape {
|
||||
}
|
||||
|
||||
export interface FileSystemEvents {
|
||||
created: URI[];
|
||||
changed: URI[];
|
||||
deleted: URI[];
|
||||
created: UriComponents[];
|
||||
changed: UriComponents[];
|
||||
deleted: UriComponents[];
|
||||
}
|
||||
export interface ExtHostFileSystemEventServiceShape {
|
||||
$onFileEvent(events: FileSystemEvents): void;
|
||||
@@ -556,58 +604,109 @@ export interface IRawColorInfo {
|
||||
range: IRange;
|
||||
}
|
||||
|
||||
export interface IExtHostSuggestion extends modes.ISuggestion {
|
||||
_id: number;
|
||||
_parentId: number;
|
||||
}
|
||||
|
||||
export interface IExtHostSuggestResult {
|
||||
_id: number;
|
||||
suggestions: IExtHostSuggestion[];
|
||||
incomplete?: boolean;
|
||||
}
|
||||
|
||||
export interface IdObject {
|
||||
_id: number;
|
||||
}
|
||||
|
||||
export namespace IdObject {
|
||||
let n = 0;
|
||||
export function mixin<T extends object>(object: T): T & IdObject {
|
||||
(<any>object)._id = n++;
|
||||
export class IdObject {
|
||||
_id?: number;
|
||||
private static _n = 0;
|
||||
static mixin<T extends object>(object: T): T & IdObject {
|
||||
(<any>object)._id = IdObject._n++;
|
||||
return <any>object;
|
||||
}
|
||||
}
|
||||
|
||||
export type IWorkspaceSymbol = IdObject & modes.SymbolInformation;
|
||||
export interface IWorkspaceSymbols extends IdObject { symbols: IWorkspaceSymbol[]; }
|
||||
export interface SuggestionDto extends modes.ISuggestion {
|
||||
_id: number;
|
||||
_parentId: number;
|
||||
}
|
||||
|
||||
export interface SuggestResultDto extends IdObject {
|
||||
suggestions: SuggestionDto[];
|
||||
incomplete?: boolean;
|
||||
}
|
||||
|
||||
export interface LocationDto {
|
||||
uri: UriComponents;
|
||||
range: IRange;
|
||||
}
|
||||
|
||||
export interface SymbolInformationDto extends IdObject {
|
||||
name: string;
|
||||
containerName?: string;
|
||||
kind: modes.SymbolKind;
|
||||
location: LocationDto;
|
||||
}
|
||||
|
||||
export interface WorkspaceSymbolsDto extends IdObject {
|
||||
symbols: SymbolInformationDto[];
|
||||
}
|
||||
|
||||
export interface ResourceFileEditDto {
|
||||
oldUri: UriComponents;
|
||||
newUri: UriComponents;
|
||||
}
|
||||
|
||||
export interface ResourceTextEditDto {
|
||||
resource: UriComponents;
|
||||
modelVersionId?: number;
|
||||
edits: modes.TextEdit[];
|
||||
}
|
||||
|
||||
export interface WorkspaceEditDto {
|
||||
edits: (ResourceFileEditDto | ResourceTextEditDto)[];
|
||||
|
||||
// todo@joh reject should go into rename
|
||||
rejectReason?: string;
|
||||
}
|
||||
|
||||
export function reviveWorkspaceEditDto(data: WorkspaceEditDto): modes.WorkspaceEdit {
|
||||
if (data && data.edits) {
|
||||
for (const edit of data.edits) {
|
||||
if (typeof (<ResourceTextEditDto>edit).resource === 'object') {
|
||||
(<ResourceTextEditDto>edit).resource = URI.revive((<ResourceTextEditDto>edit).resource);
|
||||
} else {
|
||||
(<ResourceFileEditDto>edit).newUri = URI.revive((<ResourceFileEditDto>edit).newUri);
|
||||
(<ResourceFileEditDto>edit).oldUri = URI.revive((<ResourceFileEditDto>edit).oldUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
return <modes.WorkspaceEdit>data;
|
||||
}
|
||||
|
||||
export interface CodeActionDto {
|
||||
title: string;
|
||||
edit?: WorkspaceEditDto;
|
||||
diagnostics?: IMarkerData[];
|
||||
command?: modes.Command;
|
||||
kind?: string;
|
||||
}
|
||||
|
||||
export interface ExtHostLanguageFeaturesShape {
|
||||
$provideDocumentSymbols(handle: number, resource: URI): TPromise<modes.SymbolInformation[]>;
|
||||
$provideCodeLenses(handle: number, resource: URI): TPromise<modes.ICodeLensSymbol[]>;
|
||||
$resolveCodeLens(handle: number, resource: URI, symbol: modes.ICodeLensSymbol): TPromise<modes.ICodeLensSymbol>;
|
||||
$provideDefinition(handle: number, resource: URI, position: IPosition): TPromise<modes.Definition>;
|
||||
$provideImplementation(handle: number, resource: URI, position: IPosition): TPromise<modes.Definition>;
|
||||
$provideTypeDefinition(handle: number, resource: URI, position: IPosition): TPromise<modes.Definition>;
|
||||
$provideHover(handle: number, resource: URI, position: IPosition): TPromise<modes.Hover>;
|
||||
$provideDocumentHighlights(handle: number, resource: URI, position: IPosition): TPromise<modes.DocumentHighlight[]>;
|
||||
$provideReferences(handle: number, resource: URI, position: IPosition, context: modes.ReferenceContext): TPromise<modes.Location[]>;
|
||||
$provideCodeActions(handle: number, resource: URI, range: IRange): TPromise<modes.CodeAction[]>;
|
||||
$provideDocumentFormattingEdits(handle: number, resource: URI, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]>;
|
||||
$provideDocumentRangeFormattingEdits(handle: number, resource: URI, range: IRange, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]>;
|
||||
$provideOnTypeFormattingEdits(handle: number, resource: URI, position: IPosition, ch: string, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]>;
|
||||
$provideWorkspaceSymbols(handle: number, search: string): TPromise<IWorkspaceSymbols>;
|
||||
$resolveWorkspaceSymbol(handle: number, symbol: modes.SymbolInformation): TPromise<IWorkspaceSymbol>;
|
||||
$provideDocumentSymbols(handle: number, resource: UriComponents): TPromise<SymbolInformationDto[]>;
|
||||
$provideCodeLenses(handle: number, resource: UriComponents): TPromise<modes.ICodeLensSymbol[]>;
|
||||
$resolveCodeLens(handle: number, resource: UriComponents, symbol: modes.ICodeLensSymbol): TPromise<modes.ICodeLensSymbol>;
|
||||
$provideDefinition(handle: number, resource: UriComponents, position: IPosition): TPromise<LocationDto | LocationDto[]>;
|
||||
$provideImplementation(handle: number, resource: UriComponents, position: IPosition): TPromise<LocationDto | LocationDto[]>;
|
||||
$provideTypeDefinition(handle: number, resource: UriComponents, position: IPosition): TPromise<LocationDto | LocationDto[]>;
|
||||
$provideHover(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.Hover>;
|
||||
$provideDocumentHighlights(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.DocumentHighlight[]>;
|
||||
$provideReferences(handle: number, resource: UriComponents, position: IPosition, context: modes.ReferenceContext): TPromise<LocationDto[]>;
|
||||
$provideCodeActions(handle: number, resource: UriComponents, range: IRange, context: modes.CodeActionContext): TPromise<CodeActionDto[]>;
|
||||
$provideDocumentFormattingEdits(handle: number, resource: UriComponents, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]>;
|
||||
$provideDocumentRangeFormattingEdits(handle: number, resource: UriComponents, range: IRange, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]>;
|
||||
$provideOnTypeFormattingEdits(handle: number, resource: UriComponents, position: IPosition, ch: string, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]>;
|
||||
$provideWorkspaceSymbols(handle: number, search: string): TPromise<WorkspaceSymbolsDto>;
|
||||
$resolveWorkspaceSymbol(handle: number, symbol: SymbolInformationDto): TPromise<SymbolInformationDto>;
|
||||
$releaseWorkspaceSymbols(handle: number, id: number): void;
|
||||
$provideRenameEdits(handle: number, resource: URI, position: IPosition, newName: string): TPromise<modes.WorkspaceEdit>;
|
||||
$provideCompletionItems(handle: number, resource: URI, position: IPosition, context: modes.SuggestContext): TPromise<IExtHostSuggestResult>;
|
||||
$resolveCompletionItem(handle: number, resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion>;
|
||||
$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string): TPromise<WorkspaceEditDto>;
|
||||
$resolveInitialRenameValue(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.RenameInitialValue>;
|
||||
$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;
|
||||
$provideSignatureHelp(handle: number, resource: URI, position: IPosition): TPromise<modes.SignatureHelp>;
|
||||
$provideDocumentLinks(handle: number, resource: URI): TPromise<modes.ILink[]>;
|
||||
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.SignatureHelp>;
|
||||
$provideDocumentLinks(handle: number, resource: UriComponents): TPromise<modes.ILink[]>;
|
||||
$resolveDocumentLink(handle: number, link: modes.ILink): TPromise<modes.ILink>;
|
||||
$provideDocumentColors(handle: number, resource: URI): TPromise<IRawColorInfo[]>;
|
||||
$provideColorPresentations(handle: number, resource: URI, colorInfo: IRawColorInfo): TPromise<modes.IColorPresentation[]>;
|
||||
$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>;
|
||||
}
|
||||
|
||||
export interface ExtHostQuickOpenShape {
|
||||
@@ -621,69 +720,95 @@ export interface ExtHostTerminalServiceShape {
|
||||
}
|
||||
|
||||
export interface ExtHostSCMShape {
|
||||
$provideOriginalResource(sourceControlHandle: number, uri: URI): TPromise<URI>;
|
||||
$provideOriginalResource(sourceControlHandle: number, uri: UriComponents): TPromise<UriComponents>;
|
||||
$onInputBoxValueChange(sourceControlHandle: number, value: string): TPromise<void>;
|
||||
$executeResourceCommand(sourceControlHandle: number, groupHandle: number, handle: number): TPromise<void>;
|
||||
$validateInput(sourceControlHandle: number, value: string, cursorPosition: number): TPromise<[string, number] | undefined>;
|
||||
}
|
||||
|
||||
export interface ExtHostTaskShape {
|
||||
$provideTasks(handle: number): TPromise<TaskSet>;
|
||||
}
|
||||
|
||||
export interface IBreakpointData {
|
||||
type: 'source' | 'function';
|
||||
id: string;
|
||||
export interface IFunctionBreakpointDto {
|
||||
type: 'function';
|
||||
id?: string;
|
||||
enabled: boolean;
|
||||
condition?: string;
|
||||
hitCondition?: string;
|
||||
functionName: string;
|
||||
}
|
||||
|
||||
export interface ISourceBreakpointData extends IBreakpointData {
|
||||
export interface ISourceBreakpointDto {
|
||||
type: 'source';
|
||||
uri: URI;
|
||||
id?: string;
|
||||
enabled: boolean;
|
||||
condition?: string;
|
||||
hitCondition?: string;
|
||||
uri: UriComponents;
|
||||
line: number;
|
||||
character: number;
|
||||
}
|
||||
|
||||
export interface IFunctionBreakpointData extends IBreakpointData {
|
||||
type: 'function';
|
||||
functionName: string;
|
||||
export interface IBreakpointsDeltaDto {
|
||||
added?: (ISourceBreakpointDto | IFunctionBreakpointDto)[];
|
||||
removed?: string[];
|
||||
changed?: (ISourceBreakpointDto | IFunctionBreakpointDto)[];
|
||||
}
|
||||
|
||||
export interface IBreakpointsDelta {
|
||||
added?: (ISourceBreakpointData | IFunctionBreakpointData)[];
|
||||
removed?: string[];
|
||||
changed?: (ISourceBreakpointData | IFunctionBreakpointData)[];
|
||||
export interface ISourceMultiBreakpointDto {
|
||||
type: 'sourceMulti';
|
||||
uri: UriComponents;
|
||||
lines: {
|
||||
id: string;
|
||||
enabled: boolean;
|
||||
condition?: string;
|
||||
hitCondition?: string;
|
||||
line: number;
|
||||
character: number;
|
||||
}[];
|
||||
}
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
/*
|
||||
export interface ExtHostDebugServiceShape {
|
||||
$resolveDebugConfiguration(handle: number, folder: URI | undefined, debugConfiguration: any): TPromise<any>;
|
||||
$provideDebugConfigurations(handle: number, folder: URI | undefined): TPromise<any[]>;
|
||||
$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>;
|
||||
$acceptDebugSessionStarted(id: DebugSessionUUID, type: string, name: string): void;
|
||||
$acceptDebugSessionTerminated(id: DebugSessionUUID, type: string, name: string): void;
|
||||
$acceptDebugSessionActiveChanged(id: DebugSessionUUID | undefined, type?: string, name?: string): void;
|
||||
$acceptDebugSessionCustomEvent(id: DebugSessionUUID, type: string, name: string, event: any): void;
|
||||
$acceptBreakpointsDelta(delat: IBreakpointsDelta): void;
|
||||
$acceptBreakpointsDelta(delat: IBreakpointsDeltaDto): void;
|
||||
}
|
||||
// {{SQL CARBON EDIT}}
|
||||
*/
|
||||
|
||||
export interface DecorationRequest {
|
||||
readonly id: number;
|
||||
readonly handle: number;
|
||||
readonly uri: UriComponents;
|
||||
}
|
||||
|
||||
export type DecorationData = [number, boolean, string, string, ThemeColor, string];
|
||||
export type DecorationReply = { [id: number]: DecorationData };
|
||||
|
||||
export interface ExtHostDecorationsShape {
|
||||
$providerDecorations(handle: number, uri: URI): TPromise<DecorationData>;
|
||||
$provideDecorations(requests: DecorationRequest[]): TPromise<DecorationReply>;
|
||||
}
|
||||
|
||||
export interface ExtHostWindowShape {
|
||||
$onDidChangeWindowFocus(value: boolean): void;
|
||||
}
|
||||
|
||||
export interface ExtHostLogServiceShape {
|
||||
$setLevel(level: LogLevel);
|
||||
}
|
||||
|
||||
// --- proxy identifiers
|
||||
|
||||
export const MainContext = {
|
||||
MainThreadCommands: createMainId<MainThreadCommandsShape>('MainThreadCommands'),
|
||||
MainThreadCommands: <ProxyIdentifier<MainThreadCommandsShape>>createMainId<MainThreadCommandsShape>('MainThreadCommands'),
|
||||
MainThreadConfiguration: createMainId<MainThreadConfigurationShape>('MainThreadConfiguration'),
|
||||
// {{SQL CARBON EDIT}}
|
||||
// MainThreadDebugService: createMainId<MainThreadDebugServiceShape>('MainThreadDebugService'),
|
||||
@@ -692,7 +817,7 @@ export const MainContext = {
|
||||
MainThreadDialogs: createMainId<MainThreadDiaglogsShape>('MainThreadDiaglogs'),
|
||||
MainThreadDocuments: createMainId<MainThreadDocumentsShape>('MainThreadDocuments'),
|
||||
MainThreadDocumentContentProviders: createMainId<MainThreadDocumentContentProvidersShape>('MainThreadDocumentContentProviders'),
|
||||
MainThreadEditors: createMainId<MainThreadEditorsShape>('MainThreadEditors'),
|
||||
MainThreadTextEditors: createMainId<MainThreadTextEditorsShape>('MainThreadTextEditors'),
|
||||
MainThreadErrors: createMainId<MainThreadErrorsShape>('MainThreadErrors'),
|
||||
MainThreadTreeViews: createMainId<MainThreadTreeViewsShape>('MainThreadTreeViews'),
|
||||
MainThreadLanguageFeatures: createMainId<MainThreadLanguageFeaturesShape>('MainThreadLanguageFeatures'),
|
||||
@@ -705,6 +830,7 @@ export const MainContext = {
|
||||
MainThreadStorage: createMainId<MainThreadStorageShape>('MainThreadStorage'),
|
||||
MainThreadTelemetry: createMainId<MainThreadTelemetryShape>('MainThreadTelemetry'),
|
||||
MainThreadTerminalService: createMainId<MainThreadTerminalServiceShape>('MainThreadTerminalService'),
|
||||
MainThreadWebviews: createMainId<MainThreadWebviewsShape>('MainThreadWebviews'),
|
||||
MainThreadWorkspace: createMainId<MainThreadWorkspaceShape>('MainThreadWorkspace'),
|
||||
MainThreadFileSystem: createMainId<MainThreadFileSystemShape>('MainThreadFileSystem'),
|
||||
MainThreadExtensionService: createMainId<MainThreadExtensionServiceShape>('MainThreadExtensionService'),
|
||||
@@ -732,9 +858,11 @@ export const ExtHostContext = {
|
||||
ExtHostLanguageFeatures: createExtId<ExtHostLanguageFeaturesShape>('ExtHostLanguageFeatures'),
|
||||
ExtHostQuickOpen: createExtId<ExtHostQuickOpenShape>('ExtHostQuickOpen'),
|
||||
ExtHostExtensionService: createExtId<ExtHostExtensionServiceShape>('ExtHostExtensionService'),
|
||||
ExtHostLogService: createExtId<ExtHostLogServiceShape>('ExtHostLogService'),
|
||||
ExtHostTerminalService: createExtId<ExtHostTerminalServiceShape>('ExtHostTerminalService'),
|
||||
ExtHostSCM: createExtId<ExtHostSCMShape>('ExtHostSCM'),
|
||||
ExtHostTask: createExtId<ExtHostTaskShape>('ExtHostTask'),
|
||||
ExtHostWorkspace: createExtId<ExtHostWorkspaceShape>('ExtHostWorkspace'),
|
||||
ExtHostWindow: createExtId<ExtHostWindowShape>('ExtHostWindow'),
|
||||
ExtHostWebviews: createExtId<ExtHostWebviewsShape>('ExtHostWebviews')
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ 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 { ISingleEditOperation } from 'vs/editor/common/editorCommon';
|
||||
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';
|
||||
@@ -189,10 +189,10 @@ export class ExtHostApiCommands {
|
||||
|
||||
return this._commands.executeCommand('_files.windowOpen', [uri.fsPath], forceNewWindow);
|
||||
}, {
|
||||
description: 'Open a folder 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 unless the newWindow parameter is set to true.',
|
||||
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 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 in a new window or the same. Defaults to opening in the same window.', constraint: value => value === void 0 || typeof value === 'boolean' }
|
||||
{ name: 'uri', description: '(optional) Uri of the folder or workspace file to open. If not provided, a native dialog will ask the user for the folder', constraint: value => 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' }
|
||||
]
|
||||
});
|
||||
|
||||
@@ -239,6 +239,15 @@ export class ExtHostApiCommands {
|
||||
{ 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' }
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
// --- command impl
|
||||
@@ -344,11 +353,7 @@ export class ExtHostApiCommands {
|
||||
if (value.rejectReason) {
|
||||
return TPromise.wrapError<types.WorkspaceEdit>(new Error(value.rejectReason));
|
||||
}
|
||||
let workspaceEdit = new types.WorkspaceEdit();
|
||||
for (let edit of value.edits) {
|
||||
workspaceEdit.replace(edit.resource, typeConverters.toRange(edit.range), edit.newText);
|
||||
}
|
||||
return workspaceEdit;
|
||||
return typeConverters.WorkspaceEdit.to(value);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -409,8 +414,14 @@ export class ExtHostApiCommands {
|
||||
} else {
|
||||
const ret = new types.CodeAction(
|
||||
codeAction.title,
|
||||
typeConverters.WorkspaceEdit.to(codeAction.edits)
|
||||
codeAction.kind ? new types.CodeActionKind(codeAction.kind) : undefined
|
||||
);
|
||||
if (codeAction.edit) {
|
||||
ret.edit = typeConverters.WorkspaceEdit.to(codeAction.edit);
|
||||
}
|
||||
if (codeAction.command) {
|
||||
ret.command = this._commands.converter.fromInternal(codeAction.command);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
import { validateConstraint } from 'vs/base/common/types';
|
||||
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import * as extHostTypes from 'vs/workbench/api/node/extHostTypes';
|
||||
import * as extHostTypeConverter from 'vs/workbench/api/node/extHostTypeConverters';
|
||||
import { cloneAndChange } from 'vs/base/common/objects';
|
||||
@@ -16,6 +15,7 @@ import { isFalsyOrEmpty } from 'vs/base/common/arrays';
|
||||
import * as modes from 'vs/editor/common/modes';
|
||||
import * as vscode from 'vscode';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { revive } from 'vs/base/common/marshalling';
|
||||
|
||||
interface CommandHandler {
|
||||
callback: Function;
|
||||
@@ -29,18 +29,21 @@ export interface ArgumentProcessor {
|
||||
|
||||
export class ExtHostCommands implements ExtHostCommandsShape {
|
||||
|
||||
private _commands = new Map<string, CommandHandler>();
|
||||
private _proxy: MainThreadCommandsShape;
|
||||
private _converter: CommandsConverter;
|
||||
private _argumentProcessors: ArgumentProcessor[] = [];
|
||||
private readonly _commands = new Map<string, CommandHandler>();
|
||||
private readonly _proxy: MainThreadCommandsShape;
|
||||
private readonly _converter: CommandsConverter;
|
||||
private readonly _logService: ILogService;
|
||||
private readonly _argumentProcessors: ArgumentProcessor[];
|
||||
|
||||
constructor(
|
||||
mainContext: IMainContext,
|
||||
heapService: ExtHostHeapService,
|
||||
private logService: ILogService
|
||||
logService: ILogService
|
||||
) {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadCommands);
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadCommands);
|
||||
this._logService = logService;
|
||||
this._converter = new CommandsConverter(this, heapService);
|
||||
this._argumentProcessors = [{ processArgument(a) { return revive(a, 0); } }];
|
||||
}
|
||||
|
||||
get converter(): CommandsConverter {
|
||||
@@ -52,7 +55,7 @@ export class ExtHostCommands implements ExtHostCommandsShape {
|
||||
}
|
||||
|
||||
registerCommand(id: string, callback: <T>(...args: any[]) => T | Thenable<T>, thisArg?: any, description?: ICommandHandlerDescription): extHostTypes.Disposable {
|
||||
this.logService.trace('ExtHostCommands#registerCommand', id);
|
||||
this._logService.trace('ExtHostCommands#registerCommand', id);
|
||||
|
||||
if (!id.trim().length) {
|
||||
throw new Error('invalid id');
|
||||
@@ -73,12 +76,12 @@ export class ExtHostCommands implements ExtHostCommandsShape {
|
||||
}
|
||||
|
||||
executeCommand<T>(id: string, ...args: any[]): Thenable<T> {
|
||||
this.logService.trace('ExtHostCommands#executeCommand', id);
|
||||
this._logService.trace('ExtHostCommands#executeCommand', id);
|
||||
|
||||
if (this._commands.has(id)) {
|
||||
// we stay inside the extension host and support
|
||||
// to pass any kind of parameters around
|
||||
return this.$executeContributedCommand<T>(id, ...args);
|
||||
return this._executeContributedCommand<T>(id, args);
|
||||
|
||||
} else {
|
||||
// automagically convert some argument types
|
||||
@@ -98,47 +101,42 @@ export class ExtHostCommands implements ExtHostCommandsShape {
|
||||
}
|
||||
});
|
||||
|
||||
return this._proxy.$executeCommand<T>(id, args);
|
||||
return this._proxy.$executeCommand<T>(id, args).then(result => revive(result, 0));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$executeContributedCommand<T>(id: string, ...args: any[]): Thenable<T> {
|
||||
let command = this._commands.get(id);
|
||||
if (!command) {
|
||||
return TPromise.wrapError<T>(new Error(`Contributed command '${id}' does not exist.`));
|
||||
}
|
||||
|
||||
let { callback, thisArg, description } = command;
|
||||
|
||||
private _executeContributedCommand<T>(id: string, args: any[]): Thenable<T> {
|
||||
let { callback, thisArg, description } = this._commands.get(id);
|
||||
if (description) {
|
||||
for (let i = 0; i < description.args.length; i++) {
|
||||
try {
|
||||
validateConstraint(args[i], description.args[i].constraint);
|
||||
} catch (err) {
|
||||
return TPromise.wrapError<T>(new Error(`Running the contributed command:'${id}' failed. Illegal argument '${description.args[i].name}' - ${description.args[i].description}`));
|
||||
return <any>Promise.reject(new Error(`Running the contributed command:'${id}' failed. Illegal argument '${description.args[i].name}' - ${description.args[i].description}`));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
args = args.map(arg => this._argumentProcessors.reduce((r, p) => p.processArgument(r), arg));
|
||||
|
||||
try {
|
||||
let result = callback.apply(thisArg, args);
|
||||
return TPromise.as(result);
|
||||
return Promise.resolve(result);
|
||||
} catch (err) {
|
||||
// console.log(err);
|
||||
// try {
|
||||
// console.log(toErrorMessage(err));
|
||||
// } catch (err) {
|
||||
// //
|
||||
// }
|
||||
return TPromise.wrapError<T>(new Error(`Running the contributed command:'${id}' failed.`));
|
||||
this._logService.error(err, id);
|
||||
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)) {
|
||||
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));
|
||||
return this._executeContributedCommand(id, args);
|
||||
}
|
||||
}
|
||||
|
||||
getCommands(filterUnderscoreCommands: boolean = false): Thenable<string[]> {
|
||||
this.logService.trace('ExtHostCommands#getCommands', filterUnderscoreCommands);
|
||||
this._logService.trace('ExtHostCommands#getCommands', filterUnderscoreCommands);
|
||||
|
||||
return this._proxy.$getCommands().then(result => {
|
||||
if (filterUnderscoreCommands) {
|
||||
@@ -148,7 +146,7 @@ export class ExtHostCommands implements ExtHostCommandsShape {
|
||||
});
|
||||
}
|
||||
|
||||
$getContributedCommandHandlerDescriptions(): TPromise<{ [id: string]: string | ICommandHandlerDescription }> {
|
||||
$getContributedCommandHandlerDescriptions(): Thenable<{ [id: string]: string | ICommandHandlerDescription }> {
|
||||
const result: { [id: string]: string | ICommandHandlerDescription } = Object.create(null);
|
||||
this._commands.forEach((command, id) => {
|
||||
let { description } = command;
|
||||
@@ -156,7 +154,7 @@ export class ExtHostCommands implements ExtHostCommandsShape {
|
||||
result[id] = description;
|
||||
}
|
||||
});
|
||||
return TPromise.as(result);
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,14 +41,14 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
|
||||
private readonly _onDidChangeConfiguration = new Emitter<vscode.ConfigurationChangeEvent>();
|
||||
private readonly _proxy: MainThreadConfigurationShape;
|
||||
private readonly _extHostWorkspace: ExtHostWorkspace;
|
||||
private _configurationScopes: Map<string, ConfigurationScope>;
|
||||
private _configurationScopes: { [key: string]: ConfigurationScope };
|
||||
private _configuration: Configuration;
|
||||
|
||||
constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspace, data: IConfigurationInitData) {
|
||||
this._proxy = proxy;
|
||||
this._extHostWorkspace = extHostWorkspace;
|
||||
this._configuration = Configuration.parse(data);
|
||||
this._readConfigurationScopes(data.configurationScopes);
|
||||
this._configurationScopes = data.configurationScopes;
|
||||
}
|
||||
|
||||
get onDidChangeConfiguration(): Event<vscode.ConfigurationChangeEvent> {
|
||||
@@ -129,7 +129,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
|
||||
}
|
||||
|
||||
private _validateConfigurationAccess(key: string, resource: URI, extensionId: string): void {
|
||||
const scope = this._configurationScopes.get(key);
|
||||
const scope = this._configurationScopes[key];
|
||||
const extensionIdText = extensionId ? `[${extensionId}] ` : '';
|
||||
if (ConfigurationScope.RESOURCE === scope) {
|
||||
if (resource === void 0) {
|
||||
@@ -145,18 +145,6 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
|
||||
}
|
||||
}
|
||||
|
||||
private _readConfigurationScopes(scopes: ConfigurationScope[]): void {
|
||||
this._configurationScopes = new Map<string, ConfigurationScope>();
|
||||
if (scopes.length) {
|
||||
const defaultKeys = this._configuration.keys(this._extHostWorkspace.workspace).default;
|
||||
if (defaultKeys.length === scopes.length) {
|
||||
for (let i = 0; i < defaultKeys.length; i++) {
|
||||
this._configurationScopes.set(defaultKeys[i], scopes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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>();
|
||||
|
||||
@@ -9,12 +9,16 @@
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { asWinJsPromise } from 'vs/base/common/async';
|
||||
import { MainContext, MainThreadDebugServiceShape, ExtHostDebugServiceShape, DebugSessionUUID, IMainContext, IBreakpointsDelta, ISourceBreakpointData, IFunctionBreakpointData } from 'vs/workbench/api/node/extHost.protocol';
|
||||
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 from 'vs/base/common/uri';
|
||||
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';
|
||||
|
||||
|
||||
export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
@@ -63,7 +67,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
this._onDidChangeActiveDebugSession = new Emitter<vscode.DebugSession>();
|
||||
this._onDidReceiveDebugSessionCustomEvent = new Emitter<vscode.DebugSessionCustomEvent>();
|
||||
|
||||
this._debugServiceProxy = mainContext.get(MainContext.MainThreadDebugService);
|
||||
this._debugServiceProxy = mainContext.getProxy(MainContext.MainThreadDebugService);
|
||||
|
||||
this._onDidChangeBreakpoints = new Emitter<vscode.BreakpointsChangeEvent>({
|
||||
onFirstListenerAdd: () => {
|
||||
@@ -97,50 +101,161 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
return result;
|
||||
}
|
||||
|
||||
public $acceptBreakpointsDelta(delta: IBreakpointsDelta): void {
|
||||
public $acceptBreakpointsDelta(delta: IBreakpointsDeltaDto): void {
|
||||
|
||||
let a: vscode.Breakpoint[] = [];
|
||||
let r: vscode.Breakpoint[] = [];
|
||||
let c: vscode.Breakpoint[] = [];
|
||||
|
||||
if (delta.added) {
|
||||
a = delta.added.map(bpd => {
|
||||
const bp = this.fromWire(bpd);
|
||||
this._breakpoints.set(bpd.id, bp);
|
||||
return bp;
|
||||
});
|
||||
for (const bpd of delta.added) {
|
||||
|
||||
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);
|
||||
} 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['_id'] = bpd.id;
|
||||
this._breakpoints.set(bpd.id, bp);
|
||||
a.push(bp);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (delta.removed) {
|
||||
r = delta.removed.map(id => {
|
||||
for (const id of delta.removed) {
|
||||
const bp = this._breakpoints.get(id);
|
||||
if (bp) {
|
||||
this._breakpoints.delete(id);
|
||||
r.push(bp);
|
||||
}
|
||||
return bp;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (delta.changed) {
|
||||
c = delta.changed.map(bpd => {
|
||||
const bp = this.fromWire(bpd);
|
||||
this._breakpoints.set(bpd.id, bp);
|
||||
return bp;
|
||||
});
|
||||
for (const bpd of delta.changed) {
|
||||
let bp = this._breakpoints.get(bpd.id);
|
||||
if (bp) {
|
||||
if (bpd.type === 'function') {
|
||||
const fbp = <any>bp;
|
||||
fbp.enabled = bpd.enabled;
|
||||
fbp.condition = bpd.condition;
|
||||
fbp.hitCondition = bpd.hitCondition;
|
||||
fbp.functionName = bpd.functionName;
|
||||
} else {
|
||||
const sbp = <any>bp;
|
||||
sbp.enabled = bpd.enabled;
|
||||
sbp.condition = bpd.condition;
|
||||
sbp.hitCondition = bpd.hitCondition;
|
||||
}
|
||||
c.push(bp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this._onDidChangeBreakpoints.fire(Object.freeze({
|
||||
added: Object.freeze<vscode.Breakpoint[]>(a || []),
|
||||
removed: Object.freeze<vscode.Breakpoint[]>(r || []),
|
||||
changed: Object.freeze<vscode.Breakpoint[]>(c || [])
|
||||
}));
|
||||
this.fireBreakpointChanges(a, r, c);
|
||||
}
|
||||
|
||||
private fromWire(bp: ISourceBreakpointData | IFunctionBreakpointData): vscode.Breakpoint {
|
||||
if (bp.type === 'function') {
|
||||
return new FunctionBreakpoint(bp.enabled, bp.condition, bp.hitCondition, bp.functionName);
|
||||
public addBreakpoints(breakpoints0: vscode.Breakpoint[]): TPromise<void> {
|
||||
|
||||
this.startBreakpoints();
|
||||
|
||||
// assign uuids for brand new breakpoints
|
||||
const breakpoints: vscode.Breakpoint[] = [];
|
||||
for (const bp of breakpoints0) {
|
||||
let id = bp['_id'];
|
||||
if (id) { // has already id
|
||||
if (this._breakpoints.has(id)) {
|
||||
// already there
|
||||
} else {
|
||||
breakpoints.push(bp);
|
||||
}
|
||||
} else {
|
||||
id = generateUuid();
|
||||
bp['_id'] = id;
|
||||
this._breakpoints.set(id, bp);
|
||||
breakpoints.push(bp);
|
||||
}
|
||||
}
|
||||
|
||||
// send notification for added breakpoints
|
||||
this.fireBreakpointChanges(breakpoints, [], []);
|
||||
|
||||
// convert added breakpoints to DTOs
|
||||
const dtos: (ISourceMultiBreakpointDto | IFunctionBreakpointDto)[] = [];
|
||||
const map = new Map<string, ISourceMultiBreakpointDto>();
|
||||
for (const bp of breakpoints) {
|
||||
if (bp instanceof SourceBreakpoint) {
|
||||
let dto = map.get(bp.location.uri.toString());
|
||||
if (!dto) {
|
||||
dto = <ISourceMultiBreakpointDto>{
|
||||
type: 'sourceMulti',
|
||||
uri: bp.location.uri,
|
||||
lines: []
|
||||
};
|
||||
map.set(bp.location.uri.toString(), dto);
|
||||
dtos.push(dto);
|
||||
}
|
||||
dto.lines.push({
|
||||
id: bp['_id'],
|
||||
enabled: bp.enabled,
|
||||
condition: bp.condition,
|
||||
hitCondition: bp.hitCondition,
|
||||
line: bp.location.range.start.line,
|
||||
character: bp.location.range.start.character
|
||||
});
|
||||
} else if (bp instanceof FunctionBreakpoint) {
|
||||
dtos.push({
|
||||
type: 'function',
|
||||
id: bp['_id'],
|
||||
enabled: bp.enabled,
|
||||
functionName: bp.functionName,
|
||||
hitCondition: bp.hitCondition,
|
||||
condition: bp.condition
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// send DTOs to VS Code
|
||||
return this._debugServiceProxy.$registerBreakpoints(dtos);
|
||||
}
|
||||
|
||||
public removeBreakpoints(breakpoints0: vscode.Breakpoint[]): TPromise<void> {
|
||||
|
||||
this.startBreakpoints();
|
||||
|
||||
// remove from array
|
||||
const breakpoints: vscode.Breakpoint[] = [];
|
||||
for (const b of breakpoints0) {
|
||||
let id = b['_id'];
|
||||
if (id && this._breakpoints.delete(id)) {
|
||||
breakpoints.push(b);
|
||||
}
|
||||
}
|
||||
|
||||
// send notification
|
||||
this.fireBreakpointChanges([], breakpoints, []);
|
||||
|
||||
// unregister with VS Code
|
||||
const ids = breakpoints.filter(bp => bp instanceof SourceBreakpoint).map(bp => bp['_id']);
|
||||
const fids = breakpoints.filter(bp => bp instanceof FunctionBreakpoint).map(bp => bp['_id']);
|
||||
return this._debugServiceProxy.$unregisterBreakpoints(ids, fids);
|
||||
}
|
||||
|
||||
private fireBreakpointChanges(added: vscode.Breakpoint[], removed: vscode.Breakpoint[], changed: vscode.Breakpoint[]) {
|
||||
if (added.length > 0 || removed.length > 0 || changed.length > 0) {
|
||||
this._onDidChangeBreakpoints.fire(Object.freeze({
|
||||
added: Object.freeze<vscode.Breakpoint[]>(added),
|
||||
removed: Object.freeze<vscode.Breakpoint[]>(removed),
|
||||
changed: Object.freeze<vscode.Breakpoint[]>(changed)
|
||||
}));
|
||||
}
|
||||
return new SourceBreakpoint(bp.enabled, bp.condition, bp.hitCondition, new Location(bp.uri, new Position(bp.line, bp.character)));
|
||||
}
|
||||
|
||||
public registerDebugConfigurationProvider(type: string, provider: vscode.DebugConfigurationProvider): vscode.Disposable {
|
||||
@@ -150,7 +265,10 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
|
||||
let handle = this.nextHandle();
|
||||
this._handlers.set(handle, provider);
|
||||
this._debugServiceProxy.$registerDebugConfigurationProvider(type, !!provider.provideDebugConfigurations, !!provider.resolveDebugConfiguration, handle);
|
||||
this._debugServiceProxy.$registerDebugConfigurationProvider(type,
|
||||
!!provider.provideDebugConfigurations,
|
||||
!!provider.resolveDebugConfiguration,
|
||||
!!provider.debugAdapterExecutable, handle);
|
||||
|
||||
return new Disposable(() => {
|
||||
this._handlers.delete(handle);
|
||||
@@ -158,7 +276,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
});
|
||||
}
|
||||
|
||||
public $provideDebugConfigurations(handle: number, folderUri: URI | undefined): TPromise<vscode.DebugConfiguration[]> {
|
||||
public $provideDebugConfigurations(handle: number, folderUri: UriComponents | undefined): TPromise<vscode.DebugConfiguration[]> {
|
||||
let handler = this._handlers.get(handle);
|
||||
if (!handler) {
|
||||
return TPromise.wrapError<vscode.DebugConfiguration[]>(new Error('no handler found'));
|
||||
@@ -169,7 +287,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
return asWinJsPromise(token => handler.provideDebugConfigurations(this.getFolder(folderUri), token));
|
||||
}
|
||||
|
||||
public $resolveDebugConfiguration(handle: number, folderUri: URI | undefined, debugConfiguration: vscode.DebugConfiguration): TPromise<vscode.DebugConfiguration> {
|
||||
public $resolveDebugConfiguration(handle: number, folderUri: UriComponents | undefined, debugConfiguration: vscode.DebugConfiguration): TPromise<vscode.DebugConfiguration> {
|
||||
let handler = this._handlers.get(handle);
|
||||
if (!handler) {
|
||||
return TPromise.wrapError<vscode.DebugConfiguration>(new Error('no handler found'));
|
||||
@@ -180,6 +298,17 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
return asWinJsPromise(token => handler.resolveDebugConfiguration(this.getFolder(folderUri), debugConfiguration, token));
|
||||
}
|
||||
|
||||
public $debugAdapterExecutable(handle: number, folderUri: UriComponents | undefined): TPromise<vscode.DebugAdapterExecutable> {
|
||||
let handler = this._handlers.get(handle);
|
||||
if (!handler) {
|
||||
return TPromise.wrapError<vscode.DebugAdapterExecutable>(new Error('no handler found'));
|
||||
}
|
||||
if (!handler.debugAdapterExecutable) {
|
||||
return TPromise.wrapError<vscode.DebugAdapterExecutable>(new Error('handler has no method debugAdapterExecutable'));
|
||||
}
|
||||
return asWinJsPromise(token => handler.debugAdapterExecutable(this.getFolder(folderUri), token));
|
||||
}
|
||||
|
||||
public startDebugging(folder: vscode.WorkspaceFolder | undefined, nameOrConfig: string | vscode.DebugConfiguration): TPromise<boolean> {
|
||||
return this._debugServiceProxy.$startDebugging(folder ? folder.uri : undefined, nameOrConfig);
|
||||
}
|
||||
@@ -234,10 +363,11 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
|
||||
this._onDidReceiveDebugSessionCustomEvent.fire(ee);
|
||||
}
|
||||
|
||||
private getFolder(folderUri: URI | undefined) {
|
||||
if (folderUri) {
|
||||
private getFolder(_folderUri: UriComponents | undefined) {
|
||||
if (_folderUri) {
|
||||
const folderUriString = URI.revive(_folderUri).toString();
|
||||
const folders = this._workspace.getWorkspaceFolders();
|
||||
const found = folders.filter(f => f.uri.toString() === folderUri.toString());
|
||||
const found = folders.filter(f => f.uri.toString() === folderUriString);
|
||||
if (found && found.length > 0) {
|
||||
return found[0];
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { MainContext, IMainContext, ExtHostDecorationsShape, MainThreadDecorationsShape, DecorationData } from 'vs/workbench/api/node/extHost.protocol';
|
||||
import { MainContext, IMainContext, ExtHostDecorationsShape, MainThreadDecorationsShape, DecorationData, DecorationRequest, DecorationReply } from 'vs/workbench/api/node/extHost.protocol';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { Disposable } from 'vs/workbench/api/node/extHostTypes';
|
||||
import { asWinJsPromise } from 'vs/base/common/async';
|
||||
@@ -19,7 +19,7 @@ export class ExtHostDecorations implements ExtHostDecorationsShape {
|
||||
private readonly _proxy: MainThreadDecorationsShape;
|
||||
|
||||
constructor(mainContext: IMainContext) {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadDecorations);
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadDecorations);
|
||||
}
|
||||
|
||||
registerDecorationProvider(provider: vscode.DecorationProvider, label: string): vscode.Disposable {
|
||||
@@ -38,10 +38,19 @@ export class ExtHostDecorations implements ExtHostDecorationsShape {
|
||||
});
|
||||
}
|
||||
|
||||
$providerDecorations(handle: number, uri: URI): TPromise<DecorationData> {
|
||||
const provider = this._provider.get(handle);
|
||||
return asWinJsPromise(token => provider.provideDecoration(uri, token)).then(data => {
|
||||
return data && <DecorationData>[data.priority, data.bubble, data.title, data.abbreviation, data.color, data.source];
|
||||
$provideDecorations(requests: DecorationRequest[]): TPromise<DecorationReply> {
|
||||
const result: DecorationReply = Object.create(null);
|
||||
return TPromise.join(requests.map(request => {
|
||||
const { handle, uri, id } = request;
|
||||
const provider = this._provider.get(handle);
|
||||
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 => {
|
||||
console.error(err);
|
||||
});
|
||||
|
||||
})).then(() => {
|
||||
return result;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
|
||||
private _collections: DiagnosticCollection[];
|
||||
|
||||
constructor(mainContext: IMainContext) {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadDiagnostics);
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadDiagnostics);
|
||||
this._collections = [];
|
||||
}
|
||||
|
||||
@@ -255,4 +255,3 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
|
||||
this._collections.forEach(callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ export class ExtHostDialogs {
|
||||
private readonly _proxy: MainThreadDiaglogsShape;
|
||||
|
||||
constructor(mainContext: IMainContext) {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadDialogs);
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadDialogs);
|
||||
}
|
||||
|
||||
showOpenDialog(options: vscode.OpenDialogOptions): Thenable<URI[]> {
|
||||
|
||||
@@ -5,16 +5,15 @@
|
||||
'use strict';
|
||||
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import * as editorCommon from 'vs/editor/common/editorCommon';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import URI, { UriComponents } from 'vs/base/common/uri';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable } from 'vs/workbench/api/node/extHostTypes';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import * as vscode from 'vscode';
|
||||
import { asWinJsPromise } from 'vs/base/common/async';
|
||||
import { TextSource } from 'vs/editor/common/model/textSource';
|
||||
import { MainContext, ExtHostDocumentContentProvidersShape, MainThreadDocumentContentProvidersShape, IMainContext } from './extHost.protocol';
|
||||
import { ExtHostDocumentsAndEditors } from './extHostDocumentsAndEditors';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
|
||||
export class ExtHostDocumentContentProvider implements ExtHostDocumentContentProvidersShape {
|
||||
|
||||
@@ -25,7 +24,7 @@ export class ExtHostDocumentContentProvider implements ExtHostDocumentContentPro
|
||||
private readonly _documentsAndEditors: ExtHostDocumentsAndEditors;
|
||||
|
||||
constructor(mainContext: IMainContext, documentsAndEditors: ExtHostDocumentsAndEditors) {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadDocumentContentProviders);
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadDocumentContentProviders);
|
||||
this._documentsAndEditors = documentsAndEditors;
|
||||
}
|
||||
|
||||
@@ -34,7 +33,9 @@ export class ExtHostDocumentContentProvider implements ExtHostDocumentContentPro
|
||||
}
|
||||
|
||||
registerTextDocumentContentProvider(scheme: string, provider: vscode.TextDocumentContentProvider): vscode.Disposable {
|
||||
if (scheme === 'file' || scheme === 'untitled') {
|
||||
// todo@remote
|
||||
// check with scheme from fs-providers!
|
||||
if (scheme === Schemas.file || scheme === Schemas.untitled) {
|
||||
throw new Error(`scheme '${scheme}' already registered`);
|
||||
}
|
||||
|
||||
@@ -56,11 +57,11 @@ export class ExtHostDocumentContentProvider implements ExtHostDocumentContentPro
|
||||
}
|
||||
|
||||
// create lines and compare
|
||||
const textSource = TextSource.fromString(value, editorCommon.DefaultEndOfLine.CRLF);
|
||||
const lines = value.split(/\r\n|\r|\n/);
|
||||
|
||||
// broadcast event when content changed
|
||||
if (!document.equalLines(textSource)) {
|
||||
return this._proxy.$onVirtualDocumentChange(uri, textSource);
|
||||
if (!document.equalLines(lines)) {
|
||||
return this._proxy.$onVirtualDocumentChange(uri, value);
|
||||
}
|
||||
|
||||
}, onUnexpectedError);
|
||||
@@ -78,11 +79,11 @@ export class ExtHostDocumentContentProvider implements ExtHostDocumentContentPro
|
||||
});
|
||||
}
|
||||
|
||||
$provideTextDocumentContent(handle: number, uri: URI): TPromise<string> {
|
||||
$provideTextDocumentContent(handle: number, uri: UriComponents): TPromise<string> {
|
||||
const provider = this._documentContentProviders.get(handle);
|
||||
if (!provider) {
|
||||
return TPromise.wrapError<string>(new Error(`unsupported uri-scheme: ${uri.scheme}`));
|
||||
}
|
||||
return asWinJsPromise(token => provider.provideTextDocumentContent(uri, token));
|
||||
return asWinJsPromise(token => provider.provideTextDocumentContent(URI.revive(uri), token));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,13 +6,12 @@
|
||||
|
||||
import { ok } from 'vs/base/common/assert';
|
||||
import { regExpLeadsToEndlessLoop } from 'vs/base/common/strings';
|
||||
import { MirrorModel } from 'vs/editor/common/model/mirrorModel';
|
||||
import { MirrorTextModel } from 'vs/editor/common/model/mirrorTextModel';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { Range, Position, EndOfLine } from 'vs/workbench/api/node/extHostTypes';
|
||||
import * as vscode from 'vscode';
|
||||
import { getWordAtText, ensureValidWordDefinition } from 'vs/editor/common/model/wordHelper';
|
||||
import { MainThreadDocumentsShape } from './extHost.protocol';
|
||||
import { ITextSource } from 'vs/editor/common/model/textSource';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
|
||||
const _modeId2WordDefinition = new Map<string, RegExp>();
|
||||
@@ -23,7 +22,7 @@ export function getWordDefinitionFor(modeId: string): RegExp {
|
||||
return _modeId2WordDefinition.get(modeId);
|
||||
}
|
||||
|
||||
export class ExtHostDocumentData extends MirrorModel {
|
||||
export class ExtHostDocumentData extends MirrorTextModel {
|
||||
|
||||
private _proxy: MainThreadDocumentsShape;
|
||||
private _languageId: string;
|
||||
@@ -50,7 +49,7 @@ export class ExtHostDocumentData extends MirrorModel {
|
||||
this._isDirty = false;
|
||||
}
|
||||
|
||||
equalLines({ lines }: ITextSource): boolean {
|
||||
equalLines(lines: string[]): boolean {
|
||||
const len = lines.length;
|
||||
if (len !== this._lines.length) {
|
||||
return false;
|
||||
@@ -69,6 +68,8 @@ export class ExtHostDocumentData extends MirrorModel {
|
||||
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 languageId() { return data._languageId; },
|
||||
get version() { return data._versionId; },
|
||||
|
||||
@@ -5,39 +5,42 @@
|
||||
'use strict';
|
||||
|
||||
import Event from 'vs/base/common/event';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import URI, { UriComponents } from 'vs/base/common/uri';
|
||||
import { sequence, always } from 'vs/base/common/async';
|
||||
import { illegalState } from 'vs/base/common/errors';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { ExtHostDocumentSaveParticipantShape, MainThreadEditorsShape, IWorkspaceResourceEdit } from 'vs/workbench/api/node/extHost.protocol';
|
||||
import { ExtHostDocumentSaveParticipantShape, MainThreadTextEditorsShape, ResourceTextEditDto } from 'vs/workbench/api/node/extHost.protocol';
|
||||
import { TextEdit } from 'vs/workbench/api/node/extHostTypes';
|
||||
import { fromRange, TextDocumentSaveReason, EndOfLine } from 'vs/workbench/api/node/extHostTypeConverters';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
|
||||
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import * as vscode from 'vscode';
|
||||
import { LinkedList } from 'vs/base/common/linkedList';
|
||||
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
||||
type Listener = [Function, any, IExtensionDescription];
|
||||
|
||||
export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSaveParticipantShape {
|
||||
|
||||
private _documents: ExtHostDocuments;
|
||||
private _mainThreadEditors: MainThreadEditorsShape;
|
||||
private _callbacks = new LinkedList<[Function, any]>();
|
||||
private _badListeners = new WeakMap<Function, number>();
|
||||
private _thresholds: { timeout: number; errors: number; };
|
||||
private readonly _callbacks = new LinkedList<Listener>();
|
||||
private readonly _badListeners = new WeakMap<Function, number>();
|
||||
|
||||
constructor(documents: ExtHostDocuments, mainThreadEditors: MainThreadEditorsShape, thresholds: { timeout: number; errors: number; } = { timeout: 1500, errors: 3 }) {
|
||||
this._documents = documents;
|
||||
this._mainThreadEditors = mainThreadEditors;
|
||||
this._thresholds = thresholds;
|
||||
constructor(
|
||||
private readonly _logService: ILogService,
|
||||
private readonly _documents: ExtHostDocuments,
|
||||
private readonly _mainThreadEditors: MainThreadTextEditorsShape,
|
||||
private readonly _thresholds: { timeout: number; errors: number; } = { timeout: 1500, errors: 3 }
|
||||
) {
|
||||
//
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._callbacks.clear();
|
||||
}
|
||||
|
||||
get onWillSaveTextDocumentEvent(): Event<vscode.TextDocumentWillSaveEvent> {
|
||||
getOnWillSaveTextDocumentEvent(extension: IExtensionDescription): Event<vscode.TextDocumentWillSaveEvent> {
|
||||
return (listener, thisArg, disposables) => {
|
||||
const remove = this._callbacks.push([listener, thisArg]);
|
||||
const remove = this._callbacks.push([listener, thisArg, extension]);
|
||||
const result = { dispose: remove };
|
||||
if (Array.isArray(disposables)) {
|
||||
disposables.push(result);
|
||||
@@ -46,13 +49,14 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
|
||||
};
|
||||
}
|
||||
|
||||
$participateInSave(resource: URI, reason: SaveReason): TPromise<boolean[]> {
|
||||
$participateInSave(data: UriComponents, reason: SaveReason): Thenable<boolean[]> {
|
||||
const resource = URI.revive(data);
|
||||
const entries = this._callbacks.toArray();
|
||||
|
||||
let didTimeout = false;
|
||||
let didTimeoutHandle = setTimeout(() => didTimeout = true, this._thresholds.timeout);
|
||||
|
||||
const promise = sequence(entries.map(([fn, thisArg]) => {
|
||||
const promise = sequence(entries.map(listener => {
|
||||
return () => {
|
||||
|
||||
if (didTimeout) {
|
||||
@@ -61,18 +65,17 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
|
||||
}
|
||||
|
||||
const document = this._documents.getDocumentData(resource).document;
|
||||
return this._deliverEventAsyncAndBlameBadListeners(fn, thisArg, <any>{ document, reason: TextDocumentSaveReason.to(reason) });
|
||||
return this._deliverEventAsyncAndBlameBadListeners(listener, <any>{ document, reason: TextDocumentSaveReason.to(reason) });
|
||||
};
|
||||
}));
|
||||
|
||||
return always(promise, () => clearTimeout(didTimeoutHandle));
|
||||
}
|
||||
|
||||
private _deliverEventAsyncAndBlameBadListeners(listener: Function, thisArg: any, stubEvent: vscode.TextDocumentWillSaveEvent): TPromise<any> {
|
||||
private _deliverEventAsyncAndBlameBadListeners([listener, thisArg, extension]: Listener, stubEvent: vscode.TextDocumentWillSaveEvent): Promise<any> {
|
||||
const errors = this._badListeners.get(listener);
|
||||
if (errors > this._thresholds.errors) {
|
||||
// bad listener - ignore
|
||||
return TPromise.wrap(false);
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
return this._deliverEventAsync(listener, thisArg, stubEvent).then(() => {
|
||||
@@ -80,6 +83,10 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
|
||||
return true;
|
||||
|
||||
}, err => {
|
||||
|
||||
this._logService.error('[onWillSaveTextDocument]', extension.id);
|
||||
this._logService.error(err);
|
||||
|
||||
if (!(err instanceof Error) || (<Error>err).message !== 'concurrent_edits') {
|
||||
const errors = this._badListeners.get(listener);
|
||||
this._badListeners.set(listener, !errors ? 1 : errors + 1);
|
||||
@@ -93,9 +100,9 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
|
||||
});
|
||||
}
|
||||
|
||||
private _deliverEventAsync(listener: Function, thisArg: any, stubEvent: vscode.TextDocumentWillSaveEvent): TPromise<any> {
|
||||
private _deliverEventAsync(listener: Function, thisArg: any, stubEvent: vscode.TextDocumentWillSaveEvent): Promise<any> {
|
||||
|
||||
const promises: TPromise<vscode.TextEdit[]>[] = [];
|
||||
const promises: Promise<vscode.TextEdit[]>[] = [];
|
||||
|
||||
const { document, reason } = stubEvent;
|
||||
const { version } = document;
|
||||
@@ -107,7 +114,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
|
||||
if (Object.isFrozen(promises)) {
|
||||
throw illegalState('waitUntil can not be called async');
|
||||
}
|
||||
promises.push(TPromise.wrap(p));
|
||||
promises.push(Promise.resolve(p));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -115,20 +122,27 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
|
||||
// fire event
|
||||
listener.apply(thisArg, [event]);
|
||||
} catch (err) {
|
||||
return TPromise.wrapError(err);
|
||||
return Promise.reject(err);
|
||||
}
|
||||
|
||||
// freeze promises after event call
|
||||
Object.freeze(promises);
|
||||
|
||||
return new TPromise<vscode.TextEdit[][]>((resolve, reject) => {
|
||||
return new Promise<vscode.TextEdit[][]>((resolve, reject) => {
|
||||
// join on all listener promises, reject after timeout
|
||||
const handle = setTimeout(() => reject(new Error('timeout')), this._thresholds.timeout);
|
||||
return always(TPromise.join(promises), () => clearTimeout(handle)).then(resolve, reject);
|
||||
|
||||
return Promise.all(promises).then(edits => {
|
||||
clearTimeout(handle);
|
||||
resolve(edits);
|
||||
}).catch(err => {
|
||||
clearTimeout(handle);
|
||||
reject(err);
|
||||
});
|
||||
|
||||
}).then(values => {
|
||||
|
||||
let workspaceResourceEdit: IWorkspaceResourceEdit = {
|
||||
const resourceEdit: ResourceTextEditDto = {
|
||||
resource: document.uri,
|
||||
edits: []
|
||||
};
|
||||
@@ -136,10 +150,10 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
|
||||
for (const value of values) {
|
||||
if (Array.isArray(value) && (<vscode.TextEdit[]>value).every(e => e instanceof TextEdit)) {
|
||||
for (const { newText, newEol, range } of value) {
|
||||
workspaceResourceEdit.edits.push({
|
||||
resourceEdit.edits.push({
|
||||
range: range && fromRange(range),
|
||||
newText,
|
||||
newEol: EndOfLine.from(newEol)
|
||||
text: newText,
|
||||
eol: EndOfLine.from(newEol)
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -147,16 +161,16 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
|
||||
|
||||
// apply edits if any and if document
|
||||
// didn't change somehow in the meantime
|
||||
if (workspaceResourceEdit.edits.length === 0) {
|
||||
return undefined;
|
||||
if (resourceEdit.edits.length === 0) {
|
||||
return <any>undefined;
|
||||
}
|
||||
|
||||
if (version === document.version) {
|
||||
return this._mainThreadEditors.$tryApplyWorkspaceEdit([workspaceResourceEdit]);
|
||||
return <any>this._mainThreadEditors.$tryApplyWorkspaceEdit({ edits: [resourceEdit] });
|
||||
}
|
||||
|
||||
// TODO@joh bubble this to listener?
|
||||
return TPromise.wrapError(new Error('concurrent_edits'));
|
||||
return Promise.reject(new Error('concurrent_edits'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
'use strict';
|
||||
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import URI, { UriComponents } from 'vs/base/common/uri';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import * as TypeConverters from './extHostTypeConverters';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
@@ -13,7 +13,7 @@ import * as vscode from 'vscode';
|
||||
import { MainContext, MainThreadDocumentsShape, ExtHostDocumentsShape, IMainContext } from './extHost.protocol';
|
||||
import { ExtHostDocumentData, setWordDefinitionFor } from './extHostDocumentData';
|
||||
import { ExtHostDocumentsAndEditors } from './extHostDocumentsAndEditors';
|
||||
import { IModelChangedEvent } from 'vs/editor/common/model/mirrorModel';
|
||||
import { IModelChangedEvent } from 'vs/editor/common/model/mirrorTextModel';
|
||||
|
||||
export class ExtHostDocuments implements ExtHostDocumentsShape {
|
||||
|
||||
@@ -33,7 +33,7 @@ export class ExtHostDocuments implements ExtHostDocumentsShape {
|
||||
private _documentLoader = new Map<string, TPromise<ExtHostDocumentData>>();
|
||||
|
||||
constructor(mainContext: IMainContext, documentsAndEditors: ExtHostDocumentsAndEditors) {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadDocuments);
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadDocuments);
|
||||
this._documentsAndEditors = documentsAndEditors;
|
||||
|
||||
this._toDispose = [
|
||||
@@ -92,10 +92,12 @@ export class ExtHostDocuments implements ExtHostDocumentsShape {
|
||||
}
|
||||
|
||||
public createDocumentData(options?: { language?: string; content?: string }): TPromise<URI> {
|
||||
return this._proxy.$tryCreateDocument(options);
|
||||
return this._proxy.$tryCreateDocument(options).then(data => URI.revive(data));
|
||||
}
|
||||
|
||||
public $acceptModelModeChanged(strURL: string, oldModeId: string, newModeId: string): void {
|
||||
public $acceptModelModeChanged(uriComponents: UriComponents, oldModeId: string, newModeId: string): void {
|
||||
const uri = URI.revive(uriComponents);
|
||||
const strURL = uri.toString();
|
||||
let data = this._documentsAndEditors.getDocument(strURL);
|
||||
|
||||
// Treat a mode change as a remove + add
|
||||
@@ -105,13 +107,17 @@ export class ExtHostDocuments implements ExtHostDocumentsShape {
|
||||
this._onDidAddDocument.fire(data.document);
|
||||
}
|
||||
|
||||
public $acceptModelSaved(strURL: string): void {
|
||||
public $acceptModelSaved(uriComponents: UriComponents): void {
|
||||
const uri = URI.revive(uriComponents);
|
||||
const strURL = uri.toString();
|
||||
let data = this._documentsAndEditors.getDocument(strURL);
|
||||
this.$acceptDirtyStateChanged(strURL, false);
|
||||
this.$acceptDirtyStateChanged(uriComponents, false);
|
||||
this._onDidSaveDocument.fire(data.document);
|
||||
}
|
||||
|
||||
public $acceptDirtyStateChanged(strURL: string, isDirty: boolean): void {
|
||||
public $acceptDirtyStateChanged(uriComponents: UriComponents, isDirty: boolean): void {
|
||||
const uri = URI.revive(uriComponents);
|
||||
const strURL = uri.toString();
|
||||
let data = this._documentsAndEditors.getDocument(strURL);
|
||||
data._acceptIsDirty(isDirty);
|
||||
this._onDidChangeDocument.fire({
|
||||
@@ -120,7 +126,9 @@ export class ExtHostDocuments implements ExtHostDocumentsShape {
|
||||
});
|
||||
}
|
||||
|
||||
public $acceptModelChanged(strURL: string, events: IModelChangedEvent, isDirty: boolean): void {
|
||||
public $acceptModelChanged(uriComponents: UriComponents, events: IModelChangedEvent, isDirty: boolean): void {
|
||||
const uri = URI.revive(uriComponents);
|
||||
const strURL = uri.toString();
|
||||
let data = this._documentsAndEditors.getDocument(strURL);
|
||||
data._acceptIsDirty(isDirty);
|
||||
data.onEvents(events);
|
||||
|
||||
@@ -11,10 +11,17 @@ import { ExtHostDocumentData } from './extHostDocumentData';
|
||||
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 {
|
||||
|
||||
private _disposables: Disposable[] = [];
|
||||
|
||||
private _activeEditorId: string;
|
||||
private _activeWebview: ExtHostWebview;
|
||||
|
||||
private readonly _editors = new Map<string, ExtHostTextEditor>();
|
||||
private readonly _documents = new Map<string, ExtHostDocumentData>();
|
||||
|
||||
@@ -22,15 +29,34 @@ 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
|
||||
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);
|
||||
}
|
||||
|
||||
$acceptDocumentsAndEditorsDelta(delta: IDocumentsAndEditorsDelta): void {
|
||||
@@ -40,7 +66,9 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
|
||||
const removedEditors: ExtHostTextEditor[] = [];
|
||||
|
||||
if (delta.removedDocuments) {
|
||||
for (const id of delta.removedDocuments) {
|
||||
for (const uriComponent of delta.removedDocuments) {
|
||||
const uri = URI.revive(uriComponent);
|
||||
const id = uri.toString();
|
||||
const data = this._documents.get(id);
|
||||
this._documents.delete(id);
|
||||
removedDocuments.push(data);
|
||||
@@ -49,18 +77,19 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
|
||||
|
||||
if (delta.addedDocuments) {
|
||||
for (const data of delta.addedDocuments) {
|
||||
assert.ok(!this._documents.has(data.url.toString()), `document '${data.url} already exists!'`);
|
||||
const resource = URI.revive(data.uri);
|
||||
assert.ok(!this._documents.has(resource.toString()), `document '${resource} already exists!'`);
|
||||
|
||||
const documentData = new ExtHostDocumentData(
|
||||
this._mainContext.get(MainContext.MainThreadDocuments),
|
||||
data.url,
|
||||
this._mainContext.getProxy(MainContext.MainThreadDocuments),
|
||||
resource,
|
||||
data.lines,
|
||||
data.EOL,
|
||||
data.modeId,
|
||||
data.versionId,
|
||||
data.isDirty
|
||||
);
|
||||
this._documents.set(data.url.toString(), documentData);
|
||||
this._documents.set(resource.toString(), documentData);
|
||||
addedDocuments.push(documentData);
|
||||
}
|
||||
}
|
||||
@@ -75,16 +104,18 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
|
||||
|
||||
if (delta.addedEditors) {
|
||||
for (const data of delta.addedEditors) {
|
||||
assert.ok(this._documents.has(data.document.toString()), `document '${data.document}' does not exist`);
|
||||
const resource = URI.revive(data.documentUri);
|
||||
assert.ok(this._documents.has(resource.toString()), `document '${resource}' does not exist`);
|
||||
assert.ok(!this._editors.has(data.id), `editor '${data.id}' already exists!`);
|
||||
|
||||
const documentData = this._documents.get(data.document.toString());
|
||||
const documentData = this._documents.get(resource.toString());
|
||||
const editor = new ExtHostTextEditor(
|
||||
this._mainContext.get(MainContext.MainThreadEditors),
|
||||
this._mainContext.getProxy(MainContext.MainThreadTextEditors),
|
||||
data.id,
|
||||
documentData,
|
||||
data.selections.map(typeConverters.toSelection),
|
||||
data.options,
|
||||
data.visibleRanges.map(typeConverters.toRange),
|
||||
typeConverters.toViewColumn(data.editorPosition)
|
||||
);
|
||||
this._editors.set(data.id, editor);
|
||||
@@ -112,6 +143,9 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
|
||||
}
|
||||
if (delta.newActiveEditor !== undefined) {
|
||||
this._onDidChangeActiveTextEditor.fire(this.activeEditor());
|
||||
|
||||
const activeEditor = this.activeEditor();
|
||||
this._onDidChangeActiveEditor.fire(activeEditor || this._activeWebview);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ExtHostLogger } from 'vs/workbench/api/node/extHostLogService';
|
||||
|
||||
const hasOwnProperty = Object.hasOwnProperty;
|
||||
const NO_OP_VOID_PROMISE = TPromise.wrap<void>(void 0);
|
||||
@@ -26,6 +27,7 @@ export interface IExtensionContext {
|
||||
extensionPath: string;
|
||||
storagePath: string;
|
||||
asAbsolutePath(relativePath: string): string;
|
||||
logger: ExtHostLogger;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -240,7 +242,7 @@ 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._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);
|
||||
return;
|
||||
}
|
||||
@@ -249,7 +251,7 @@ export class ExtensionsActivator {
|
||||
let dep = this._activatedExtensions[depId];
|
||||
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._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);
|
||||
return;
|
||||
}
|
||||
@@ -282,7 +284,7 @@ export class ExtensionsActivator {
|
||||
// More than 10 dependencies deep => most likely a dependency loop
|
||||
for (let i = 0, len = extensionDescriptions.length; i < len; i++) {
|
||||
// Error condition 3: dependency loop
|
||||
this._host.showMessage(Severity.Error, nls.localize('failedDep2', "Extension `{0}` failed to activate. Reason: more than 10 levels of dependencies (most likely a dependency loop).", extensionDescriptions[i].id));
|
||||
this._host.showMessage(Severity.Error, nls.localize('failedDep2', "Extension '{0}' failed to activate. Reason: more than 10 levels of dependencies (most likely a dependency loop).", extensionDescriptions[i].id));
|
||||
this._activatedExtensions[extensionDescriptions[i].id] = new FailedExtension(ExtensionActivationTimes.NONE);
|
||||
}
|
||||
return TPromise.as(void 0);
|
||||
@@ -327,7 +329,7 @@ export class ExtensionsActivator {
|
||||
}
|
||||
|
||||
this._activatingExtensions[extensionDescription.id] = this._host.actualActivateExtension(extensionDescription, reason).then(null, (err) => {
|
||||
this._host.showMessage(Severity.Error, nls.localize('activationError', "Activating extension `{0}` failed: {1}.", extensionDescription.id, err.message));
|
||||
this._host.showMessage(Severity.Error, nls.localize('activationError', "Activating extension '{0}' failed: {1}.", extensionDescription.id, err.message));
|
||||
console.error('Activating extension `' + extensionDescription.id + '` failed: ', err.message);
|
||||
console.log('Here is the error stack: ', err.stack);
|
||||
// Treat the extension as being empty
|
||||
|
||||
@@ -6,31 +6,33 @@
|
||||
|
||||
import { dispose } from 'vs/base/common/lifecycle';
|
||||
import { join } from 'path';
|
||||
import { mkdirp, dirExists } from 'vs/base/node/pfs';
|
||||
import { mkdirp, dirExists, realpath, writeFile } from 'vs/base/node/pfs';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ExtHostStorage } from 'vs/workbench/api/node/extHostStorage';
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { createApiFactory, initializeExtensionApi } from 'sql/workbench/api/node/sqlExtHost.api.impl';
|
||||
import { MainContext, MainThreadExtensionServiceShape, IWorkspaceData, IEnvironment, IInitData, ExtHostExtensionServiceShape, MainThreadTelemetryShape } from './extHost.protocol';
|
||||
import { checkProposedApiEnabled } from 'vs/workbench/api/node/extHost.api.impl';
|
||||
import { MainContext, MainThreadExtensionServiceShape, IWorkspaceData, IEnvironment, IInitData, ExtHostExtensionServiceShape, MainThreadTelemetryShape, IExtHostContext } from './extHost.protocol';
|
||||
import { IExtensionMemento, ExtensionsActivator, ActivatedExtension, IExtensionAPI, IExtensionContext, EmptyExtension, IExtensionModule, ExtensionActivationTimesBuilder, ExtensionActivationTimes, ExtensionActivationReason, ExtensionActivatedByEvent } from 'vs/workbench/api/node/extHostExtensionActivator';
|
||||
import { ExtHostThreadService } from 'vs/workbench/services/thread/node/extHostThreadService';
|
||||
import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration';
|
||||
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
|
||||
import { realpath } from 'fs';
|
||||
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';
|
||||
|
||||
class ExtensionMemento implements IExtensionMemento {
|
||||
|
||||
private _id: string;
|
||||
private _shared: boolean;
|
||||
private _storage: ExtHostStorage;
|
||||
private readonly _id: string;
|
||||
private readonly _shared: boolean;
|
||||
private readonly _storage: ExtHostStorage;
|
||||
|
||||
private _init: TPromise<ExtensionMemento>;
|
||||
private readonly _init: TPromise<ExtensionMemento>;
|
||||
private _value: { [n: string]: any; };
|
||||
|
||||
constructor(id: string, global: boolean, storage: ExtHostStorage) {
|
||||
@@ -89,24 +91,36 @@ class ExtensionStoragePath {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private _getOrCreateWorkspaceStoragePath(): TPromise<string> {
|
||||
private async _getOrCreateWorkspaceStoragePath(): TPromise<string> {
|
||||
if (!this._workspace) {
|
||||
return TPromise.as(undefined);
|
||||
}
|
||||
|
||||
const storageName = this._workspace.id;
|
||||
const storagePath = join(this._environment.appSettingsHome, 'workspaceStorage', storageName);
|
||||
|
||||
return dirExists(storagePath).then(exists => {
|
||||
if (exists) {
|
||||
return storagePath;
|
||||
}
|
||||
const exists = await dirExists(storagePath);
|
||||
|
||||
return mkdirp(storagePath).then(success => {
|
||||
return storagePath;
|
||||
}, err => {
|
||||
return undefined;
|
||||
});
|
||||
});
|
||||
if (exists) {
|
||||
return storagePath;
|
||||
}
|
||||
|
||||
try {
|
||||
await mkdirp(storagePath);
|
||||
await writeFile(
|
||||
join(storagePath, 'meta.json'),
|
||||
JSON.stringify({
|
||||
id: this._workspace.id,
|
||||
configuration: this._workspace.configuration && URI.revive(this._workspace.configuration).toString(),
|
||||
name: this._workspace.name
|
||||
}, undefined, 2)
|
||||
);
|
||||
return storagePath;
|
||||
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,35 +128,34 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
|
||||
private readonly _barrier: Barrier;
|
||||
private readonly _registry: ExtensionDescriptionRegistry;
|
||||
private readonly _threadService: ExtHostThreadService;
|
||||
private readonly _mainThreadTelemetry: MainThreadTelemetryShape;
|
||||
private readonly _storage: ExtHostStorage;
|
||||
private readonly _storagePath: ExtensionStoragePath;
|
||||
private readonly _proxy: MainThreadExtensionServiceShape;
|
||||
private readonly _logService: ILogService;
|
||||
private readonly _extHostLogService: ExtHostLogService;
|
||||
private _activator: ExtensionsActivator;
|
||||
private _extensionPathIndex: TPromise<TernarySearchTree<IExtensionDescription>>;
|
||||
/**
|
||||
* This class is constructed manually because it is a service, so it doesn't use any ctor injection
|
||||
*/
|
||||
constructor(initData: IInitData,
|
||||
threadService: ExtHostThreadService,
|
||||
extHostContext: IExtHostContext,
|
||||
extHostWorkspace: ExtHostWorkspace,
|
||||
extHostConfiguration: ExtHostConfiguration,
|
||||
logService: ILogService
|
||||
extHostLogService: ExtHostLogService,
|
||||
environmentService: IEnvironmentService
|
||||
) {
|
||||
this._barrier = new Barrier();
|
||||
this._registry = new ExtensionDescriptionRegistry(initData.extensions);
|
||||
this._threadService = threadService;
|
||||
this._logService = logService;
|
||||
this._mainThreadTelemetry = threadService.get(MainContext.MainThreadTelemetry);
|
||||
this._storage = new ExtHostStorage(threadService);
|
||||
this._extHostLogService = extHostLogService;
|
||||
this._mainThreadTelemetry = extHostContext.getProxy(MainContext.MainThreadTelemetry);
|
||||
this._storage = new ExtHostStorage(extHostContext);
|
||||
this._storagePath = new ExtensionStoragePath(initData.workspace, initData.environment);
|
||||
this._proxy = this._threadService.get(MainContext.MainThreadExtensionService);
|
||||
this._proxy = extHostContext.getProxy(MainContext.MainThreadExtensionService);
|
||||
this._activator = null;
|
||||
|
||||
// initialize API first (i.e. do not release barrier until the API is initialized)
|
||||
const apiFactory = createApiFactory(initData, threadService, extHostWorkspace, extHostConfiguration, this, logService);
|
||||
const apiFactory = createApiFactory(initData, extHostContext, extHostWorkspace, extHostConfiguration, this, this._extHostLogService);
|
||||
|
||||
initializeExtensionApi(this, apiFactory).then(() => {
|
||||
|
||||
@@ -223,16 +236,8 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
if (!ext.main) {
|
||||
return undefined;
|
||||
}
|
||||
return new TPromise((resolve, reject) => {
|
||||
realpath(ext.extensionFolderPath, (err, path) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
tree.set(path, ext);
|
||||
resolve(void 0);
|
||||
}
|
||||
});
|
||||
});
|
||||
return realpath(ext.extensionFolderPath).then(value => tree.set(value, ext));
|
||||
|
||||
});
|
||||
this._extensionPathIndex = TPromise.join(extensions).then(() => tree);
|
||||
}
|
||||
@@ -311,14 +316,14 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
return TPromise.as(new EmptyExtension(ExtensionActivationTimes.NONE));
|
||||
}
|
||||
|
||||
this._logService.info(`ExtensionService#_doActivateExtension ${extensionDescription.id} ${JSON.stringify(reason)}`);
|
||||
this._extHostLogService.info(`ExtensionService#_doActivateExtension ${extensionDescription.id} ${JSON.stringify(reason)}`);
|
||||
|
||||
const activationTimesBuilder = new ExtensionActivationTimesBuilder(reason.startup);
|
||||
return TPromise.join<any>([
|
||||
loadCommonJSModule(this._logService, extensionDescription.main, activationTimesBuilder),
|
||||
loadCommonJSModule(this._extHostLogService, extensionDescription.main, activationTimesBuilder),
|
||||
this._loadExtensionContext(extensionDescription)
|
||||
]).then(values => {
|
||||
return ExtHostExtensionService._callActivate(this._logService, extensionDescription.id, <IExtensionModule>values[0], <IExtensionContext>values[1], activationTimesBuilder);
|
||||
return ExtHostExtensionService._callActivate(this._extHostLogService, extensionDescription.id, <IExtensionModule>values[0], <IExtensionContext>values[1], activationTimesBuilder);
|
||||
}, (errors: any[]) => {
|
||||
// Avoid failing with an array of errors, fail with a single error
|
||||
if (errors[0]) {
|
||||
@@ -336,19 +341,24 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
|
||||
let globalState = new ExtensionMemento(extensionDescription.id, true, this._storage);
|
||||
let workspaceState = new ExtensionMemento(extensionDescription.id, false, this._storage);
|
||||
|
||||
this._logService.trace(`ExtensionService#loadExtensionContext ${extensionDescription.id}`);
|
||||
this._extHostLogService.trace(`ExtensionService#loadExtensionContext ${extensionDescription.id}`);
|
||||
return TPromise.join([
|
||||
globalState.whenReady,
|
||||
workspaceState.whenReady,
|
||||
this._storagePath.whenReady
|
||||
]).then(() => {
|
||||
const that = this;
|
||||
return Object.freeze(<IExtensionContext>{
|
||||
globalState,
|
||||
workspaceState,
|
||||
subscriptions: [],
|
||||
get extensionPath() { return extensionDescription.extensionFolderPath; },
|
||||
storagePath: this._storagePath.value(extensionDescription),
|
||||
asAbsolutePath: (relativePath: string) => { return join(extensionDescription.extensionFolderPath, relativePath); }
|
||||
asAbsolutePath: (relativePath: string) => { return join(extensionDescription.extensionFolderPath, relativePath); },
|
||||
get logger() {
|
||||
checkProposedApiEnabled(extensionDescription);
|
||||
return that._extHostLogService.getExtLogger(extensionDescription.id);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,29 +4,79 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import URI from 'vs/base/common/uri';
|
||||
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 * as vscode from 'vscode';
|
||||
import { IStat } from 'vs/platform/files/common/files';
|
||||
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 { ExtHostLanguageFeatures } from 'vs/workbench/api/node/extHostLanguageFeatures';
|
||||
|
||||
class FsLinkProvider implements vscode.DocumentLinkProvider {
|
||||
|
||||
private _schemes = new Set<string>();
|
||||
private _regex: RegExp;
|
||||
|
||||
add(scheme: string): void {
|
||||
this._regex = undefined;
|
||||
this._schemes.add(scheme);
|
||||
}
|
||||
|
||||
delete(scheme: string): void {
|
||||
if (this._schemes.delete(scheme)) {
|
||||
this._regex = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
provideDocumentLinks(document: vscode.TextDocument, token: vscode.CancellationToken): vscode.ProviderResult<vscode.DocumentLink[]> {
|
||||
if (this._schemes.size === 0) {
|
||||
return undefined;
|
||||
}
|
||||
if (!this._regex) {
|
||||
this._regex = new RegExp(`(${(values(this._schemes).join('|'))}):[^\\s]+`, 'gi');
|
||||
}
|
||||
let result: vscode.DocumentLink[] = [];
|
||||
let max = Math.min(document.lineCount, 2500);
|
||||
for (let line = 0; line < max; line++) {
|
||||
this._regex.lastIndex = 0;
|
||||
let textLine = document.lineAt(line);
|
||||
let m: RegExpMatchArray;
|
||||
while (m = this._regex.exec(textLine.text)) {
|
||||
const target = URI.parse(m[0]);
|
||||
const range = new Range(line, this._regex.lastIndex - m[0].length, line, this._regex.lastIndex);
|
||||
result.push({ target, range });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
|
||||
private readonly _proxy: MainThreadFileSystemShape;
|
||||
private readonly _provider = new Map<number, vscode.FileSystemProvider>();
|
||||
private readonly _linkProvider = new FsLinkProvider();
|
||||
|
||||
private _handlePool: number = 0;
|
||||
|
||||
constructor(mainContext: IMainContext) {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadFileSystem);
|
||||
constructor(mainContext: IMainContext, extHostLanguageFeatures: ExtHostLanguageFeatures) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadFileSystem);
|
||||
extHostLanguageFeatures.registerDocumentLinkProvider('*', this._linkProvider);
|
||||
}
|
||||
|
||||
registerFileSystemProvider(scheme: string, provider: vscode.FileSystemProvider) {
|
||||
const handle = this._handlePool++;
|
||||
this._linkProvider.add(scheme);
|
||||
this._provider.set(handle, provider);
|
||||
this._proxy.$registerFileSystemProvider(handle, scheme);
|
||||
this._proxy.$onDidAddFileSystemRoot(<any>provider.root);
|
||||
if (provider.root) {
|
||||
// todo@remote
|
||||
this._proxy.$onDidAddFileSystemRoot(provider.root);
|
||||
}
|
||||
let reg: IDisposable;
|
||||
if (provider.onDidChange) {
|
||||
reg = provider.onDidChange(event => this._proxy.$onFileSystemChange(handle, <any>event));
|
||||
@@ -36,50 +86,71 @@ export class ExtHostFileSystem implements ExtHostFileSystemShape {
|
||||
if (reg) {
|
||||
reg.dispose();
|
||||
}
|
||||
this._linkProvider.delete(scheme);
|
||||
this._provider.delete(handle);
|
||||
this._proxy.$unregisterFileSystemProvider(handle);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
$utimes(handle: number, resource: URI, mtime: number, atime: number): TPromise<IStat, any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).utimes(resource, mtime, atime));
|
||||
$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));
|
||||
}
|
||||
$stat(handle: number, resource: URI): TPromise<IStat, any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).stat(resource));
|
||||
$stat(handle: number, resource: UriComponents): TPromise<IStat, any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).stat(URI.revive(resource)));
|
||||
}
|
||||
$read(handle: number, offset: number, count: number, resource: URI): TPromise<number> {
|
||||
$read(handle: number, session: number, offset: number, count: number, resource: UriComponents): TPromise<number> {
|
||||
const progress = {
|
||||
report: chunk => {
|
||||
this._proxy.$reportFileChunk(handle, resource, [].slice.call(chunk));
|
||||
this._proxy.$reportFileChunk(handle, session, [].slice.call(chunk));
|
||||
}
|
||||
};
|
||||
return asWinJsPromise(token => this._provider.get(handle).read(resource, offset, count, progress));
|
||||
return asWinJsPromise(token => this._provider.get(handle).read(URI.revive(resource), offset, count, progress));
|
||||
}
|
||||
$write(handle: number, resource: URI, content: number[]): TPromise<void, any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).write(resource, Buffer.from(content)));
|
||||
$write(handle: number, resource: UriComponents, content: number[]): TPromise<void, any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).write(URI.revive(resource), Buffer.from(content)));
|
||||
}
|
||||
$unlink(handle: number, resource: URI): TPromise<void, any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).unlink(resource));
|
||||
$unlink(handle: number, resource: UriComponents): TPromise<void, any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).unlink(URI.revive(resource)));
|
||||
}
|
||||
$move(handle: number, resource: URI, target: URI): TPromise<IStat, any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).move(resource, target));
|
||||
$move(handle: number, resource: UriComponents, target: UriComponents): TPromise<IStat, any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).move(URI.revive(resource), URI.revive(target)));
|
||||
}
|
||||
$mkdir(handle: number, resource: URI): TPromise<IStat, any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).mkdir(resource));
|
||||
$mkdir(handle: number, resource: UriComponents): TPromise<IStat, any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).mkdir(URI.revive(resource)));
|
||||
}
|
||||
$readdir(handle: number, resource: URI): TPromise<[URI, IStat][], any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).readdir(resource));
|
||||
$readdir(handle: number, resource: UriComponents): TPromise<[UriComponents, IStat][], any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).readdir(URI.revive(resource)));
|
||||
}
|
||||
$rmdir(handle: number, resource: URI): TPromise<void, any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).rmdir(resource));
|
||||
$rmdir(handle: number, resource: UriComponents): TPromise<void, any> {
|
||||
return asWinJsPromise(token => this._provider.get(handle).rmdir(URI.revive(resource)));
|
||||
}
|
||||
$fileFiles(handle: number, session: number, query: string): TPromise<void> {
|
||||
$findFiles(handle: number, session: number, query: string): TPromise<void> {
|
||||
const provider = this._provider.get(handle);
|
||||
if (!provider.findFiles) {
|
||||
return TPromise.as(undefined);
|
||||
}
|
||||
const progress = { report: (uri) => this._proxy.$handleSearchProgress(handle, session, uri) };
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Disposable } from './extHostTypes';
|
||||
import { parse, IRelativePattern } from 'vs/base/common/glob';
|
||||
import { Uri, FileSystemWatcher as _FileSystemWatcher } from 'vscode';
|
||||
import { FileSystemEvents, ExtHostFileSystemEventServiceShape } from './extHost.protocol';
|
||||
import URI from 'vs/base/common/uri';
|
||||
|
||||
class FileSystemWatcher implements _FileSystemWatcher {
|
||||
|
||||
@@ -48,22 +49,25 @@ class FileSystemWatcher implements _FileSystemWatcher {
|
||||
let subscription = dispatcher(events => {
|
||||
if (!ignoreCreateEvents) {
|
||||
for (let created of events.created) {
|
||||
if (parsedPattern(created.fsPath)) {
|
||||
this._onDidCreate.fire(created);
|
||||
let uri = URI.revive(created);
|
||||
if (parsedPattern(uri.fsPath)) {
|
||||
this._onDidCreate.fire(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ignoreChangeEvents) {
|
||||
for (let changed of events.changed) {
|
||||
if (parsedPattern(changed.fsPath)) {
|
||||
this._onDidChange.fire(changed);
|
||||
let uri = URI.revive(changed);
|
||||
if (parsedPattern(uri.fsPath)) {
|
||||
this._onDidChange.fire(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!ignoreDeleteEvents) {
|
||||
for (let deleted of events.deleted) {
|
||||
if (parsedPattern(deleted.fsPath)) {
|
||||
this._onDidDelete.fire(deleted);
|
||||
let uri = URI.revive(deleted);
|
||||
if (parsedPattern(uri.fsPath)) {
|
||||
this._onDidDelete.fire(uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,20 +4,20 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import URI from 'vs/base/common/uri';
|
||||
import URI, { UriComponents } from 'vs/base/common/uri';
|
||||
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 } from 'vs/workbench/api/node/extHostTypes';
|
||||
import { ISingleEditOperation } from 'vs/editor/common/editorCommon';
|
||||
import { Range, Disposable, CompletionList, SnippetString, Color, CodeActionKind } 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 { asWinJsPromise } from 'vs/base/common/async';
|
||||
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IExtHostSuggestResult, IExtHostSuggestion, IWorkspaceSymbols, IWorkspaceSymbol, IdObject } from './extHost.protocol';
|
||||
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, SymbolInformationDto, SuggestResultDto, WorkspaceSymbolsDto, SuggestionDto, CodeActionDto } 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';
|
||||
@@ -35,11 +35,11 @@ class OutlineAdapter {
|
||||
this._provider = provider;
|
||||
}
|
||||
|
||||
provideDocumentSymbols(resource: URI): TPromise<modes.SymbolInformation[]> {
|
||||
provideDocumentSymbols(resource: URI): TPromise<SymbolInformationDto[]> {
|
||||
let doc = this._documents.getDocumentData(resource).document;
|
||||
return asWinJsPromise(token => this._provider.provideDocumentSymbols(doc, token)).then(value => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(TypeConverters.fromSymbolInformation);
|
||||
return value.map(symbol => IdObject.mixin(TypeConverters.fromSymbolInformation(symbol)));
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
@@ -255,7 +255,7 @@ class ReferenceAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
export interface CustomCodeAction extends modes.CodeAction {
|
||||
export interface CustomCodeAction extends CodeActionDto {
|
||||
_isSynthetic?: boolean;
|
||||
}
|
||||
|
||||
@@ -273,7 +273,8 @@ class CodeActionAdapter {
|
||||
this._provider = provider;
|
||||
}
|
||||
|
||||
provideCodeActions(resource: URI, range: IRange): TPromise<modes.CodeAction[]> {
|
||||
|
||||
provideCodeActions(resource: URI, range: IRange, context: modes.CodeActionContext): TPromise<CodeActionDto[]> {
|
||||
|
||||
const doc = this._documents.getDocumentData(resource).document;
|
||||
const ran = <vscode.Range>TypeConverters.toRange(range);
|
||||
@@ -289,9 +290,12 @@ class CodeActionAdapter {
|
||||
}
|
||||
});
|
||||
|
||||
return asWinJsPromise(token => this._provider.provideCodeActions2
|
||||
? this._provider.provideCodeActions2(doc, ran, { diagnostics: allDiagnostics }, token)
|
||||
: this._provider.provideCodeActions(doc, ran, { diagnostics: allDiagnostics }, token)
|
||||
const codeActionContext: vscode.CodeActionContext = {
|
||||
diagnostics: allDiagnostics,
|
||||
only: context.only ? new CodeActionKind(context.only) : undefined
|
||||
};
|
||||
return asWinJsPromise(token =>
|
||||
this._provider.provideCodeActions(doc, ran, codeActionContext, token)
|
||||
).then(commandsOrActions => {
|
||||
if (isFalsyOrEmpty(commandsOrActions)) {
|
||||
return undefined;
|
||||
@@ -314,9 +318,8 @@ class CodeActionAdapter {
|
||||
title: candidate.title,
|
||||
command: candidate.command && this._commands.toInternal(candidate.command),
|
||||
diagnostics: candidate.diagnostics && candidate.diagnostics.map(DiagnosticCollection.toMarkerData),
|
||||
edits: Array.isArray(candidate.edits)
|
||||
? TypeConverters.WorkspaceEdit.fromTextEdits(resource, candidate.edits)
|
||||
: candidate.edits && TypeConverters.WorkspaceEdit.from(candidate.edits),
|
||||
edit: candidate.edit && TypeConverters.WorkspaceEdit.from(candidate.edit),
|
||||
kind: candidate.kind && candidate.kind.value
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -413,8 +416,8 @@ class NavigateTypeAdapter {
|
||||
this._provider = provider;
|
||||
}
|
||||
|
||||
provideWorkspaceSymbols(search: string): TPromise<IWorkspaceSymbols> {
|
||||
const result: IWorkspaceSymbols = IdObject.mixin({ symbols: [] });
|
||||
provideWorkspaceSymbols(search: string): TPromise<WorkspaceSymbolsDto> {
|
||||
const result: WorkspaceSymbolsDto = IdObject.mixin({ symbols: [] });
|
||||
return asWinJsPromise(token => this._provider.provideWorkspaceSymbols(search, token)).then(value => {
|
||||
if (!isFalsyOrEmpty(value)) {
|
||||
for (const item of value) {
|
||||
@@ -439,7 +442,7 @@ class NavigateTypeAdapter {
|
||||
});
|
||||
}
|
||||
|
||||
resolveWorkspaceSymbol(symbol: IWorkspaceSymbol): TPromise<IWorkspaceSymbol> {
|
||||
resolveWorkspaceSymbol(symbol: SymbolInformationDto): TPromise<SymbolInformationDto> {
|
||||
|
||||
if (typeof this._provider.resolveWorkspaceSymbol !== 'function') {
|
||||
return TPromise.as(symbol);
|
||||
@@ -465,12 +468,20 @@ class NavigateTypeAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
interface RenameProvider2 extends vscode.RenameProvider {
|
||||
resolveInitialRenameValue?(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.ProviderResult<any>;
|
||||
}
|
||||
|
||||
class RenameAdapter {
|
||||
|
||||
private _documents: ExtHostDocuments;
|
||||
private _provider: vscode.RenameProvider;
|
||||
static supportsResolving(provider: RenameProvider2): boolean {
|
||||
return typeof provider.resolveInitialRenameValue === 'function';
|
||||
}
|
||||
|
||||
constructor(documents: ExtHostDocuments, provider: vscode.RenameProvider) {
|
||||
private _documents: ExtHostDocuments;
|
||||
private _provider: RenameProvider2;
|
||||
|
||||
constructor(documents: ExtHostDocuments, provider: RenameProvider2) {
|
||||
this._documents = documents;
|
||||
this._provider = provider;
|
||||
}
|
||||
@@ -502,6 +513,22 @@ class RenameAdapter {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
resolveInitialRenameValue(resource: URI, position: IPosition): TPromise<modes.RenameInitialValue> {
|
||||
if (typeof this._provider.resolveInitialRenameValue !== '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
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -524,7 +551,7 @@ class SuggestAdapter {
|
||||
this._provider = provider;
|
||||
}
|
||||
|
||||
provideCompletionItems(resource: URI, position: IPosition, context: modes.SuggestContext): TPromise<IExtHostSuggestResult> {
|
||||
provideCompletionItems(resource: URI, position: IPosition, context: modes.SuggestContext): TPromise<SuggestResultDto> {
|
||||
|
||||
const doc = this._documents.getDocumentData(resource).document;
|
||||
const pos = TypeConverters.toPosition(position);
|
||||
@@ -535,7 +562,7 @@ class SuggestAdapter {
|
||||
|
||||
const _id = this._idPool++;
|
||||
|
||||
const result: IExtHostSuggestResult = {
|
||||
const result: SuggestResultDto = {
|
||||
_id,
|
||||
suggestions: [],
|
||||
};
|
||||
@@ -554,7 +581,7 @@ class SuggestAdapter {
|
||||
}
|
||||
|
||||
// the default text edit range
|
||||
const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) || new Range(pos, pos))
|
||||
const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) as Range || new Range(pos, pos))
|
||||
.with({ end: pos });
|
||||
|
||||
for (let i = 0; i < list.items.length; i++) {
|
||||
@@ -577,7 +604,7 @@ class SuggestAdapter {
|
||||
return TPromise.as(suggestion);
|
||||
}
|
||||
|
||||
const { _parentId, _id } = (<IExtHostSuggestion>suggestion);
|
||||
const { _parentId, _id } = (<SuggestionDto>suggestion);
|
||||
const item = this._cache.has(_parentId) && this._cache.get(_parentId)[_id];
|
||||
if (!item) {
|
||||
return TPromise.as(suggestion);
|
||||
@@ -591,7 +618,7 @@ class SuggestAdapter {
|
||||
|
||||
const doc = this._documents.getDocumentData(resource).document;
|
||||
const pos = TypeConverters.toPosition(position);
|
||||
const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) || new Range(pos, pos)).with({ end: pos });
|
||||
const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) as Range || new Range(pos, pos)).with({ end: pos });
|
||||
const newSuggestion = this._convertCompletionItem(resolvedItem, pos, wordRangeBeforePos, _id, _parentId);
|
||||
if (newSuggestion) {
|
||||
mixin(suggestion, newSuggestion, true);
|
||||
@@ -605,13 +632,13 @@ class SuggestAdapter {
|
||||
this._cache.delete(id);
|
||||
}
|
||||
|
||||
private _convertCompletionItem(item: vscode.CompletionItem, position: vscode.Position, defaultRange: vscode.Range, _id: number, _parentId: number): IExtHostSuggestion {
|
||||
private _convertCompletionItem(item: vscode.CompletionItem, position: vscode.Position, defaultRange: vscode.Range, _id: number, _parentId: number): SuggestionDto {
|
||||
if (typeof item.label !== 'string' || item.label.length === 0) {
|
||||
console.warn('INVALID text edit -> must have at least a label');
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const result: IExtHostSuggestion = {
|
||||
const result: SuggestionDto = {
|
||||
//
|
||||
_id,
|
||||
_parentId,
|
||||
@@ -777,10 +804,29 @@ class ColorProviderAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
class FoldingProviderAdapter {
|
||||
|
||||
constructor(
|
||||
private _documents: ExtHostDocuments,
|
||||
private _provider: vscode.FoldingProvider
|
||||
) { }
|
||||
|
||||
provideFoldingRanges(resource: URI): TPromise<modes.IFoldingRangeList> {
|
||||
const doc = this._documents.getDocumentData(resource).document;
|
||||
return asWinJsPromise(token => this._provider.provideFoldingRanges(doc, token)).then(list => {
|
||||
if (!Array.isArray(list.ranges)) {
|
||||
return void 0;
|
||||
}
|
||||
return TypeConverters.FoldingRangeList.from(list);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
type Adapter = OutlineAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter
|
||||
| DocumentHighlightAdapter | ReferenceAdapter | CodeActionAdapter | DocumentFormattingAdapter
|
||||
| RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter
|
||||
| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter | TypeDefinitionAdapter | ColorProviderAdapter;
|
||||
| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter | TypeDefinitionAdapter
|
||||
| ColorProviderAdapter | FoldingProviderAdapter;
|
||||
|
||||
export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
|
||||
@@ -800,7 +846,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
heapMonitor: ExtHostHeapService,
|
||||
diagnostics: ExtHostDiagnostics
|
||||
) {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadLanguageFeatures);
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadLanguageFeatures);
|
||||
this._documents = documents;
|
||||
this._commands = commands;
|
||||
this._heapService = heapMonitor;
|
||||
@@ -826,17 +872,22 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
return callback(<any>adapter);
|
||||
}
|
||||
|
||||
private _addNewAdapter(adapter: Adapter): number {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter.set(handle, adapter);
|
||||
return handle;
|
||||
}
|
||||
|
||||
// --- outline
|
||||
|
||||
registerDocumentSymbolProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentSymbolProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter.set(handle, new OutlineAdapter(this._documents, provider));
|
||||
const handle = this._addNewAdapter(new OutlineAdapter(this._documents, provider));
|
||||
this._proxy.$registerOutlineSupport(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideDocumentSymbols(handle: number, resource: URI): TPromise<modes.SymbolInformation[]> {
|
||||
return this._withAdapter(handle, OutlineAdapter, adapter => adapter.provideDocumentSymbols(resource));
|
||||
$provideDocumentSymbols(handle: number, resource: UriComponents): TPromise<SymbolInformationDto[]> {
|
||||
return this._withAdapter(handle, OutlineAdapter, adapter => adapter.provideDocumentSymbols(URI.revive(resource)));
|
||||
}
|
||||
|
||||
// --- code lens
|
||||
@@ -857,150 +908,140 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
return result;
|
||||
}
|
||||
|
||||
$provideCodeLenses(handle: number, resource: URI): TPromise<modes.ICodeLensSymbol[]> {
|
||||
return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.provideCodeLenses(resource));
|
||||
$provideCodeLenses(handle: number, resource: UriComponents): TPromise<modes.ICodeLensSymbol[]> {
|
||||
return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.provideCodeLenses(URI.revive(resource)));
|
||||
}
|
||||
|
||||
$resolveCodeLens(handle: number, resource: URI, symbol: modes.ICodeLensSymbol): TPromise<modes.ICodeLensSymbol> {
|
||||
return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.resolveCodeLens(resource, symbol));
|
||||
$resolveCodeLens(handle: number, resource: UriComponents, symbol: modes.ICodeLensSymbol): TPromise<modes.ICodeLensSymbol> {
|
||||
return this._withAdapter(handle, CodeLensAdapter, adapter => adapter.resolveCodeLens(URI.revive(resource), symbol));
|
||||
}
|
||||
|
||||
// --- declaration
|
||||
|
||||
registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter.set(handle, new DefinitionAdapter(this._documents, provider));
|
||||
const handle = this._addNewAdapter(new DefinitionAdapter(this._documents, provider));
|
||||
this._proxy.$registerDeclaractionSupport(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideDefinition(handle: number, resource: URI, position: IPosition): TPromise<modes.Definition> {
|
||||
return this._withAdapter(handle, DefinitionAdapter, adapter => adapter.provideDefinition(resource, position));
|
||||
$provideDefinition(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.Definition> {
|
||||
return this._withAdapter(handle, DefinitionAdapter, adapter => adapter.provideDefinition(URI.revive(resource), position));
|
||||
}
|
||||
|
||||
registerImplementationProvider(selector: vscode.DocumentSelector, provider: vscode.ImplementationProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter.set(handle, new ImplementationAdapter(this._documents, provider));
|
||||
const handle = this._addNewAdapter(new ImplementationAdapter(this._documents, provider));
|
||||
this._proxy.$registerImplementationSupport(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideImplementation(handle: number, resource: URI, position: IPosition): TPromise<modes.Definition> {
|
||||
return this._withAdapter(handle, ImplementationAdapter, adapter => adapter.provideImplementation(resource, position));
|
||||
$provideImplementation(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.Definition> {
|
||||
return this._withAdapter(handle, ImplementationAdapter, adapter => adapter.provideImplementation(URI.revive(resource), position));
|
||||
}
|
||||
|
||||
registerTypeDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.TypeDefinitionProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter.set(handle, new TypeDefinitionAdapter(this._documents, provider));
|
||||
const handle = this._addNewAdapter(new TypeDefinitionAdapter(this._documents, provider));
|
||||
this._proxy.$registerTypeDefinitionSupport(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideTypeDefinition(handle: number, resource: URI, position: IPosition): TPromise<modes.Definition> {
|
||||
return this._withAdapter(handle, TypeDefinitionAdapter, adapter => adapter.provideTypeDefinition(resource, position));
|
||||
$provideTypeDefinition(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.Definition> {
|
||||
return this._withAdapter(handle, TypeDefinitionAdapter, adapter => adapter.provideTypeDefinition(URI.revive(resource), position));
|
||||
}
|
||||
|
||||
// --- extra info
|
||||
|
||||
registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider, extensionId?: string): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter.set(handle, new HoverAdapter(this._documents, provider));
|
||||
const handle = this._addNewAdapter(new HoverAdapter(this._documents, provider));
|
||||
this._proxy.$registerHoverProvider(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideHover(handle: number, resource: URI, position: IPosition): TPromise<modes.Hover> {
|
||||
return this._withAdapter(handle, HoverAdapter, adpater => adpater.provideHover(resource, position));
|
||||
$provideHover(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.Hover> {
|
||||
return this._withAdapter(handle, HoverAdapter, adpater => adpater.provideHover(URI.revive(resource), position));
|
||||
}
|
||||
|
||||
// --- occurrences
|
||||
|
||||
registerDocumentHighlightProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentHighlightProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter.set(handle, new DocumentHighlightAdapter(this._documents, provider));
|
||||
const handle = this._addNewAdapter(new DocumentHighlightAdapter(this._documents, provider));
|
||||
this._proxy.$registerDocumentHighlightProvider(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideDocumentHighlights(handle: number, resource: URI, position: IPosition): TPromise<modes.DocumentHighlight[]> {
|
||||
return this._withAdapter(handle, DocumentHighlightAdapter, adapter => adapter.provideDocumentHighlights(resource, position));
|
||||
$provideDocumentHighlights(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.DocumentHighlight[]> {
|
||||
return this._withAdapter(handle, DocumentHighlightAdapter, adapter => adapter.provideDocumentHighlights(URI.revive(resource), position));
|
||||
}
|
||||
|
||||
// --- references
|
||||
|
||||
registerReferenceProvider(selector: vscode.DocumentSelector, provider: vscode.ReferenceProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter.set(handle, new ReferenceAdapter(this._documents, provider));
|
||||
const handle = this._addNewAdapter(new ReferenceAdapter(this._documents, provider));
|
||||
this._proxy.$registerReferenceSupport(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideReferences(handle: number, resource: URI, position: IPosition, context: modes.ReferenceContext): TPromise<modes.Location[]> {
|
||||
return this._withAdapter(handle, ReferenceAdapter, adapter => adapter.provideReferences(resource, position, context));
|
||||
$provideReferences(handle: number, resource: UriComponents, position: IPosition, context: modes.ReferenceContext): TPromise<modes.Location[]> {
|
||||
return this._withAdapter(handle, ReferenceAdapter, adapter => adapter.provideReferences(URI.revive(resource), position, context));
|
||||
}
|
||||
|
||||
// --- quick fix
|
||||
|
||||
registerCodeActionProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter.set(handle, new CodeActionAdapter(this._documents, this._commands.converter, this._diagnostics, provider));
|
||||
const handle = this._addNewAdapter(new CodeActionAdapter(this._documents, this._commands.converter, this._diagnostics, provider));
|
||||
this._proxy.$registerQuickFixSupport(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideCodeActions(handle: number, resource: URI, range: IRange): TPromise<modes.CodeAction[]> {
|
||||
return this._withAdapter(handle, CodeActionAdapter, adapter => adapter.provideCodeActions(resource, range));
|
||||
|
||||
$provideCodeActions(handle: number, resource: UriComponents, range: IRange, context: modes.CodeActionContext): TPromise<CodeActionDto[]> {
|
||||
return this._withAdapter(handle, CodeActionAdapter, adapter => adapter.provideCodeActions(URI.revive(resource), range, context));
|
||||
}
|
||||
|
||||
// --- formatting
|
||||
|
||||
registerDocumentFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentFormattingEditProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter.set(handle, new DocumentFormattingAdapter(this._documents, provider));
|
||||
const handle = this._addNewAdapter(new DocumentFormattingAdapter(this._documents, provider));
|
||||
this._proxy.$registerDocumentFormattingSupport(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideDocumentFormattingEdits(handle: number, resource: URI, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
|
||||
return this._withAdapter(handle, DocumentFormattingAdapter, adapter => adapter.provideDocumentFormattingEdits(resource, options));
|
||||
$provideDocumentFormattingEdits(handle: number, resource: UriComponents, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
|
||||
return this._withAdapter(handle, DocumentFormattingAdapter, adapter => adapter.provideDocumentFormattingEdits(URI.revive(resource), options));
|
||||
}
|
||||
|
||||
registerDocumentRangeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentRangeFormattingEditProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter.set(handle, new RangeFormattingAdapter(this._documents, provider));
|
||||
const handle = this._addNewAdapter(new RangeFormattingAdapter(this._documents, provider));
|
||||
this._proxy.$registerRangeFormattingSupport(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideDocumentRangeFormattingEdits(handle: number, resource: URI, range: IRange, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
|
||||
return this._withAdapter(handle, RangeFormattingAdapter, adapter => adapter.provideDocumentRangeFormattingEdits(resource, range, options));
|
||||
$provideDocumentRangeFormattingEdits(handle: number, resource: UriComponents, range: IRange, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
|
||||
return this._withAdapter(handle, RangeFormattingAdapter, adapter => adapter.provideDocumentRangeFormattingEdits(URI.revive(resource), range, options));
|
||||
}
|
||||
|
||||
registerOnTypeFormattingEditProvider(selector: vscode.DocumentSelector, provider: vscode.OnTypeFormattingEditProvider, triggerCharacters: string[]): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter.set(handle, new OnTypeFormattingAdapter(this._documents, provider));
|
||||
const handle = this._addNewAdapter(new OnTypeFormattingAdapter(this._documents, provider));
|
||||
this._proxy.$registerOnTypeFormattingSupport(handle, selector, triggerCharacters);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideOnTypeFormattingEdits(handle: number, resource: URI, position: IPosition, ch: string, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
|
||||
return this._withAdapter(handle, OnTypeFormattingAdapter, adapter => adapter.provideOnTypeFormattingEdits(resource, position, ch, options));
|
||||
$provideOnTypeFormattingEdits(handle: number, resource: UriComponents, position: IPosition, ch: string, options: modes.FormattingOptions): TPromise<ISingleEditOperation[]> {
|
||||
return this._withAdapter(handle, OnTypeFormattingAdapter, adapter => adapter.provideOnTypeFormattingEdits(URI.revive(resource), position, ch, options));
|
||||
}
|
||||
|
||||
// --- navigate types
|
||||
|
||||
registerWorkspaceSymbolProvider(provider: vscode.WorkspaceSymbolProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter.set(handle, new NavigateTypeAdapter(provider));
|
||||
const handle = this._addNewAdapter(new NavigateTypeAdapter(provider));
|
||||
this._proxy.$registerNavigateTypeSupport(handle);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideWorkspaceSymbols(handle: number, search: string): TPromise<IWorkspaceSymbols> {
|
||||
$provideWorkspaceSymbols(handle: number, search: string): TPromise<WorkspaceSymbolsDto> {
|
||||
return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.provideWorkspaceSymbols(search));
|
||||
}
|
||||
|
||||
$resolveWorkspaceSymbol(handle: number, symbol: IWorkspaceSymbol): TPromise<IWorkspaceSymbol> {
|
||||
$resolveWorkspaceSymbol(handle: number, symbol: SymbolInformationDto): TPromise<SymbolInformationDto> {
|
||||
return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.resolveWorkspaceSymbol(symbol));
|
||||
}
|
||||
|
||||
@@ -1010,32 +1051,34 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
|
||||
// --- rename
|
||||
|
||||
registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter.set(handle, new RenameAdapter(this._documents, provider));
|
||||
this._proxy.$registerRenameSupport(handle, selector);
|
||||
registerRenameProvider(selector: vscode.DocumentSelector, provider: vscode.RenameProvider, canUseProposedApi = false): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new RenameAdapter(this._documents, provider));
|
||||
this._proxy.$registerRenameSupport(handle, selector, canUseProposedApi && RenameAdapter.supportsResolving(provider));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideRenameEdits(handle: number, resource: URI, position: IPosition, newName: string): TPromise<modes.WorkspaceEdit> {
|
||||
return this._withAdapter(handle, RenameAdapter, adapter => adapter.provideRenameEdits(resource, position, newName));
|
||||
$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string): TPromise<modes.WorkspaceEdit> {
|
||||
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));
|
||||
}
|
||||
|
||||
// --- suggestion
|
||||
|
||||
registerCompletionItemProvider(selector: vscode.DocumentSelector, provider: vscode.CompletionItemProvider, triggerCharacters: string[]): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter.set(handle, new SuggestAdapter(this._documents, this._commands.converter, provider));
|
||||
const handle = this._addNewAdapter(new SuggestAdapter(this._documents, this._commands.converter, provider));
|
||||
this._proxy.$registerSuggestSupport(handle, selector, triggerCharacters, SuggestAdapter.supportsResolving(provider));
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideCompletionItems(handle: number, resource: URI, position: IPosition, context: modes.SuggestContext): TPromise<IExtHostSuggestResult> {
|
||||
return this._withAdapter(handle, SuggestAdapter, adapter => adapter.provideCompletionItems(resource, position, context));
|
||||
$provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.SuggestContext): TPromise<SuggestResultDto> {
|
||||
return this._withAdapter(handle, SuggestAdapter, adapter => adapter.provideCompletionItems(URI.revive(resource), position, context));
|
||||
}
|
||||
|
||||
$resolveCompletionItem(handle: number, resource: URI, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion> {
|
||||
return this._withAdapter(handle, SuggestAdapter, adapter => adapter.resolveCompletionItem(resource, position, suggestion));
|
||||
$resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, suggestion: modes.ISuggestion): TPromise<modes.ISuggestion> {
|
||||
return this._withAdapter(handle, SuggestAdapter, adapter => adapter.resolveCompletionItem(URI.revive(resource), position, suggestion));
|
||||
}
|
||||
|
||||
$releaseCompletionItems(handle: number, id: number): void {
|
||||
@@ -1045,27 +1088,25 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
// --- parameter hints
|
||||
|
||||
registerSignatureHelpProvider(selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, triggerCharacters: string[]): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter.set(handle, new SignatureHelpAdapter(this._documents, provider));
|
||||
const handle = this._addNewAdapter(new SignatureHelpAdapter(this._documents, provider));
|
||||
this._proxy.$registerSignatureHelpProvider(handle, selector, triggerCharacters);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideSignatureHelp(handle: number, resource: URI, position: IPosition): TPromise<modes.SignatureHelp> {
|
||||
return this._withAdapter(handle, SignatureHelpAdapter, adapter => adapter.provideSignatureHelp(resource, position));
|
||||
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.SignatureHelp> {
|
||||
return this._withAdapter(handle, SignatureHelpAdapter, adapter => adapter.provideSignatureHelp(URI.revive(resource), position));
|
||||
}
|
||||
|
||||
// --- links
|
||||
|
||||
registerDocumentLinkProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentLinkProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter.set(handle, new LinkProviderAdapter(this._documents, this._heapService, provider));
|
||||
const handle = this._addNewAdapter(new LinkProviderAdapter(this._documents, this._heapService, provider));
|
||||
this._proxy.$registerDocumentLinkProvider(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideDocumentLinks(handle: number, resource: URI): TPromise<modes.ILink[]> {
|
||||
return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.provideLinks(resource));
|
||||
$provideDocumentLinks(handle: number, resource: UriComponents): TPromise<modes.ILink[]> {
|
||||
return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.provideLinks(URI.revive(resource)));
|
||||
}
|
||||
|
||||
$resolveDocumentLink(handle: number, link: modes.ILink): TPromise<modes.ILink> {
|
||||
@@ -1073,22 +1114,77 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
}
|
||||
|
||||
registerColorProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable {
|
||||
const handle = this._nextHandle();
|
||||
this._adapter.set(handle, new ColorProviderAdapter(this._documents, provider));
|
||||
const handle = this._addNewAdapter(new ColorProviderAdapter(this._documents, provider));
|
||||
this._proxy.$registerDocumentColorProvider(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideDocumentColors(handle: number, resource: URI): TPromise<IRawColorInfo[]> {
|
||||
return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColors(resource));
|
||||
$provideDocumentColors(handle: number, resource: UriComponents): TPromise<IRawColorInfo[]> {
|
||||
return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColors(URI.revive(resource)));
|
||||
}
|
||||
|
||||
$provideColorPresentations(handle: number, resource: URI, colorInfo: IRawColorInfo): TPromise<modes.IColorPresentation[]> {
|
||||
return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColorPresentations(resource, colorInfo));
|
||||
$provideColorPresentations(handle: number, resource: UriComponents, colorInfo: IRawColorInfo): TPromise<modes.IColorPresentation[]> {
|
||||
return this._withAdapter(handle, ColorProviderAdapter, adapter => adapter.provideColorPresentations(URI.revive(resource), colorInfo));
|
||||
}
|
||||
|
||||
registerFoldingProvider(selector: vscode.DocumentSelector, provider: vscode.FoldingProvider): vscode.Disposable {
|
||||
const handle = this._addNewAdapter(new FoldingProviderAdapter(this._documents, provider));
|
||||
this._proxy.$registerFoldingProvider(handle, selector);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
|
||||
$provideFoldingRanges(handle: number, resource: UriComponents): TPromise<modes.IFoldingRangeList> {
|
||||
return this._withAdapter(handle, FoldingProviderAdapter, adapter => adapter.provideFoldingRanges(URI.revive(resource)));
|
||||
}
|
||||
|
||||
// --- configuration
|
||||
|
||||
private static _serializeRegExp(regExp: RegExp): ISerializedRegExp {
|
||||
if (typeof regExp === 'undefined') {
|
||||
return undefined;
|
||||
}
|
||||
if (regExp === null) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
pattern: regExp.source,
|
||||
flags: (regExp.global ? 'g' : '') + (regExp.ignoreCase ? 'i' : '') + (regExp.multiline ? 'm' : ''),
|
||||
};
|
||||
}
|
||||
|
||||
private static _serializeIndentationRule(indentationRule: vscode.IndentationRule): ISerializedIndentationRule {
|
||||
if (typeof indentationRule === 'undefined') {
|
||||
return undefined;
|
||||
}
|
||||
if (indentationRule === null) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
decreaseIndentPattern: ExtHostLanguageFeatures._serializeRegExp(indentationRule.decreaseIndentPattern),
|
||||
increaseIndentPattern: ExtHostLanguageFeatures._serializeRegExp(indentationRule.increaseIndentPattern),
|
||||
indentNextLinePattern: ExtHostLanguageFeatures._serializeRegExp(indentationRule.indentNextLinePattern),
|
||||
unIndentedLinePattern: ExtHostLanguageFeatures._serializeRegExp(indentationRule.unIndentedLinePattern),
|
||||
};
|
||||
}
|
||||
|
||||
private static _serializeOnEnterRule(onEnterRule: vscode.OnEnterRule): ISerializedOnEnterRule {
|
||||
return {
|
||||
beforeText: ExtHostLanguageFeatures._serializeRegExp(onEnterRule.beforeText),
|
||||
afterText: ExtHostLanguageFeatures._serializeRegExp(onEnterRule.afterText),
|
||||
action: onEnterRule.action
|
||||
};
|
||||
}
|
||||
|
||||
private static _serializeOnEnterRules(onEnterRules: vscode.OnEnterRule[]): ISerializedOnEnterRule[] {
|
||||
if (typeof onEnterRules === 'undefined') {
|
||||
return undefined;
|
||||
}
|
||||
if (onEnterRules === null) {
|
||||
return null;
|
||||
}
|
||||
return onEnterRules.map(ExtHostLanguageFeatures._serializeOnEnterRule);
|
||||
}
|
||||
|
||||
setLanguageConfiguration(languageId: string, configuration: vscode.LanguageConfiguration): vscode.Disposable {
|
||||
let { wordPattern } = configuration;
|
||||
|
||||
@@ -1105,7 +1201,16 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
|
||||
}
|
||||
|
||||
const handle = this._nextHandle();
|
||||
this._proxy.$setLanguageConfiguration(handle, languageId, configuration);
|
||||
const serializedConfiguration: ISerializedLanguageConfiguration = {
|
||||
comments: configuration.comments,
|
||||
brackets: configuration.brackets,
|
||||
wordPattern: ExtHostLanguageFeatures._serializeRegExp(configuration.wordPattern),
|
||||
indentationRules: ExtHostLanguageFeatures._serializeIndentationRule(configuration.indentationRules),
|
||||
onEnterRules: ExtHostLanguageFeatures._serializeOnEnterRules(configuration.onEnterRules),
|
||||
__electricCharacterSupport: configuration.__electricCharacterSupport,
|
||||
__characterPairSupport: configuration.__characterPairSupport,
|
||||
};
|
||||
this._proxy.$setLanguageConfiguration(handle, languageId, serializedConfiguration);
|
||||
return this._createDisposable(handle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,10 @@ export class ExtHostLanguages {
|
||||
constructor(
|
||||
mainContext: IMainContext
|
||||
) {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadLanguages);
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadLanguages);
|
||||
}
|
||||
|
||||
getLanguages(): TPromise<string[]> {
|
||||
return this._proxy.$getLanguages();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
103
src/vs/workbench/api/node/extHostLogService.ts
Normal file
103
src/vs/workbench/api/node/extHostLogService.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 * 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';
|
||||
|
||||
|
||||
export class ExtHostLogService extends DelegatedLogService implements ILogService, ExtHostLogServiceShape {
|
||||
|
||||
private _loggers: Map<string, ExtHostLogger> = new Map();
|
||||
|
||||
constructor(
|
||||
private _windowId: number,
|
||||
logLevel: LogLevel,
|
||||
private _environmentService: IEnvironmentService
|
||||
) {
|
||||
super(createSpdLogService(`exthost${_windowId}`, logLevel, _environmentService.logsPath));
|
||||
}
|
||||
|
||||
$setLevel(level: LogLevel): void {
|
||||
this.setLevel(level);
|
||||
}
|
||||
|
||||
getExtLogger(extensionID: string): ExtHostLogger {
|
||||
let logger = this._loggers.get(extensionID);
|
||||
if (!logger) {
|
||||
logger = this.createLogger(extensionID);
|
||||
this._loggers.set(extensionID, logger);
|
||||
}
|
||||
return logger;
|
||||
}
|
||||
|
||||
private createLogger(extensionID: string): ExtHostLogger {
|
||||
const logsDirPath = join(this._environmentService.logsPath, `${extensionID}_${this._windowId}`);
|
||||
const logService = createSpdLogService(extensionID, this.getLevel(), logsDirPath);
|
||||
this._register(this.onDidChangeLogLevel(level => logService.setLevel(level)));
|
||||
return new ExtHostLogger(logService, logsDirPath);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
});
|
||||
}
|
||||
|
||||
trace(message: string, ...args: any[]): void {
|
||||
return this._logService.trace(message, ...args);
|
||||
}
|
||||
|
||||
debug(message: string, ...args: any[]): void {
|
||||
return this._logService.debug(message, ...args);
|
||||
}
|
||||
|
||||
info(message: string, ...args: any[]): void {
|
||||
return this._logService.info(message, ...args);
|
||||
}
|
||||
|
||||
warn(message: string, ...args: any[]): void {
|
||||
return this._logService.warn(message, ...args);
|
||||
}
|
||||
|
||||
error(message: string | Error, ...args: any[]): void {
|
||||
return this._logService.error(message, ...args);
|
||||
}
|
||||
|
||||
critical(message: string | Error, ...args: any[]): void {
|
||||
return this._logService.critical(message, ...args);
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
import Severity from 'vs/base/common/severity';
|
||||
import vscode = require('vscode');
|
||||
import { MainContext, MainThreadMessageServiceShape, MainThreadMessageOptions, IMainContext } from './extHost.protocol';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
|
||||
|
||||
function isMessageItem(item: any): item is vscode.MessageItem {
|
||||
return item && item.title;
|
||||
@@ -18,7 +18,7 @@ export class ExtHostMessageService {
|
||||
private _proxy: MainThreadMessageServiceShape;
|
||||
|
||||
constructor(mainContext: IMainContext) {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadMessageService);
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadMessageService);
|
||||
}
|
||||
|
||||
showMessage(extension: IExtensionDescription, severity: Severity, message: string, optionsOrFirstItem: vscode.MessageOptions | string, rest: string[]): Thenable<string | undefined>;
|
||||
|
||||
@@ -35,18 +35,22 @@ export class ExtHostOutputChannel implements vscode.OutputChannel {
|
||||
}
|
||||
|
||||
append(value: string): void {
|
||||
this.validate();
|
||||
this._proxy.$append(this._id, this._name, value);
|
||||
}
|
||||
|
||||
appendLine(value: string): void {
|
||||
this.validate();
|
||||
this.append(value + '\n');
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
this.validate();
|
||||
this._proxy.$clear(this._id, this._name);
|
||||
}
|
||||
|
||||
show(columnOrPreserveFocus?: vscode.ViewColumn | boolean, preserveFocus?: boolean): void {
|
||||
this.validate();
|
||||
if (typeof columnOrPreserveFocus === 'boolean') {
|
||||
preserveFocus = columnOrPreserveFocus;
|
||||
}
|
||||
@@ -55,8 +59,15 @@ export class ExtHostOutputChannel implements vscode.OutputChannel {
|
||||
}
|
||||
|
||||
hide(): void {
|
||||
this.validate();
|
||||
this._proxy.$close(this._id);
|
||||
}
|
||||
|
||||
private validate(): void {
|
||||
if (this._disposed) {
|
||||
throw new Error('Channel has been closed');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostOutputService {
|
||||
@@ -64,7 +75,7 @@ export class ExtHostOutputService {
|
||||
private _proxy: MainThreadOutputServiceShape;
|
||||
|
||||
constructor(mainContext: IMainContext) {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadOutputService);
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadOutputService);
|
||||
}
|
||||
|
||||
createOutputChannel(name: string): vscode.OutputChannel {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import { Progress, ProgressOptions, CancellationToken } from 'vscode';
|
||||
import { MainThreadProgressShape } from './extHost.protocol';
|
||||
import { ProgressLocation } from './extHostTypeConverters';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IProgressStep } from 'vs/platform/progress/common/progress';
|
||||
|
||||
export class ExtHostProgress {
|
||||
|
||||
@@ -24,7 +24,7 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
|
||||
private _validateInput: (input: string) => string | Thenable<string>;
|
||||
|
||||
constructor(mainContext: IMainContext, workspace: ExtHostWorkspace, commands: ExtHostCommands) {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadQuickOpen);
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadQuickOpen);
|
||||
this._workspace = workspace;
|
||||
this._commands = commands;
|
||||
}
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import URI from 'vs/base/common/uri';
|
||||
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 { debounce } from 'vs/base/common/decorators';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { asWinJsPromise } from 'vs/base/common/async';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
|
||||
import { MainContext, MainThreadSCMShape, SCMRawResource, SCMRawResourceSplice, SCMRawResourceSplices, IMainContext } from './extHost.protocol';
|
||||
import { MainContext, MainThreadSCMShape, SCMRawResource, SCMRawResourceSplice, SCMRawResourceSplices, IMainContext, ExtHostSCMShape } from './extHost.protocol';
|
||||
import { sortedDiff } from 'vs/base/common/arrays';
|
||||
import { comparePaths } from 'vs/base/common/comparers';
|
||||
import * as vscode from 'vscode';
|
||||
@@ -93,7 +93,7 @@ function compareResourceStatesDecorations(a: vscode.SourceControlResourceDecorat
|
||||
}
|
||||
|
||||
function compareResourceStates(a: vscode.SourceControlResourceState, b: vscode.SourceControlResourceState): number {
|
||||
let result = comparePaths(a.resourceUri.fsPath, b.resourceUri.fsPath);
|
||||
let result = comparePaths(a.resourceUri.fsPath, b.resourceUri.fsPath, true);
|
||||
|
||||
if (result !== 0) {
|
||||
return result;
|
||||
@@ -110,7 +110,11 @@ function compareResourceStates(a: vscode.SourceControlResourceState, b: vscode.S
|
||||
return result;
|
||||
}
|
||||
|
||||
export class ExtHostSCMInputBox {
|
||||
export interface IValidateInput {
|
||||
(value: string, cursorPosition: number): vscode.ProviderResult<vscode.SourceControlInputBoxValidation | undefined | null>;
|
||||
}
|
||||
|
||||
export class ExtHostSCMInputBox implements vscode.SourceControlInputBox {
|
||||
|
||||
private _value: string = '';
|
||||
|
||||
@@ -140,7 +144,31 @@ export class ExtHostSCMInputBox {
|
||||
this._placeholder = placeholder;
|
||||
}
|
||||
|
||||
constructor(private _proxy: MainThreadSCMShape, private _sourceControlHandle: number) {
|
||||
private _validateInput: IValidateInput;
|
||||
|
||||
get validateInput(): IValidateInput {
|
||||
if (!this._extension.enableProposedApi) {
|
||||
throw new Error(`[${this._extension.id}]: Proposed API is only available when running out of dev or with the following command line switch: --enable-proposed-api ${this._extension.id}`);
|
||||
}
|
||||
|
||||
return this._validateInput;
|
||||
}
|
||||
|
||||
set validateInput(fn: IValidateInput) {
|
||||
if (!this._extension.enableProposedApi) {
|
||||
throw new Error(`[${this._extension.id}]: Proposed API is only available when running out of dev or with the following command line switch: --enable-proposed-api ${this._extension.id}`);
|
||||
}
|
||||
|
||||
if (fn && typeof fn !== 'function') {
|
||||
console.warn('Invalid SCM input box validation function');
|
||||
return;
|
||||
}
|
||||
|
||||
this._validateInput = fn;
|
||||
this._proxy.$setValidationProviderIsEnabled(this._sourceControlHandle, !!fn);
|
||||
}
|
||||
|
||||
constructor(private _extension: IExtensionDescription, private _proxy: MainThreadSCMShape, private _sourceControlHandle: number) {
|
||||
// noop
|
||||
}
|
||||
|
||||
@@ -228,7 +256,7 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG
|
||||
const handle = this._resourceHandlePool++;
|
||||
this._resourceStatesMap.set(handle, r);
|
||||
|
||||
const sourceUri = r.resourceUri.toString();
|
||||
const sourceUri = r.resourceUri;
|
||||
const iconPath = getIconPath(r.decorations);
|
||||
const lightIconPath = r.decorations && getIconPath(r.decorations.light) || iconPath;
|
||||
const darkIconPath = r.decorations && getIconPath(r.decorations.dark) || iconPath;
|
||||
@@ -254,7 +282,7 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG
|
||||
const letter = r.decorations && r.decorations.letter || undefined;
|
||||
const color = r.decorations && r.decorations.color || undefined;
|
||||
|
||||
const rawResource = [handle, sourceUri, icons, tooltip, strikeThrough, faded, source, letter, color] as SCMRawResource;
|
||||
const rawResource = [handle, <UriComponents>sourceUri, icons, tooltip, strikeThrough, faded, source, letter, color] as SCMRawResource;
|
||||
|
||||
return { rawResource, handle };
|
||||
});
|
||||
@@ -370,14 +398,15 @@ class ExtHostSourceControl implements vscode.SourceControl {
|
||||
private handle: number = ExtHostSourceControl._handlePool++;
|
||||
|
||||
constructor(
|
||||
_extension: IExtensionDescription,
|
||||
private _proxy: MainThreadSCMShape,
|
||||
private _commands: ExtHostCommands,
|
||||
private _id: string,
|
||||
private _label: string,
|
||||
private _rootUri?: vscode.Uri
|
||||
) {
|
||||
this._inputBox = new ExtHostSCMInputBox(this._proxy, this.handle);
|
||||
this._proxy.$registerSourceControl(this.handle, _id, _label, _rootUri && _rootUri.toString());
|
||||
this._inputBox = new ExtHostSCMInputBox(_extension, this._proxy, this.handle);
|
||||
this._proxy.$registerSourceControl(this.handle, _id, _label, _rootUri);
|
||||
}
|
||||
|
||||
private updatedResourceGroups = new Set<ExtHostSourceControlResourceGroup>();
|
||||
@@ -431,7 +460,7 @@ class ExtHostSourceControl implements vscode.SourceControl {
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostSCM {
|
||||
export class ExtHostSCM implements ExtHostSCMShape {
|
||||
|
||||
private static _handlePool: number = 0;
|
||||
|
||||
@@ -447,7 +476,7 @@ export class ExtHostSCM {
|
||||
private _commands: ExtHostCommands,
|
||||
@ILogService private logService: ILogService
|
||||
) {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadSCM);
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadSCM);
|
||||
|
||||
_commands.registerArgumentProcessor({
|
||||
processArgument: arg => {
|
||||
@@ -492,7 +521,7 @@ export class ExtHostSCM {
|
||||
this.logService.trace('ExtHostSCM#createSourceControl', extension.id, id, label, rootUri);
|
||||
|
||||
const handle = ExtHostSCM._handlePool++;
|
||||
const sourceControl = new ExtHostSourceControl(this._proxy, this._commands, id, label, rootUri);
|
||||
const sourceControl = new ExtHostSourceControl(extension, this._proxy, this._commands, id, label, rootUri);
|
||||
this._sourceControls.set(handle, sourceControl);
|
||||
|
||||
const sourceControls = this._sourceControlsByExtension.get(extension.id) || [];
|
||||
@@ -513,8 +542,9 @@ export class ExtHostSCM {
|
||||
return inputBox;
|
||||
}
|
||||
|
||||
$provideOriginalResource(sourceControlHandle: number, uri: URI): TPromise<URI> {
|
||||
this.logService.trace('ExtHostSCM#$provideOriginalResource', sourceControlHandle, uri);
|
||||
$provideOriginalResource(sourceControlHandle: number, uriComponents: UriComponents): TPromise<UriComponents> {
|
||||
const uri = URI.revive(uriComponents);
|
||||
this.logService.trace('ExtHostSCM#$provideOriginalResource', sourceControlHandle, uri.toString());
|
||||
|
||||
const sourceControl = this._sourceControls.get(sourceControlHandle);
|
||||
|
||||
@@ -522,10 +552,7 @@ export class ExtHostSCM {
|
||||
return TPromise.as(null);
|
||||
}
|
||||
|
||||
return asWinJsPromise(token => {
|
||||
const result = sourceControl.quickDiffProvider.provideOriginalResource(uri, token);
|
||||
return result && URI.parse(result.toString());
|
||||
});
|
||||
return asWinJsPromise(token => sourceControl.quickDiffProvider.provideOriginalResource(uri, token));
|
||||
}
|
||||
|
||||
$onInputBoxValueChange(sourceControlHandle: number, value: string): TPromise<void> {
|
||||
@@ -558,4 +585,26 @@ export class ExtHostSCM {
|
||||
|
||||
await group.$executeResourceCommand(handle);
|
||||
}
|
||||
|
||||
async $validateInput(sourceControlHandle: number, value: string, cursorPosition: number): TPromise<[string, number] | undefined> {
|
||||
this.logService.trace('ExtHostSCM#$validateInput', sourceControlHandle);
|
||||
|
||||
const sourceControl = this._sourceControls.get(sourceControlHandle);
|
||||
|
||||
if (!sourceControl) {
|
||||
return TPromise.as(undefined);
|
||||
}
|
||||
|
||||
if (!sourceControl.inputBox.validateInput) {
|
||||
return TPromise.as(undefined);
|
||||
}
|
||||
|
||||
const result = await sourceControl.inputBox.validateInput(value, cursorPosition);
|
||||
|
||||
if (!result) {
|
||||
return TPromise.as(undefined);
|
||||
}
|
||||
|
||||
return [result.message, result.type];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ export class ExtHostStatusBar {
|
||||
private _statusMessage: StatusBarMessage;
|
||||
|
||||
constructor(mainContext: IMainContext) {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadStatusBar);
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadStatusBar);
|
||||
this._statusMessage = new StatusBarMessage(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ export class ExtHostStorage {
|
||||
private _proxy: MainThreadStorageShape;
|
||||
|
||||
constructor(mainContext: IMainContext) {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadStorage);
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadStorage);
|
||||
}
|
||||
|
||||
getValue<T>(shared: boolean, key: string, defaultValue?: T): TPromise<T> {
|
||||
@@ -22,4 +22,4 @@ export class ExtHostStorage {
|
||||
setValue(shared: boolean, key: string, value: any): TPromise<void> {
|
||||
return this._proxy.$setValue(shared, key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import * as Objects from 'vs/base/common/objects';
|
||||
import { asWinJsPromise } from 'vs/base/common/async';
|
||||
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import * as TaskSystem from 'vs/workbench/parts/tasks/common/tasks';
|
||||
|
||||
import { MainContext, MainThreadTaskShape, ExtHostTaskShape, IMainContext } from 'vs/workbench/api/node/extHost.protocol';
|
||||
@@ -294,11 +294,11 @@ namespace ShellConfiguration {
|
||||
|
||||
namespace Tasks {
|
||||
|
||||
export function from(tasks: vscode.Task[], rootFolder: vscode.WorkspaceFolder, extension: IExtensionDescription): TaskSystem.Task[] {
|
||||
export function from(tasks: vscode.Task[], rootFolder: vscode.WorkspaceFolder, extension: IExtensionDescription): TaskSystem.ContributedTask[] {
|
||||
if (tasks === void 0 || tasks === null) {
|
||||
return [];
|
||||
}
|
||||
let result: TaskSystem.Task[] = [];
|
||||
let result: TaskSystem.ContributedTask[] = [];
|
||||
for (let task of tasks) {
|
||||
let converted = fromSingle(task, rootFolder, extension);
|
||||
if (converted) {
|
||||
@@ -351,7 +351,7 @@ namespace Tasks {
|
||||
// We can't transfer a workspace folder object from the extension host to main since they differ
|
||||
// in shape and we don't have backwards converting function. So transfer the URI and resolve the
|
||||
// workspace folder on the main side.
|
||||
(source as any).__workspaceFolder = workspaceFolder ? workspaceFolder.uri as URI : undefined;
|
||||
(source as any as TaskSystem.ExtensionTaskSourceTransfer).__workspaceFolder = workspaceFolder ? workspaceFolder.uri as URI : undefined;
|
||||
let label = nls.localize('task.label', '{0}: {1}', source.label, task.name);
|
||||
let key = (task as types.Task).definitionKey;
|
||||
let kind = (task as types.Task).definition;
|
||||
@@ -424,7 +424,7 @@ export class ExtHostTask implements ExtHostTaskShape {
|
||||
private _handlers: Map<number, HandlerData>;
|
||||
|
||||
constructor(mainContext: IMainContext, extHostWorkspace: ExtHostWorkspace) {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadTask);
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadTask);
|
||||
this._extHostWorkspace = extHostWorkspace;
|
||||
this._handleCounter = 0;
|
||||
this._handlers = new Map<number, HandlerData>();
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
'use strict';
|
||||
|
||||
import vscode = require('vscode');
|
||||
import { TPromise, TValueCallback } from 'vs/base/common/winjs.base';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IMainContext } from './extHost.protocol';
|
||||
|
||||
@@ -16,24 +15,26 @@ export class ExtHostTerminal implements vscode.Terminal {
|
||||
private _proxy: MainThreadTerminalServiceShape;
|
||||
private _disposed: boolean;
|
||||
private _queuedRequests: ApiRequest[];
|
||||
private _pidPromise: TPromise<number>;
|
||||
private _pidPromiseComplete: TValueCallback<number>;
|
||||
private _pidPromise: Promise<number>;
|
||||
private _pidPromiseComplete: (value: number) => any;
|
||||
|
||||
constructor(
|
||||
proxy: MainThreadTerminalServiceShape,
|
||||
name?: string,
|
||||
shellPath?: string,
|
||||
shellArgs?: string[],
|
||||
cwd?: string,
|
||||
env?: { [key: string]: string },
|
||||
waitOnExit?: boolean
|
||||
) {
|
||||
this._name = name;
|
||||
this._queuedRequests = [];
|
||||
this._proxy = proxy;
|
||||
this._pidPromise = new TPromise<number>(c => {
|
||||
this._pidPromise = new Promise<number>(c => {
|
||||
this._pidPromiseComplete = c;
|
||||
});
|
||||
this._proxy.$createTerminal(name, shellPath, shellArgs, env, waitOnExit).then((id) => {
|
||||
|
||||
this._proxy.$createTerminal(name, shellPath, shellArgs, cwd, env, waitOnExit).then((id) => {
|
||||
this._id = id;
|
||||
this._queuedRequests.forEach((r) => {
|
||||
r.run(this._proxy, this._id);
|
||||
@@ -103,7 +104,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
|
||||
constructor(mainContext: IMainContext) {
|
||||
this._onDidCloseTerminal = new Emitter<vscode.Terminal>();
|
||||
this._proxy = mainContext.get(MainContext.MainThreadTerminalService);
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadTerminalService);
|
||||
this._terminals = [];
|
||||
}
|
||||
|
||||
@@ -114,7 +115,7 @@ export class ExtHostTerminalService implements ExtHostTerminalServiceShape {
|
||||
}
|
||||
|
||||
public createTerminalFromOptions(options: vscode.TerminalOptions): vscode.Terminal {
|
||||
let terminal = new ExtHostTerminal(this._proxy, options.name, options.shellPath, options.shellArgs, options.env/*, options.waitOnExit*/);
|
||||
let terminal = new ExtHostTerminal(this._proxy, options.name, options.shellPath, options.shellArgs, options.cwd, options.env /*, options.waitOnExit*/);
|
||||
this._terminals.push(terminal);
|
||||
return terminal;
|
||||
}
|
||||
@@ -172,4 +173,4 @@ class ApiRequest {
|
||||
public run(proxy: MainThreadTerminalServiceShape, id: number) {
|
||||
this._callback.apply(proxy, [id].concat(this._args));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,9 +11,9 @@ import { IdGenerator } from 'vs/base/common/idGenerator';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { ExtHostDocumentData } from 'vs/workbench/api/node/extHostDocumentData';
|
||||
import { Selection, Range, Position, EndOfLine, TextEditorRevealType, TextEditorLineNumbersStyle, SnippetString } from './extHostTypes';
|
||||
import { ISingleEditOperation } from 'vs/editor/common/editorCommon';
|
||||
import { ISingleEditOperation } from 'vs/editor/common/model';
|
||||
import * as TypeConverters from './extHostTypeConverters';
|
||||
import { MainThreadEditorsShape, IResolvedTextEditorConfiguration, ITextEditorConfigurationUpdate } from './extHost.protocol';
|
||||
import { MainThreadTextEditorsShape, IResolvedTextEditorConfiguration, ITextEditorConfigurationUpdate } from './extHost.protocol';
|
||||
import * as vscode from 'vscode';
|
||||
import { TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions';
|
||||
import { IRange } from 'vs/editor/common/core/range';
|
||||
@@ -22,10 +22,10 @@ export class TextEditorDecorationType implements vscode.TextEditorDecorationType
|
||||
|
||||
private static readonly _Keys = new IdGenerator('TextEditorDecorationType');
|
||||
|
||||
private _proxy: MainThreadEditorsShape;
|
||||
private _proxy: MainThreadTextEditorsShape;
|
||||
public key: string;
|
||||
|
||||
constructor(proxy: MainThreadEditorsShape, options: vscode.DecorationRenderOptions) {
|
||||
constructor(proxy: MainThreadTextEditorsShape, options: vscode.DecorationRenderOptions) {
|
||||
this.key = TextEditorDecorationType._Keys.nextId();
|
||||
this._proxy = proxy;
|
||||
this._proxy.$registerTextEditorDecorationType(this.key, <any>/* URI vs Uri */ options);
|
||||
@@ -141,7 +141,7 @@ function deprecated(name: string, message: string = 'Refer to the documentation
|
||||
|
||||
export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
|
||||
|
||||
private _proxy: MainThreadEditorsShape;
|
||||
private _proxy: MainThreadTextEditorsShape;
|
||||
private _id: string;
|
||||
|
||||
private _tabSize: number;
|
||||
@@ -149,7 +149,7 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
|
||||
private _cursorStyle: TextEditorCursorStyle;
|
||||
private _lineNumbers: TextEditorLineNumbersStyle;
|
||||
|
||||
constructor(proxy: MainThreadEditorsShape, id: string, source: IResolvedTextEditorConfiguration) {
|
||||
constructor(proxy: MainThreadTextEditorsShape, id: string, source: IResolvedTextEditorConfiguration) {
|
||||
this._proxy = proxy;
|
||||
this._id = id;
|
||||
this._accept(source);
|
||||
@@ -313,23 +313,31 @@ export class ExtHostTextEditorOptions implements vscode.TextEditorOptions {
|
||||
|
||||
export class ExtHostTextEditor implements vscode.TextEditor {
|
||||
|
||||
private readonly _proxy: MainThreadEditorsShape;
|
||||
public readonly editorType = 'texteditor';
|
||||
|
||||
private readonly _proxy: MainThreadTextEditorsShape;
|
||||
private readonly _id: string;
|
||||
private readonly _documentData: ExtHostDocumentData;
|
||||
|
||||
private _selections: Selection[];
|
||||
private _options: ExtHostTextEditorOptions;
|
||||
private _visibleRanges: Range[];
|
||||
private _viewColumn: vscode.ViewColumn;
|
||||
private _disposed: boolean = false;
|
||||
|
||||
get id(): string { return this._id; }
|
||||
|
||||
constructor(proxy: MainThreadEditorsShape, id: string, document: ExtHostDocumentData, selections: Selection[], options: IResolvedTextEditorConfiguration, viewColumn: vscode.ViewColumn) {
|
||||
constructor(
|
||||
proxy: MainThreadTextEditorsShape, id: string, document: ExtHostDocumentData,
|
||||
selections: Selection[], options: IResolvedTextEditorConfiguration,
|
||||
visibleRanges: Range[], viewColumn: vscode.ViewColumn
|
||||
) {
|
||||
this._proxy = proxy;
|
||||
this._id = id;
|
||||
this._documentData = document;
|
||||
this._selections = selections;
|
||||
this._options = new ExtHostTextEditorOptions(this._proxy, this._id, options);
|
||||
this._visibleRanges = visibleRanges;
|
||||
this._viewColumn = viewColumn;
|
||||
}
|
||||
|
||||
@@ -373,6 +381,21 @@ export class ExtHostTextEditor implements vscode.TextEditor {
|
||||
this._options._accept(options);
|
||||
}
|
||||
|
||||
// ---- visible ranges
|
||||
|
||||
get visibleRanges(): Range[] {
|
||||
return this._visibleRanges;
|
||||
}
|
||||
|
||||
set visibleRanges(value: Range[]) {
|
||||
throw readonly('visibleRanges');
|
||||
}
|
||||
|
||||
_acceptVisibleRanges(value: Range[]): void {
|
||||
ok(!this._disposed);
|
||||
this._visibleRanges = value;
|
||||
}
|
||||
|
||||
// ---- view column
|
||||
|
||||
get viewColumn(): vscode.ViewColumn {
|
||||
@@ -435,7 +458,7 @@ export class ExtHostTextEditor implements vscode.TextEditor {
|
||||
return this._proxy.$trySetDecorationsFast(
|
||||
this._id,
|
||||
decorationType.key,
|
||||
/*TODO: marshaller is too slow*/JSON.stringify(_ranges)
|
||||
_ranges
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,32 +12,34 @@ import * as TypeConverters from './extHostTypeConverters';
|
||||
import { TextEditorDecorationType, ExtHostTextEditor } from './extHostTextEditor';
|
||||
import { ExtHostDocumentsAndEditors } from './extHostDocumentsAndEditors';
|
||||
import { Position as EditorPosition } from 'vs/platform/editor/common/editor';
|
||||
import { MainContext, MainThreadEditorsShape, ExtHostEditorsShape, ITextDocumentShowOptions, ITextEditorPositionData, IResolvedTextEditorConfiguration, ISelectionChangeEvent, IMainContext, IWorkspaceResourceEdit } from './extHost.protocol';
|
||||
import { MainContext, MainThreadTextEditorsShape, ExtHostEditorsShape, ITextDocumentShowOptions, ITextEditorPositionData, IMainContext, WorkspaceEditDto, IEditorPropertiesChangeData } from './extHost.protocol';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
export class ExtHostEditors implements ExtHostEditorsShape {
|
||||
|
||||
private readonly _onDidChangeTextEditorSelection = new Emitter<vscode.TextEditorSelectionChangeEvent>();
|
||||
private readonly _onDidChangeTextEditorOptions = new Emitter<vscode.TextEditorOptionsChangeEvent>();
|
||||
private readonly _onDidChangeTextEditorVisibleRanges = new Emitter<vscode.TextEditorVisibleRangesChangeEvent>();
|
||||
private readonly _onDidChangeTextEditorViewColumn = new Emitter<vscode.TextEditorViewColumnChangeEvent>();
|
||||
private readonly _onDidChangeActiveTextEditor = new Emitter<vscode.TextEditor | undefined>();
|
||||
private readonly _onDidChangeVisibleTextEditors = new Emitter<vscode.TextEditor[]>();
|
||||
|
||||
readonly onDidChangeTextEditorSelection: Event<vscode.TextEditorSelectionChangeEvent> = this._onDidChangeTextEditorSelection.event;
|
||||
readonly onDidChangeTextEditorOptions: Event<vscode.TextEditorOptionsChangeEvent> = this._onDidChangeTextEditorOptions.event;
|
||||
readonly onDidChangeTextEditorVisibleRanges: Event<vscode.TextEditorVisibleRangesChangeEvent> = this._onDidChangeTextEditorVisibleRanges.event;
|
||||
readonly onDidChangeTextEditorViewColumn: Event<vscode.TextEditorViewColumnChangeEvent> = this._onDidChangeTextEditorViewColumn.event;
|
||||
readonly onDidChangeActiveTextEditor: Event<vscode.TextEditor | undefined> = this._onDidChangeActiveTextEditor.event;
|
||||
readonly onDidChangeVisibleTextEditors: Event<vscode.TextEditor[]> = this._onDidChangeVisibleTextEditors.event;
|
||||
|
||||
|
||||
private _proxy: MainThreadEditorsShape;
|
||||
private _proxy: MainThreadTextEditorsShape;
|
||||
private _extHostDocumentsAndEditors: ExtHostDocumentsAndEditors;
|
||||
|
||||
constructor(
|
||||
mainContext: IMainContext,
|
||||
extHostDocumentsAndEditors: ExtHostDocumentsAndEditors,
|
||||
) {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadEditors);
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadTextEditors);
|
||||
this._extHostDocumentsAndEditors = extHostDocumentsAndEditors;
|
||||
|
||||
this._extHostDocumentsAndEditors.onDidChangeVisibleTextEditors(e => this._onDidChangeVisibleTextEditors.fire(e));
|
||||
@@ -92,59 +94,66 @@ export class ExtHostEditors implements ExtHostEditorsShape {
|
||||
|
||||
applyWorkspaceEdit(edit: vscode.WorkspaceEdit): TPromise<boolean> {
|
||||
|
||||
let workspaceResourceEdits: IWorkspaceResourceEdit[] = [];
|
||||
const dto: WorkspaceEditDto = { edits: [] };
|
||||
|
||||
let entries = edit.entries();
|
||||
for (let entry of entries) {
|
||||
let [uri, edits] = entry;
|
||||
|
||||
let doc = this._extHostDocumentsAndEditors.getDocument(uri.toString());
|
||||
let docVersion: number = undefined;
|
||||
if (doc) {
|
||||
docVersion = doc.version;
|
||||
}
|
||||
|
||||
let workspaceResourceEdit: IWorkspaceResourceEdit = {
|
||||
resource: uri,
|
||||
modelVersionId: docVersion,
|
||||
edits: []
|
||||
};
|
||||
|
||||
for (let edit of edits) {
|
||||
workspaceResourceEdit.edits.push({
|
||||
newText: edit.newText,
|
||||
newEol: TypeConverters.EndOfLine.from(edit.newEol),
|
||||
range: edit.range && TypeConverters.fromRange(edit.range)
|
||||
for (let entry of edit.entries()) {
|
||||
let [uri, uriOrEdits] = entry;
|
||||
if (Array.isArray(uriOrEdits)) {
|
||||
let doc = this._extHostDocumentsAndEditors.getDocument(uri.toString());
|
||||
dto.edits.push({
|
||||
resource: uri,
|
||||
modelVersionId: doc && doc.version,
|
||||
edits: uriOrEdits.map(TypeConverters.TextEdit.from)
|
||||
});
|
||||
// } else {
|
||||
// dto.edits.push({ oldUri: uri, newUri: uriOrEdits });
|
||||
}
|
||||
|
||||
workspaceResourceEdits.push(workspaceResourceEdit);
|
||||
}
|
||||
|
||||
return this._proxy.$tryApplyWorkspaceEdit(workspaceResourceEdits);
|
||||
return this._proxy.$tryApplyWorkspaceEdit(dto);
|
||||
}
|
||||
|
||||
// --- called from main thread
|
||||
|
||||
$acceptOptionsChanged(id: string, opts: IResolvedTextEditorConfiguration): void {
|
||||
let editor = this._extHostDocumentsAndEditors.getEditor(id);
|
||||
editor._acceptOptions(opts);
|
||||
this._onDidChangeTextEditorOptions.fire({
|
||||
textEditor: editor,
|
||||
options: opts
|
||||
});
|
||||
}
|
||||
|
||||
$acceptSelectionsChanged(id: string, event: ISelectionChangeEvent): void {
|
||||
const kind = TextEditorSelectionChangeKind.fromValue(event.source);
|
||||
const selections = event.selections.map(TypeConverters.toSelection);
|
||||
$acceptEditorPropertiesChanged(id: string, data: IEditorPropertiesChangeData): void {
|
||||
const textEditor = this._extHostDocumentsAndEditors.getEditor(id);
|
||||
textEditor._acceptSelections(selections);
|
||||
this._onDidChangeTextEditorSelection.fire({
|
||||
textEditor,
|
||||
selections,
|
||||
kind
|
||||
});
|
||||
|
||||
// (1) set all properties
|
||||
if (data.options) {
|
||||
textEditor._acceptOptions(data.options);
|
||||
}
|
||||
if (data.selections) {
|
||||
const selections = data.selections.selections.map(TypeConverters.toSelection);
|
||||
textEditor._acceptSelections(selections);
|
||||
}
|
||||
if (data.visibleRanges) {
|
||||
const visibleRanges = data.visibleRanges.map(TypeConverters.toRange);
|
||||
textEditor._acceptVisibleRanges(visibleRanges);
|
||||
}
|
||||
|
||||
// (2) fire change events
|
||||
if (data.options) {
|
||||
this._onDidChangeTextEditorOptions.fire({
|
||||
textEditor: textEditor,
|
||||
options: data.options
|
||||
});
|
||||
}
|
||||
if (data.selections) {
|
||||
const kind = TextEditorSelectionChangeKind.fromValue(data.selections.source);
|
||||
const selections = data.selections.selections.map(TypeConverters.toSelection);
|
||||
this._onDidChangeTextEditorSelection.fire({
|
||||
textEditor,
|
||||
selections,
|
||||
kind
|
||||
});
|
||||
}
|
||||
if (data.visibleRanges) {
|
||||
const visibleRanges = data.visibleRanges.map(TypeConverters.toRange);
|
||||
this._onDidChangeTextEditorVisibleRanges.fire({
|
||||
textEditor,
|
||||
visibleRanges
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$acceptEditorPositionData(data: ITextEditorPositionData): void {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import * as vscode from 'vscode';
|
||||
import { basename } from 'vs/base/common/paths';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { debounceEvent } from 'vs/base/common/event';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
@@ -14,6 +15,8 @@ import { ExtHostTreeViewsShape, MainThreadTreeViewsShape } from './extHost.proto
|
||||
import { ITreeItem, TreeViewItemHandleArg } from 'vs/workbench/common/views';
|
||||
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands';
|
||||
import { asWinJsPromise } from 'vs/base/common/async';
|
||||
import { TreeItemCollapsibleState, ThemeIcon } from 'vs/workbench/api/node/extHostTypes';
|
||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||
|
||||
type TreeItemHandle = string;
|
||||
|
||||
@@ -35,10 +38,12 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
|
||||
});
|
||||
}
|
||||
|
||||
registerTreeDataProvider<T>(id: string, treeDataProvider: vscode.TreeDataProvider<T>): vscode.Disposable {
|
||||
const treeView = new ExtHostTreeView<T>(id, treeDataProvider, this._proxy, this.commands.converter);
|
||||
this.treeViews.set(id, treeView);
|
||||
registerTreeDataProvider<T>(id: string, dataProvider: vscode.TreeDataProvider<T>, proposedApiFunction: <U>(fn: U) => U): vscode.TreeView<T> {
|
||||
const treeView = this.createExtHostTreeViewer(id, dataProvider);
|
||||
return {
|
||||
reveal: proposedApiFunction((element: T, options?: { select?: boolean }): Thenable<void> => {
|
||||
return treeView.reveal(element, options);
|
||||
}),
|
||||
dispose: () => {
|
||||
this.treeViews.delete(id);
|
||||
treeView.dispose();
|
||||
@@ -46,14 +51,6 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
|
||||
};
|
||||
}
|
||||
|
||||
$getElements(treeViewId: string): TPromise<ITreeItem[]> {
|
||||
const treeView = this.treeViews.get(treeViewId);
|
||||
if (!treeView) {
|
||||
return TPromise.wrapError<ITreeItem[]>(new Error(localize('treeView.notRegistered', 'No tree view with id \'{0}\' registered.', treeViewId)));
|
||||
}
|
||||
return treeView.getTreeItems();
|
||||
}
|
||||
|
||||
$getChildren(treeViewId: string, treeItemHandle?: string): TPromise<ITreeItem[]> {
|
||||
const treeView = this.treeViews.get(treeViewId);
|
||||
if (!treeView) {
|
||||
@@ -62,6 +59,12 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
|
||||
return treeView.getChildren(treeItemHandle);
|
||||
}
|
||||
|
||||
private createExtHostTreeViewer<T>(id: string, dataProvider: vscode.TreeDataProvider<T>): ExtHostTreeView<T> {
|
||||
const treeView = new ExtHostTreeView<T>(id, dataProvider, this._proxy, this.commands.converter);
|
||||
this.treeViews.set(id, treeView);
|
||||
return treeView;
|
||||
}
|
||||
|
||||
private convertArgument(arg: TreeViewItemHandleArg): any {
|
||||
const treeView = this.treeViews.get(arg.$treeViewId);
|
||||
return treeView ? treeView.getExtensionElement(arg.$treeItemHandle) : null;
|
||||
@@ -69,124 +72,254 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
|
||||
}
|
||||
|
||||
interface TreeNode {
|
||||
index: number;
|
||||
handle: TreeItemHandle;
|
||||
parent: TreeItemHandle;
|
||||
children: TreeItemHandle[];
|
||||
item: ITreeItem;
|
||||
parent: TreeNode;
|
||||
children: TreeNode[];
|
||||
}
|
||||
|
||||
class ExtHostTreeView<T> extends Disposable {
|
||||
|
||||
private static ROOT_HANDLE = '0';
|
||||
private static LABEL_HANDLE_PREFIX = '0';
|
||||
private static ID_HANDLE_PREFIX = '1';
|
||||
|
||||
private roots: TreeNode[] = null;
|
||||
private elements: Map<TreeItemHandle, T> = new Map<TreeItemHandle, T>();
|
||||
private nodes: Map<T, TreeNode> = new Map<T, TreeNode>();
|
||||
|
||||
constructor(private viewId: string, private dataProvider: vscode.TreeDataProvider<T>, private proxy: MainThreadTreeViewsShape, private commands: CommandsConverter) {
|
||||
super();
|
||||
this.proxy.$registerView(viewId);
|
||||
if (dataProvider.onDidChangeTreeData) {
|
||||
this._register(debounceEvent<T, T[]>(dataProvider.onDidChangeTreeData, (last, current) => last ? [...last, current] : [current], 200)(elements => this._refresh(elements)));
|
||||
this.proxy.$registerTreeViewDataProvider(viewId);
|
||||
if (this.dataProvider.onDidChangeTreeData) {
|
||||
this._register(debounceEvent<T, T[]>(this.dataProvider.onDidChangeTreeData, (last, current) => last ? [...last, current] : [current], 200)(elements => this.refresh(elements)));
|
||||
}
|
||||
}
|
||||
|
||||
getTreeItems(): TPromise<ITreeItem[]> {
|
||||
this.clearAll();
|
||||
return asWinJsPromise(() => this.dataProvider.getChildren())
|
||||
.then(elements => this.resolveElements(elements));
|
||||
}
|
||||
|
||||
getChildren(treeItemHandle: TreeItemHandle): TPromise<ITreeItem[]> {
|
||||
let extElement = this.getExtensionElement(treeItemHandle);
|
||||
if (extElement) {
|
||||
this.clearChildren(extElement);
|
||||
} else {
|
||||
return TPromise.wrapError<ITreeItem[]>(new Error(localize('treeItem.notFound', 'No tree item with id \'{0}\' found.', treeItemHandle)));
|
||||
getChildren(parentHandle?: TreeItemHandle): TPromise<ITreeItem[]> {
|
||||
const parentElement = parentHandle ? this.getExtensionElement(parentHandle) : void 0;
|
||||
if (parentHandle && !parentElement) {
|
||||
console.error(`No tree item with id \'${parentHandle}\' found.`);
|
||||
return TPromise.as([]);
|
||||
}
|
||||
|
||||
return asWinJsPromise(() => this.dataProvider.getChildren(extElement))
|
||||
.then(childrenElements => this.resolveElements(childrenElements, treeItemHandle))
|
||||
.then(childrenItems => {
|
||||
this.nodes.get(extElement).children = childrenItems.map(c => c.handle);
|
||||
return childrenItems;
|
||||
});
|
||||
const childrenNodes = this.getChildrenNodes(parentHandle); // Get it from cache
|
||||
return (childrenNodes ? TPromise.as(childrenNodes) : this.fetchChildrenNodes(parentElement))
|
||||
.then(nodes => nodes.map(n => n.item));
|
||||
}
|
||||
|
||||
getExtensionElement(treeItemHandle: TreeItemHandle): T {
|
||||
return this.elements.get(treeItemHandle);
|
||||
}
|
||||
|
||||
private _refresh(elements: T[]): void {
|
||||
reveal(element: T, options?: { select?: boolean }): TPromise<void> {
|
||||
if (typeof this.dataProvider.getParent !== 'function') {
|
||||
return TPromise.wrapError(new Error(`Required registered TreeDataProvider to implement 'getParent' method to access 'reveal' mehtod`));
|
||||
}
|
||||
return this.resolveUnknownParentChain(element)
|
||||
.then(parentChain => this.resolveTreeNode(element, parentChain[parentChain.length - 1])
|
||||
.then(treeNode => this.proxy.$reveal(this.viewId, treeNode.item, parentChain.map(p => p.item), options)));
|
||||
}
|
||||
|
||||
private resolveUnknownParentChain(element: T): TPromise<TreeNode[]> {
|
||||
return this.resolveParent(element)
|
||||
.then((parent) => {
|
||||
if (!parent) {
|
||||
return TPromise.as([]);
|
||||
}
|
||||
return this.resolveUnknownParentChain(parent)
|
||||
.then(result => this.resolveTreeNode(parent, result[result.length - 1])
|
||||
.then(parentNode => {
|
||||
result.push(parentNode);
|
||||
return result;
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
private resolveParent(element: T): TPromise<T> {
|
||||
const node = this.nodes.get(element);
|
||||
if (node) {
|
||||
return TPromise.as(node.parent ? this.elements.get(node.parent.item.handle) : null);
|
||||
}
|
||||
return asWinJsPromise(() => this.dataProvider.getParent(element));
|
||||
}
|
||||
|
||||
private resolveTreeNode(element: T, parent?: TreeNode): TPromise<TreeNode> {
|
||||
return asWinJsPromise(() => this.dataProvider.getTreeItem(element))
|
||||
.then(extTreeItem => this.createHandle(element, extTreeItem, parent))
|
||||
.then(handle => this.getChildren(parent ? parent.item.handle : null)
|
||||
.then(() => {
|
||||
const cachedElement = this.getExtensionElement(handle);
|
||||
if (cachedElement) {
|
||||
const node = this.nodes.get(cachedElement);
|
||||
if (node) {
|
||||
return TPromise.as(node);
|
||||
}
|
||||
}
|
||||
throw new Error(`Cannot resolve tree item for element ${handle}`);
|
||||
}));
|
||||
}
|
||||
|
||||
private getChildrenNodes(parentNodeOrHandle?: TreeNode | TreeItemHandle): TreeNode[] {
|
||||
if (parentNodeOrHandle) {
|
||||
let parentNode: TreeNode;
|
||||
if (typeof parentNodeOrHandle === 'string') {
|
||||
const parentElement = this.getExtensionElement(parentNodeOrHandle);
|
||||
parentNode = parentElement ? this.nodes.get(parentElement) : null;
|
||||
} else {
|
||||
parentNode = parentNodeOrHandle;
|
||||
}
|
||||
return parentNode ? parentNode.children : null;
|
||||
}
|
||||
return this.roots;
|
||||
}
|
||||
|
||||
private fetchChildrenNodes(parentElement?: T): TPromise<TreeNode[]> {
|
||||
// clear children cache
|
||||
this.clearChildren(parentElement);
|
||||
|
||||
const parentNode = parentElement ? this.nodes.get(parentElement) : void 0;
|
||||
return asWinJsPromise(() => this.dataProvider.getChildren(parentElement))
|
||||
.then(elements => TPromise.join(
|
||||
(elements || [])
|
||||
.filter(element => !!element)
|
||||
.map(element => asWinJsPromise(() => this.dataProvider.getTreeItem(element))
|
||||
.then(extTreeItem => extTreeItem ? this.createAndRegisterTreeNode(element, extTreeItem, parentNode) : null))))
|
||||
.then(nodes => nodes.filter(n => !!n));
|
||||
}
|
||||
|
||||
private refresh(elements: T[]): void {
|
||||
const hasRoot = elements.some(element => !element);
|
||||
if (hasRoot) {
|
||||
this.clearAll(); // clear cache
|
||||
this.proxy.$refresh(this.viewId);
|
||||
} else {
|
||||
const handlesToUpdate = this.getHandlesToUpdate(elements);
|
||||
if (handlesToUpdate.length) {
|
||||
this._refreshHandles(handlesToUpdate);
|
||||
const handlesToRefresh = this.getHandlesToRefresh(elements);
|
||||
if (handlesToRefresh.length) {
|
||||
this.refreshHandles(handlesToRefresh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private resolveElements(elements: T[], parentHandle?: TreeItemHandle): TPromise<ITreeItem[]> {
|
||||
if (elements && elements.length) {
|
||||
return TPromise.join(
|
||||
elements.filter(element => !!element)
|
||||
.map((element, index) => {
|
||||
return this.resolveElement(element, index, parentHandle)
|
||||
.then(treeItem => {
|
||||
if (treeItem) {
|
||||
this.nodes.set(element, {
|
||||
index,
|
||||
handle: treeItem.handle,
|
||||
parent: parentHandle,
|
||||
children: void 0
|
||||
});
|
||||
if (this.elements.has(treeItem.handle)) {
|
||||
return TPromise.wrapError<ITreeItem>(new Error(localize('treeView.duplicateElement', 'Element {0} is already registered', element)));
|
||||
}
|
||||
this.elements.set(treeItem.handle, element);
|
||||
}
|
||||
return treeItem;
|
||||
});
|
||||
}))
|
||||
.then(treeItems => treeItems.filter(treeItem => !!treeItem));
|
||||
private getHandlesToRefresh(elements: T[]): TreeItemHandle[] {
|
||||
const elementsToUpdate = new Set<TreeItemHandle>();
|
||||
for (const element of elements) {
|
||||
let elementNode = this.nodes.get(element);
|
||||
if (elementNode && !elementsToUpdate.has(elementNode.item.handle)) {
|
||||
// check if an ancestor of extElement is already in the elements to update list
|
||||
let currentNode = elementNode;
|
||||
while (currentNode && currentNode.parent && !elementsToUpdate.has(currentNode.parent.item.handle)) {
|
||||
const parentElement = this.elements.get(currentNode.parent.item.handle);
|
||||
currentNode = this.nodes.get(parentElement);
|
||||
}
|
||||
if (!currentNode.parent) {
|
||||
elementsToUpdate.add(elementNode.item.handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
return TPromise.as([]);
|
||||
|
||||
const handlesToUpdate: TreeItemHandle[] = [];
|
||||
// Take only top level elements
|
||||
elementsToUpdate.forEach((handle) => {
|
||||
const element = this.elements.get(handle);
|
||||
let node = this.nodes.get(element);
|
||||
if (node && (!node.parent || !elementsToUpdate.has(node.parent.item.handle))) {
|
||||
handlesToUpdate.push(handle);
|
||||
}
|
||||
});
|
||||
|
||||
return handlesToUpdate;
|
||||
}
|
||||
|
||||
private resolveElement(element: T, index: number, parentHandle?: TreeItemHandle): TPromise<ITreeItem> {
|
||||
return asWinJsPromise(() => this.dataProvider.getTreeItem(element))
|
||||
.then(extTreeItem => this.massageTreeItem(element, extTreeItem, index, parentHandle));
|
||||
private refreshHandles(itemHandles: TreeItemHandle[]): TPromise<void> {
|
||||
const itemsToRefresh: { [treeItemHandle: string]: ITreeItem } = {};
|
||||
return TPromise.join(itemHandles.map(treeItemHandle =>
|
||||
this.refreshNode(treeItemHandle)
|
||||
.then(node => {
|
||||
if (node) {
|
||||
itemsToRefresh[treeItemHandle] = node.item;
|
||||
}
|
||||
})))
|
||||
.then(() => Object.keys(itemsToRefresh).length ? this.proxy.$refresh(this.viewId, itemsToRefresh) : null);
|
||||
}
|
||||
|
||||
private massageTreeItem(element: T, extensionTreeItem: vscode.TreeItem, index: number, parentHandle: TreeItemHandle): ITreeItem {
|
||||
if (!extensionTreeItem) {
|
||||
return null;
|
||||
private refreshNode(treeItemHandle: TreeItemHandle): TPromise<TreeNode> {
|
||||
const extElement = this.getExtensionElement(treeItemHandle);
|
||||
const existing = this.nodes.get(extElement);
|
||||
this.clearChildren(extElement); // clear children cache
|
||||
return asWinJsPromise(() => this.dataProvider.getTreeItem(extElement))
|
||||
.then(extTreeItem => {
|
||||
if (extTreeItem) {
|
||||
const newNode = this.createTreeNode(extElement, extTreeItem, existing.parent);
|
||||
this.updateNodeCache(extElement, newNode, existing, existing.parent);
|
||||
return newNode;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private createAndRegisterTreeNode(element: T, extTreeItem: vscode.TreeItem, parentNode: TreeNode): TreeNode {
|
||||
const node = this.createTreeNode(element, extTreeItem, parentNode);
|
||||
if (extTreeItem.id && this.elements.has(node.item.handle)) {
|
||||
throw new Error(localize('treeView.duplicateElement', 'Element with id {0} is already registered', extTreeItem.id));
|
||||
}
|
||||
const icon = this.getLightIconPath(extensionTreeItem);
|
||||
const label = extensionTreeItem.label;
|
||||
const handle = typeof element === 'string' ? element : this.generateHandle(label, index, parentHandle);
|
||||
this.addNodeToCache(element, node);
|
||||
this.addNodeToParentCache(node, parentNode);
|
||||
return node;
|
||||
}
|
||||
|
||||
private createTreeNode(element: T, extensionTreeItem: vscode.TreeItem, parent: TreeNode): TreeNode {
|
||||
return {
|
||||
item: this.createTreeItem(element, extensionTreeItem, parent),
|
||||
parent,
|
||||
children: void 0
|
||||
};
|
||||
}
|
||||
|
||||
private createTreeItem(element: T, extensionTreeItem: vscode.TreeItem, parent?: TreeNode): ITreeItem {
|
||||
|
||||
const handle = this.createHandle(element, extensionTreeItem, parent);
|
||||
const icon = this.getLightIconPath(extensionTreeItem);
|
||||
const item = {
|
||||
handle,
|
||||
parentHandle,
|
||||
label,
|
||||
parentHandle: parent ? parent.item.handle : void 0,
|
||||
label: extensionTreeItem.label,
|
||||
resourceUri: extensionTreeItem.resourceUri,
|
||||
tooltip: typeof extensionTreeItem.tooltip === 'string' ? extensionTreeItem.tooltip : void 0,
|
||||
command: extensionTreeItem.command ? this.commands.toInternal(extensionTreeItem.command) : void 0,
|
||||
contextValue: extensionTreeItem.contextValue,
|
||||
icon,
|
||||
iconDark: this.getDarkIconPath(extensionTreeItem) || icon,
|
||||
collapsibleState: extensionTreeItem.collapsibleState
|
||||
themeIcon: extensionTreeItem.iconPath instanceof ThemeIcon ? { id: extensionTreeItem.iconPath.id } : void 0,
|
||||
collapsibleState: isUndefinedOrNull(extensionTreeItem.collapsibleState) ? TreeItemCollapsibleState.None : extensionTreeItem.collapsibleState
|
||||
};
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
private generateHandle(label: string, index: number, parentHandle: TreeItemHandle): TreeItemHandle {
|
||||
parentHandle = parentHandle ? parentHandle : ExtHostTreeView.ROOT_HANDLE;
|
||||
label = label.indexOf('/') !== -1 ? label.replace('/', '//') : label;
|
||||
return `${parentHandle}/${index}:${label}`;
|
||||
private createHandle(element: T, { id, label, resourceUri }: vscode.TreeItem, parent?: TreeNode): TreeItemHandle {
|
||||
if (id) {
|
||||
return `${ExtHostTreeView.ID_HANDLE_PREFIX}/${id}`;
|
||||
}
|
||||
|
||||
const prefix: string = parent ? parent.item.handle : ExtHostTreeView.LABEL_HANDLE_PREFIX;
|
||||
let elementId = label ? label : resourceUri ? basename(resourceUri.path) : '';
|
||||
elementId = elementId.indexOf('/') !== -1 ? elementId.replace('/', '//') : elementId;
|
||||
const existingHandle = this.nodes.has(element) ? this.nodes.get(element).item.handle : void 0;
|
||||
const childrenNodes = (this.getChildrenNodes(parent) || []);
|
||||
|
||||
for (let counter = 0; counter <= childrenNodes.length; counter++) {
|
||||
const handle = `${prefix}/${counter}:${elementId}`;
|
||||
if (!this.elements.has(handle) || existingHandle === handle) {
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error('This should not be reached');
|
||||
}
|
||||
|
||||
private getLightIconPath(extensionTreeItem: vscode.TreeItem): string {
|
||||
if (extensionTreeItem.iconPath) {
|
||||
if (typeof extensionTreeItem.iconPath === 'string' || extensionTreeItem.iconPath instanceof URI) {
|
||||
if (extensionTreeItem.iconPath && !(extensionTreeItem.iconPath instanceof ThemeIcon)) {
|
||||
if (typeof extensionTreeItem.iconPath === 'string'
|
||||
|| extensionTreeItem.iconPath instanceof URI) {
|
||||
return this.getIconPath(extensionTreeItem.iconPath);
|
||||
}
|
||||
return this.getIconPath(extensionTreeItem.iconPath['light']);
|
||||
@@ -195,7 +328,7 @@ class ExtHostTreeView<T> extends Disposable {
|
||||
}
|
||||
|
||||
private getDarkIconPath(extensionTreeItem: vscode.TreeItem): string {
|
||||
if (extensionTreeItem.iconPath && extensionTreeItem.iconPath['dark']) {
|
||||
if (extensionTreeItem.iconPath && !(extensionTreeItem.iconPath instanceof ThemeIcon) && extensionTreeItem.iconPath['dark']) {
|
||||
return this.getIconPath(extensionTreeItem.iconPath['dark']);
|
||||
}
|
||||
return void 0;
|
||||
@@ -208,102 +341,77 @@ class ExtHostTreeView<T> extends Disposable {
|
||||
return URI.file(iconPath).toString();
|
||||
}
|
||||
|
||||
private getHandlesToUpdate(elements: T[]): TreeItemHandle[] {
|
||||
const elementsToUpdate = new Set<TreeItemHandle>();
|
||||
for (const element of elements) {
|
||||
let elementNode = this.nodes.get(element);
|
||||
if (elementNode && !elementsToUpdate.has(elementNode.handle)) {
|
||||
// check if an ancestor of extElement is already in the elements to update list
|
||||
let currentNode = elementNode;
|
||||
while (currentNode && currentNode.parent && !elementsToUpdate.has(currentNode.parent)) {
|
||||
const parentElement = this.elements.get(currentNode.parent);
|
||||
currentNode = this.nodes.get(parentElement);
|
||||
}
|
||||
if (!currentNode.parent) {
|
||||
elementsToUpdate.add(elementNode.handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handlesToUpdate: TreeItemHandle[] = [];
|
||||
// Take only top level elements
|
||||
elementsToUpdate.forEach((handle) => {
|
||||
const element = this.elements.get(handle);
|
||||
let node = this.nodes.get(element);
|
||||
if (node && !elementsToUpdate.has(node.parent)) {
|
||||
handlesToUpdate.push(handle);
|
||||
}
|
||||
});
|
||||
|
||||
return handlesToUpdate;
|
||||
private addNodeToCache(element: T, node: TreeNode): void {
|
||||
this.elements.set(node.item.handle, element);
|
||||
this.nodes.set(element, node);
|
||||
}
|
||||
|
||||
private _refreshHandles(itemHandles: TreeItemHandle[]): TPromise<void> {
|
||||
const itemsToRefresh: { [handle: string]: ITreeItem } = {};
|
||||
const promises: TPromise<void>[] = [];
|
||||
itemHandles.forEach(treeItemHandle => {
|
||||
const extElement = this.getExtensionElement(treeItemHandle);
|
||||
const node = this.nodes.get(extElement);
|
||||
const promise = this.resolveElement(extElement, node.index, node.parent)
|
||||
.then(treeItem => {
|
||||
if (treeItemHandle !== treeItem.handle) {
|
||||
// Update caches if handle changes
|
||||
this.updateCaches(node, treeItem, extElement);
|
||||
private updateNodeCache(element: T, newNode: TreeNode, existing: TreeNode, parentNode: TreeNode): void {
|
||||
// Remove from the cache
|
||||
this.elements.delete(newNode.item.handle);
|
||||
this.nodes.delete(element);
|
||||
if (newNode.item.handle !== existing.item.handle) {
|
||||
this.elements.delete(existing.item.handle);
|
||||
}
|
||||
|
||||
// Add the new node to the cache
|
||||
this.addNodeToCache(element, newNode);
|
||||
|
||||
// Replace the node in parent's children nodes
|
||||
const childrenNodes = (this.getChildrenNodes(parentNode) || []);
|
||||
const childNode = childrenNodes.filter(c => c.item.handle === existing.item.handle)[0];
|
||||
if (childNode) {
|
||||
childrenNodes.splice(childrenNodes.indexOf(childNode), 1, newNode);
|
||||
}
|
||||
}
|
||||
|
||||
private addNodeToParentCache(node: TreeNode, parentNode: TreeNode): void {
|
||||
if (parentNode) {
|
||||
if (!parentNode.children) {
|
||||
parentNode.children = [];
|
||||
}
|
||||
parentNode.children.push(node);
|
||||
} else {
|
||||
if (!this.roots) {
|
||||
this.roots = [];
|
||||
}
|
||||
this.roots.push(node);
|
||||
}
|
||||
}
|
||||
|
||||
private clearChildren(parentElement?: T): void {
|
||||
if (parentElement) {
|
||||
let node = this.nodes.get(parentElement);
|
||||
if (node.children) {
|
||||
for (const child of node.children) {
|
||||
const childEleement = this.elements.get(child.item.handle);
|
||||
if (childEleement) {
|
||||
this.clear(childEleement);
|
||||
}
|
||||
itemsToRefresh[treeItemHandle] = treeItem;
|
||||
});
|
||||
promises.push(promise);
|
||||
});
|
||||
return TPromise.join(promises)
|
||||
.then(treeItems => {
|
||||
this.proxy.$refresh(this.viewId, itemsToRefresh);
|
||||
});
|
||||
}
|
||||
|
||||
private updateCaches(node: TreeNode, treeItem: ITreeItem, element: T): void {
|
||||
if (node.parent) {
|
||||
// Update parent's children handles
|
||||
const parentElement = this.getExtensionElement(node.parent);
|
||||
const parentNode = this.nodes.get(parentElement);
|
||||
parentNode.children[node.index] = treeItem.handle;
|
||||
}
|
||||
|
||||
// Update elements map
|
||||
this.elements.delete(node.handle);
|
||||
this.elements.set(treeItem.handle, element);
|
||||
|
||||
// Update node
|
||||
node.handle = treeItem.handle;
|
||||
}
|
||||
|
||||
private clearChildren(element: T): void {
|
||||
let node = this.nodes.get(element);
|
||||
if (node.children) {
|
||||
for (const childHandle of node.children) {
|
||||
const childEleement = this.elements.get(childHandle);
|
||||
if (childEleement) {
|
||||
this.clear(childEleement);
|
||||
}
|
||||
}
|
||||
node.children = [];
|
||||
} else {
|
||||
this.clearAll();
|
||||
}
|
||||
node.children = void 0;
|
||||
}
|
||||
|
||||
private clear(element: T): void {
|
||||
let node = this.nodes.get(element);
|
||||
if (node.children) {
|
||||
for (const childHandle of node.children) {
|
||||
const childEleement = this.elements.get(childHandle);
|
||||
for (const child of node.children) {
|
||||
const childEleement = this.elements.get(child.item.handle);
|
||||
if (childEleement) {
|
||||
this.clear(childEleement);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.nodes.delete(element);
|
||||
this.elements.delete(node.handle);
|
||||
this.elements.delete(node.item.handle);
|
||||
}
|
||||
|
||||
private clearAll(): void {
|
||||
this.roots = null;
|
||||
this.elements.clear();
|
||||
this.nodes.clear();
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ 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';
|
||||
import { IDecorationOptions, EndOfLineSequence } from 'vs/editor/common/editorCommon';
|
||||
import { IDecorationOptions } from 'vs/editor/common/editorCommon';
|
||||
import { EndOfLineSequence } from 'vs/editor/common/model';
|
||||
import * as vscode from 'vscode';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { ProgressLocation as MainProgressLocation } from 'vs/platform/progress/common/progress';
|
||||
@@ -19,6 +20,7 @@ import { ISelection } from 'vs/editor/common/core/selection';
|
||||
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';
|
||||
|
||||
export interface PositionLike {
|
||||
line: number;
|
||||
@@ -227,36 +229,36 @@ export const TextEdit = {
|
||||
|
||||
export namespace WorkspaceEdit {
|
||||
export function from(value: vscode.WorkspaceEdit): modes.WorkspaceEdit {
|
||||
const result: modes.WorkspaceEdit = { edits: [] };
|
||||
for (let entry of value.entries()) {
|
||||
let [uri, textEdits] = entry;
|
||||
for (let textEdit of textEdits) {
|
||||
result.edits.push({
|
||||
resource: uri,
|
||||
newText: textEdit.newText,
|
||||
range: fromRange(textEdit.range)
|
||||
});
|
||||
const result: modes.WorkspaceEdit = {
|
||||
edits: []
|
||||
};
|
||||
for (const entry of value.entries()) {
|
||||
const [uri, uriOrEdits] = entry;
|
||||
if (Array.isArray(uriOrEdits)) {
|
||||
// text edits
|
||||
result.edits.push({ resource: uri, edits: uriOrEdits.map(TextEdit.from) });
|
||||
} else {
|
||||
// resource edits
|
||||
result.edits.push({ oldUri: uri, newUri: uriOrEdits });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function fromTextEdits(uri: vscode.Uri, textEdits: vscode.TextEdit[]): modes.WorkspaceEdit {
|
||||
const result: modes.WorkspaceEdit = { edits: [] };
|
||||
for (let textEdit of textEdits) {
|
||||
result.edits.push({
|
||||
resource: uri,
|
||||
newText: textEdit.newText,
|
||||
range: fromRange(textEdit.range)
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function to(value: modes.WorkspaceEdit) {
|
||||
export function to(value: WorkspaceEditDto) {
|
||||
const result = new types.WorkspaceEdit();
|
||||
for (const edit of value.edits) {
|
||||
result.replace(edit.resource, toRange(edit.range), edit.newText);
|
||||
if (Array.isArray((<ResourceTextEditDto>edit).edits)) {
|
||||
result.set(
|
||||
URI.revive((<ResourceTextEditDto>edit).resource),
|
||||
<types.TextEdit[]>(<ResourceTextEditDto>edit).edits.map(TextEdit.to)
|
||||
);
|
||||
// } else {
|
||||
// result.renameResource(
|
||||
// URI.revive((<ResourceFileEditDto>edit).oldUri),
|
||||
// URI.revive((<ResourceFileEditDto>edit).newUri)
|
||||
// );
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -358,7 +360,8 @@ export namespace CompletionTriggerKind {
|
||||
switch (kind) {
|
||||
case modes.SuggestTriggerKind.TriggerCharacter:
|
||||
return types.CompletionTriggerKind.TriggerCharacter;
|
||||
|
||||
case modes.SuggestTriggerKind.TriggerForIncompleteCompletions:
|
||||
return types.CompletionTriggerKind.TriggerForIncompleteCompletions;
|
||||
case modes.SuggestTriggerKind.Invoke:
|
||||
default:
|
||||
return types.CompletionTriggerKind.Invoke;
|
||||
@@ -424,8 +427,7 @@ export namespace Suggest {
|
||||
result.insertText = suggestion.insertText;
|
||||
result.kind = CompletionItemKind.to(suggestion.type);
|
||||
result.detail = suggestion.detail;
|
||||
// {{SQL CARBON EDIT}}
|
||||
result.documentation = <string>suggestion.documentation;
|
||||
result.documentation = htmlContent.isMarkdownString(suggestion.documentation) ? MarkdownString.to(suggestion.documentation) : suggestion.documentation;
|
||||
result.sortText = suggestion.sortText;
|
||||
result.filterText = suggestion.filterText;
|
||||
|
||||
@@ -584,6 +586,14 @@ export namespace ProgressLocation {
|
||||
}
|
||||
}
|
||||
|
||||
export namespace FoldingRangeList {
|
||||
export function from(rangeList: vscode.FoldingRangeList): modes.IFoldingRangeList {
|
||||
return {
|
||||
ranges: rangeList.ranges.map(r => ({ startLineNumber: r.startLine + 1, endLineNumber: r.endLine + 1, type: r.type }))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function toTextEditorOptions(options?: vscode.TextDocumentShowOptions): ITextEditorOptions {
|
||||
if (options) {
|
||||
return {
|
||||
@@ -601,11 +611,11 @@ export function toGlobPattern(pattern: vscode.GlobPattern): string | IRelativePa
|
||||
return pattern;
|
||||
}
|
||||
|
||||
if (!isRelativePattern(pattern)) {
|
||||
return undefined;
|
||||
if (isRelativePattern(pattern)) {
|
||||
return new types.RelativePattern(pattern.base, pattern.pattern);
|
||||
}
|
||||
|
||||
return new types.RelativePattern(pattern.base, pattern.pattern);
|
||||
return pattern; // preserve `undefined` and `null`
|
||||
}
|
||||
|
||||
function isRelativePattern(obj: any): obj is vscode.RelativePattern {
|
||||
@@ -627,9 +637,13 @@ function doToLanguageSelector(selector: string | vscode.DocumentFilter): string
|
||||
return selector;
|
||||
}
|
||||
|
||||
return {
|
||||
language: selector.language,
|
||||
scheme: selector.scheme,
|
||||
pattern: toGlobPattern(selector.pattern)
|
||||
};
|
||||
if (selector) {
|
||||
return {
|
||||
language: selector.language,
|
||||
scheme: selector.scheme,
|
||||
pattern: toGlobPattern(selector.pattern)
|
||||
};
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import * as vscode from 'vscode';
|
||||
import { isMarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { IRelativePattern } from 'vs/base/common/glob';
|
||||
import { relative } from 'path';
|
||||
import { startsWith } from 'vs/base/common/strings';
|
||||
|
||||
export class Disposable {
|
||||
|
||||
@@ -91,10 +92,10 @@ export class Position {
|
||||
|
||||
constructor(line: number, character: number) {
|
||||
if (line < 0) {
|
||||
throw illegalArgument('line must be positive');
|
||||
throw illegalArgument('line must be non-negative');
|
||||
}
|
||||
if (character < 0) {
|
||||
throw illegalArgument('character must be positive');
|
||||
throw illegalArgument('character must be non-negative');
|
||||
}
|
||||
this._line = line;
|
||||
this._character = character;
|
||||
@@ -491,10 +492,28 @@ export class TextEdit {
|
||||
}
|
||||
}
|
||||
|
||||
export class WorkspaceEdit {
|
||||
export class WorkspaceEdit implements vscode.WorkspaceEdit {
|
||||
|
||||
private _values: [URI, TextEdit[]][] = [];
|
||||
private _index = new Map<string, number>();
|
||||
private _seqPool: number = 0;
|
||||
|
||||
private _resourceEdits: { seq: number, from: URI, to: URI }[] = [];
|
||||
private _textEdits = new Map<string, { seq: number, uri: URI, edits: TextEdit[] }>();
|
||||
|
||||
// createResource(uri: vscode.Uri): void {
|
||||
// this.renameResource(undefined, uri);
|
||||
// }
|
||||
|
||||
// deleteResource(uri: vscode.Uri): void {
|
||||
// this.renameResource(uri, undefined);
|
||||
// }
|
||||
|
||||
// renameResource(from: vscode.Uri, to: vscode.Uri): void {
|
||||
// this._resourceEdits.push({ seq: this._seqPool++, from, to });
|
||||
// }
|
||||
|
||||
// resourceEdits(): [vscode.Uri, vscode.Uri][] {
|
||||
// return this._resourceEdits.map(({ from, to }) => (<[vscode.Uri, vscode.Uri]>[from, to]));
|
||||
// }
|
||||
|
||||
replace(uri: URI, range: Range, newText: string): void {
|
||||
let edit = new TextEdit(range, newText);
|
||||
@@ -502,8 +521,9 @@ export class WorkspaceEdit {
|
||||
if (array) {
|
||||
array.push(edit);
|
||||
} else {
|
||||
this.set(uri, [edit]);
|
||||
array = [edit];
|
||||
}
|
||||
this.set(uri, array);
|
||||
}
|
||||
|
||||
insert(resource: URI, position: Position, newText: string): void {
|
||||
@@ -515,34 +535,59 @@ export class WorkspaceEdit {
|
||||
}
|
||||
|
||||
has(uri: URI): boolean {
|
||||
return this._index.has(uri.toString());
|
||||
return this._textEdits.has(uri.toString());
|
||||
}
|
||||
|
||||
set(uri: URI, edits: TextEdit[]): void {
|
||||
const idx = this._index.get(uri.toString());
|
||||
if (typeof idx === 'undefined') {
|
||||
let newLen = this._values.push([uri, edits]);
|
||||
this._index.set(uri.toString(), newLen - 1);
|
||||
let data = this._textEdits.get(uri.toString());
|
||||
if (!data) {
|
||||
data = { seq: this._seqPool++, uri, edits: [] };
|
||||
this._textEdits.set(uri.toString(), data);
|
||||
}
|
||||
if (!edits) {
|
||||
data.edits = undefined;
|
||||
} else {
|
||||
this._values[idx][1] = edits;
|
||||
data.edits = edits.slice(0);
|
||||
}
|
||||
}
|
||||
|
||||
get(uri: URI): TextEdit[] {
|
||||
let idx = this._index.get(uri.toString());
|
||||
return typeof idx !== 'undefined' && this._values[idx][1];
|
||||
if (!this._textEdits.has(uri.toString())) {
|
||||
return undefined;
|
||||
}
|
||||
const { edits } = this._textEdits.get(uri.toString());
|
||||
return edits ? edits.slice() : undefined;
|
||||
}
|
||||
|
||||
entries(): [URI, TextEdit[]][] {
|
||||
return this._values;
|
||||
const res: [URI, TextEdit[]][] = [];
|
||||
this._textEdits.forEach(value => res.push([value.uri, value.edits]));
|
||||
return res.slice();
|
||||
}
|
||||
|
||||
allEntries(): ([URI, TextEdit[]] | [URI, URI])[] {
|
||||
return this.entries();
|
||||
// // use the 'seq' the we have assigned when inserting
|
||||
// // the operation and use that order in the resulting
|
||||
// // array
|
||||
// const res: ([URI, TextEdit[]] | [URI, URI])[] = [];
|
||||
// this._textEdits.forEach(value => {
|
||||
// const { seq, uri, edits } = value;
|
||||
// res[seq] = [uri, edits];
|
||||
// });
|
||||
// this._resourceEdits.forEach(value => {
|
||||
// const { seq, from, to } = value;
|
||||
// res[seq] = [from, to];
|
||||
// });
|
||||
// return res;
|
||||
}
|
||||
|
||||
get size(): number {
|
||||
return this._values.length;
|
||||
return this._textEdits.size + this._resourceEdits.length;
|
||||
}
|
||||
|
||||
toJSON(): any {
|
||||
return this._values;
|
||||
return this.entries();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -814,16 +859,43 @@ export class CodeAction {
|
||||
|
||||
command?: vscode.Command;
|
||||
|
||||
edits?: TextEdit[] | WorkspaceEdit;
|
||||
edit?: WorkspaceEdit;
|
||||
|
||||
dianostics?: Diagnostic[];
|
||||
|
||||
constructor(title: string, edits?: TextEdit[] | WorkspaceEdit) {
|
||||
kind?: CodeActionKind;
|
||||
|
||||
constructor(title: string, kind?: CodeActionKind) {
|
||||
this.title = title;
|
||||
this.edits = edits;
|
||||
this.kind = kind;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class CodeActionKind {
|
||||
private static readonly sep = '.';
|
||||
|
||||
public static readonly Empty = new CodeActionKind('');
|
||||
public static readonly QuickFix = CodeActionKind.Empty.append('quickfix');
|
||||
public static readonly Refactor = CodeActionKind.Empty.append('refactor');
|
||||
public static readonly RefactorExtract = CodeActionKind.Refactor.append('extract');
|
||||
public static readonly RefactorInline = CodeActionKind.Refactor.append('inline');
|
||||
public static readonly RefactorRewrite = CodeActionKind.Refactor.append('rewrite');
|
||||
|
||||
constructor(
|
||||
public readonly value: string
|
||||
) { }
|
||||
|
||||
public append(parts: string): CodeActionKind {
|
||||
return new CodeActionKind(this.value ? this.value + CodeActionKind.sep + parts : parts);
|
||||
}
|
||||
|
||||
public contains(other: CodeActionKind): boolean {
|
||||
return this.value === other.value || startsWith(other.value, this.value + CodeActionKind.sep);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class CodeLens {
|
||||
|
||||
range: Range;
|
||||
@@ -905,14 +977,10 @@ export class SignatureHelp {
|
||||
}
|
||||
}
|
||||
|
||||
export enum CodeActionType {
|
||||
QuickFix = 1,
|
||||
Refactoring = 2
|
||||
}
|
||||
|
||||
export enum CompletionTriggerKind {
|
||||
Invoke = 0,
|
||||
TriggerCharacter = 1
|
||||
TriggerCharacter = 1,
|
||||
TriggerForIncompleteCompletions = 2
|
||||
}
|
||||
|
||||
export interface CompletionContext {
|
||||
@@ -953,8 +1021,7 @@ export class CompletionItem {
|
||||
label: string;
|
||||
kind: CompletionItemKind;
|
||||
detail: string;
|
||||
// {{SQL CARBON EDIT}}
|
||||
documentation: string;
|
||||
documentation: string | MarkdownString;
|
||||
sortText: string;
|
||||
filterText: string;
|
||||
insertText: string | SnippetString;
|
||||
@@ -1134,6 +1201,12 @@ export enum ColorFormat {
|
||||
HSL = 2
|
||||
}
|
||||
|
||||
export enum SourceControlInputBoxValidationType {
|
||||
Error = 0,
|
||||
Warning = 1,
|
||||
Information = 2
|
||||
}
|
||||
|
||||
export enum TaskRevealKind {
|
||||
Always = 1,
|
||||
|
||||
@@ -1446,11 +1519,21 @@ export enum ProgressLocation {
|
||||
|
||||
export class TreeItem {
|
||||
|
||||
label?: string;
|
||||
resourceUri?: URI;
|
||||
iconPath?: string | URI | { light: string | URI; dark: string | URI };
|
||||
command?: vscode.Command;
|
||||
contextValue?: string;
|
||||
tooltip?: string;
|
||||
|
||||
constructor(public label: string, public collapsibleState: vscode.TreeItemCollapsibleState = TreeItemCollapsibleState.None) {
|
||||
constructor(label: string, collapsibleState?: vscode.TreeItemCollapsibleState)
|
||||
constructor(resourceUri: URI, collapsibleState?: vscode.TreeItemCollapsibleState)
|
||||
constructor(arg1: string | URI, public collapsibleState: vscode.TreeItemCollapsibleState = TreeItemCollapsibleState.None) {
|
||||
if (arg1 instanceof URI) {
|
||||
this.resourceUri = arg1;
|
||||
} else {
|
||||
this.label = arg1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1461,6 +1544,18 @@ export enum TreeItemCollapsibleState {
|
||||
Expanded = 2
|
||||
}
|
||||
|
||||
export class ThemeIcon {
|
||||
static readonly File = new ThemeIcon('file');
|
||||
|
||||
static readonly Folder = new ThemeIcon('folder');
|
||||
|
||||
readonly id: string;
|
||||
|
||||
private constructor(id: string) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
export class ThemeColor {
|
||||
id: string;
|
||||
constructor(id: string) {
|
||||
@@ -1506,20 +1601,25 @@ export class Breakpoint {
|
||||
readonly condition?: string;
|
||||
readonly hitCondition?: string;
|
||||
|
||||
protected constructor(enabled: boolean, condition: string, hitCondition: string) {
|
||||
this.enabled = enabled;
|
||||
this.condition = condition;
|
||||
this.hitCondition = hitCondition;
|
||||
this.condition = condition;
|
||||
this.hitCondition = hitCondition;
|
||||
protected constructor(enabled?: boolean, condition?: string, hitCondition?: string) {
|
||||
this.enabled = typeof enabled === 'boolean' ? enabled : true;
|
||||
if (typeof condition === 'string') {
|
||||
this.condition = condition;
|
||||
}
|
||||
if (typeof hitCondition === 'string') {
|
||||
this.hitCondition = hitCondition;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class SourceBreakpoint extends Breakpoint {
|
||||
readonly location: Location;
|
||||
|
||||
constructor(enabled: boolean, condition: string, hitCondition: string, location: Location) {
|
||||
constructor(location: Location, enabled?: boolean, condition?: string, hitCondition?: string) {
|
||||
super(enabled, condition, hitCondition);
|
||||
if (location === null) {
|
||||
throw illegalArgument('location');
|
||||
}
|
||||
this.location = location;
|
||||
}
|
||||
}
|
||||
@@ -1527,8 +1627,93 @@ export class SourceBreakpoint extends Breakpoint {
|
||||
export class FunctionBreakpoint extends Breakpoint {
|
||||
readonly functionName: string;
|
||||
|
||||
constructor(enabled: boolean, condition: string, hitCondition: string, functionName: string) {
|
||||
constructor(functionName: string, enabled?: boolean, condition?: string, hitCondition?: string) {
|
||||
super(enabled, condition, hitCondition);
|
||||
if (!functionName) {
|
||||
throw illegalArgument('functionName');
|
||||
}
|
||||
this.functionName = functionName;
|
||||
}
|
||||
}
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
/*
|
||||
export class DebugAdapterExecutable implements vscode.DebugAdapterExecutable {
|
||||
readonly command: string;
|
||||
readonly args: string[];
|
||||
|
||||
constructor(command: string, args?: string[]) {
|
||||
this.command = command;
|
||||
this.args = args;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
export enum LogLevel {
|
||||
Trace = 1,
|
||||
Debug = 2,
|
||||
Info = 3,
|
||||
Warning = 4,
|
||||
Error = 5,
|
||||
Critical = 6,
|
||||
Off = 7
|
||||
}
|
||||
|
||||
//#region file api
|
||||
// todo@remote
|
||||
export enum FileChangeType {
|
||||
Updated = 0,
|
||||
Added = 1,
|
||||
Deleted = 2
|
||||
}
|
||||
|
||||
export enum FileType {
|
||||
File = 0,
|
||||
Dir = 1,
|
||||
Symlink = 2
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region folding api
|
||||
|
||||
export class FoldingRangeList {
|
||||
|
||||
ranges: FoldingRange[];
|
||||
|
||||
constructor(ranges: FoldingRange[]) {
|
||||
this.ranges = ranges;
|
||||
}
|
||||
}
|
||||
|
||||
export class FoldingRange {
|
||||
|
||||
startLine: number;
|
||||
|
||||
endLine: number;
|
||||
|
||||
type?: FoldingRangeType | string;
|
||||
|
||||
constructor(startLine: number, endLine: number, type?: FoldingRangeType | string) {
|
||||
this.startLine = startLine;
|
||||
this.endLine = endLine;
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
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'
|
||||
}
|
||||
|
||||
//#endregion
|
||||
180
src/vs/workbench/api/node/extHostWebview.ts
Normal file
180
src/vs/workbench/api/node/extHostWebview.ts
Normal file
@@ -0,0 +1,180 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* 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 * as vscode from 'vscode';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import * as typeConverters from 'vs/workbench/api/node/extHostTypeConverters';
|
||||
import { Position } from 'vs/platform/editor/common/editor';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
|
||||
export class ExtHostWebview implements vscode.Webview {
|
||||
public readonly editorType = 'webview';
|
||||
|
||||
private _title: string;
|
||||
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;
|
||||
|
||||
constructor(
|
||||
private readonly _handle: WebviewHandle,
|
||||
private readonly _proxy: MainThreadWebviewsShape,
|
||||
private readonly _uri: vscode.Uri,
|
||||
viewColumn: vscode.ViewColumn,
|
||||
options: vscode.WebviewOptions
|
||||
) {
|
||||
this._viewColumn = viewColumn;
|
||||
this._options = options;
|
||||
}
|
||||
|
||||
public dispose() {
|
||||
if (this._isDisposed) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._isDisposed = true;
|
||||
this._proxy.$disposeWebview(this._handle);
|
||||
|
||||
this.onDisposeEmitter.dispose();
|
||||
this.onMessageEmitter.dispose();
|
||||
this.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);
|
||||
}
|
||||
}
|
||||
|
||||
get html(): string {
|
||||
this.assertNotDisposed();
|
||||
return this._html;
|
||||
}
|
||||
|
||||
set html(value: string) {
|
||||
this.assertNotDisposed();
|
||||
if (this._html !== value) {
|
||||
this._html = value;
|
||||
this._proxy.$setHtml(this._handle, value);
|
||||
}
|
||||
}
|
||||
|
||||
get options(): vscode.WebviewOptions {
|
||||
this.assertNotDisposed();
|
||||
return this._options;
|
||||
}
|
||||
|
||||
get viewColumn(): vscode.ViewColumn {
|
||||
this.assertNotDisposed();
|
||||
return this._viewColumn;
|
||||
}
|
||||
|
||||
set viewColumn(value: vscode.ViewColumn) {
|
||||
this.assertNotDisposed();
|
||||
this._viewColumn = value;
|
||||
}
|
||||
|
||||
public postMessage(message: any): Thenable<boolean> {
|
||||
return this._proxy.$sendMessage(this._handle, message);
|
||||
}
|
||||
|
||||
public show(viewColumn: vscode.ViewColumn): void {
|
||||
this._proxy.$show(this._handle, typeConverters.fromViewColumn(viewColumn));
|
||||
}
|
||||
|
||||
private assertNotDisposed() {
|
||||
if (this._isDisposed) {
|
||||
throw new Error('Webview is disposed');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class ExtHostWebviews implements ExtHostWebviewsShape {
|
||||
private static handlePool = 0;
|
||||
|
||||
private readonly _proxy: MainThreadWebviewsShape;
|
||||
|
||||
private readonly _webviews = new Map<WebviewHandle, ExtHostWebview>();
|
||||
|
||||
constructor(
|
||||
mainContext: IMainContext
|
||||
) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadWebviews);
|
||||
}
|
||||
|
||||
createWebview(
|
||||
uri: vscode.Uri,
|
||||
title: string,
|
||||
viewColumn: vscode.ViewColumn,
|
||||
options: vscode.WebviewOptions
|
||||
): vscode.Webview {
|
||||
const handle = ExtHostWebviews.handlePool++;
|
||||
this._proxy.$createWebview(handle, uri, title, typeConverters.fromViewColumn(viewColumn), options);
|
||||
|
||||
const webview = new ExtHostWebview(handle, this._proxy, uri, viewColumn, options);
|
||||
this._webviews.set(handle, webview);
|
||||
return webview;
|
||||
}
|
||||
|
||||
$onMessage(handle: WebviewHandle, message: any): void {
|
||||
const webview = this.getWebview(handle);
|
||||
if (webview) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly _onDidChangeActiveWebview = new Emitter<ExtHostWebview | undefined>();
|
||||
public readonly onDidChangeActiveWebview = this._onDidChangeActiveWebview.event;
|
||||
|
||||
private getWebview(handle: WebviewHandle) {
|
||||
return this._webviews.get(handle);
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,7 @@
|
||||
'use strict';
|
||||
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
|
||||
import { ExtHostWindowShape, MainContext, MainThreadWindowShape } from './extHost.protocol';
|
||||
import { ExtHostWindowShape, MainContext, MainThreadWindowShape, IMainContext } from './extHost.protocol';
|
||||
import { WindowState } from 'vscode';
|
||||
|
||||
export class ExtHostWindow implements ExtHostWindowShape {
|
||||
@@ -23,8 +22,8 @@ export class ExtHostWindow implements ExtHostWindowShape {
|
||||
private _state = ExtHostWindow.InitialState;
|
||||
get state(): WindowState { return this._state; }
|
||||
|
||||
constructor(threadService: IThreadService) {
|
||||
this._proxy = threadService.get(MainContext.MainThreadWindow);
|
||||
constructor(mainContext: IMainContext) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadWindow);
|
||||
this._proxy.$getWindowVisibility().then(isFocused => this.$onDidChangeWindowFocus(isFocused));
|
||||
}
|
||||
|
||||
@@ -36,4 +35,4 @@ export class ExtHostWindow implements ExtHostWindowShape {
|
||||
this._state = { ...this._state, focused };
|
||||
this._onDidChangeWindowState.fire(this._state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,31 +7,110 @@
|
||||
import URI from 'vs/base/common/uri';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { normalize } from 'vs/base/common/paths';
|
||||
import { delta } from 'vs/base/common/arrays';
|
||||
import { delta as arrayDelta } from 'vs/base/common/arrays';
|
||||
import { relative, dirname } from 'path';
|
||||
import { Workspace, WorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkspaceData, ExtHostWorkspaceShape, MainContext, MainThreadWorkspaceShape, IMainContext } from './extHost.protocol';
|
||||
import { IWorkspaceData, ExtHostWorkspaceShape, MainContext, MainThreadWorkspaceShape, IMainContext, MainThreadMessageServiceShape } from './extHost.protocol';
|
||||
import * as vscode from 'vscode';
|
||||
import { compare } from 'vs/base/common/strings';
|
||||
import { TernarySearchTree } from 'vs/base/common/map';
|
||||
import { basenameOrAuthority, isEqual } from 'vs/base/common/resources';
|
||||
import { isLinux } from 'vs/base/common/platform';
|
||||
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { localize } from 'vs/nls';
|
||||
import { Severity } from 'vs/platform/notification/common/notification';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
|
||||
class Workspace2 extends Workspace {
|
||||
function isFolderEqual(folderA: URI, folderB: URI): boolean {
|
||||
return isEqual(folderA, folderB, !isLinux);
|
||||
}
|
||||
|
||||
static fromData(data: IWorkspaceData) {
|
||||
return data ? new Workspace2(data) : null;
|
||||
function compareWorkspaceFolderByUri(a: vscode.WorkspaceFolder, b: vscode.WorkspaceFolder): number {
|
||||
return isFolderEqual(a.uri, b.uri) ? 0 : compare(a.uri.toString(), b.uri.toString());
|
||||
}
|
||||
|
||||
function compareWorkspaceFolderByUriAndNameAndIndex(a: vscode.WorkspaceFolder, b: vscode.WorkspaceFolder): number {
|
||||
if (a.index !== b.index) {
|
||||
return a.index < b.index ? -1 : 1;
|
||||
}
|
||||
|
||||
return isFolderEqual(a.uri, b.uri) ? compare(a.name, b.name) : compare(a.uri.toString(), b.uri.toString());
|
||||
}
|
||||
|
||||
function delta(oldFolders: vscode.WorkspaceFolder[], newFolders: vscode.WorkspaceFolder[], compare: (a: vscode.WorkspaceFolder, b: vscode.WorkspaceFolder) => number): { removed: vscode.WorkspaceFolder[], added: vscode.WorkspaceFolder[] } {
|
||||
const oldSortedFolders = oldFolders.slice(0).sort(compare);
|
||||
const newSortedFolders = newFolders.slice(0).sort(compare);
|
||||
|
||||
return arrayDelta(oldSortedFolders, newSortedFolders, compare);
|
||||
}
|
||||
|
||||
interface MutableWorkspaceFolder extends vscode.WorkspaceFolder {
|
||||
name: string;
|
||||
index: number;
|
||||
}
|
||||
|
||||
class ExtHostWorkspaceImpl extends Workspace {
|
||||
|
||||
static toExtHostWorkspace(data: IWorkspaceData, previousConfirmedWorkspace?: ExtHostWorkspaceImpl, previousUnconfirmedWorkspace?: ExtHostWorkspaceImpl): { workspace: ExtHostWorkspaceImpl, added: vscode.WorkspaceFolder[], removed: vscode.WorkspaceFolder[] } {
|
||||
if (!data) {
|
||||
return { workspace: null, added: [], removed: [] };
|
||||
}
|
||||
|
||||
const { id, name, folders } = data;
|
||||
const newWorkspaceFolders: vscode.WorkspaceFolder[] = [];
|
||||
|
||||
// If we have an existing workspace, we try to find the folders that match our
|
||||
// data and update their properties. It could be that an extension stored them
|
||||
// for later use and we want to keep them "live" if they are still present.
|
||||
const oldWorkspace = previousConfirmedWorkspace;
|
||||
if (oldWorkspace) {
|
||||
folders.forEach((folderData, index) => {
|
||||
const folderUri = URI.revive(folderData.uri);
|
||||
const existingFolder = ExtHostWorkspaceImpl._findFolder(previousUnconfirmedWorkspace || previousConfirmedWorkspace, folderUri);
|
||||
|
||||
if (existingFolder) {
|
||||
existingFolder.name = folderData.name;
|
||||
existingFolder.index = folderData.index;
|
||||
|
||||
newWorkspaceFolders.push(existingFolder);
|
||||
} else {
|
||||
newWorkspaceFolders.push({ uri: folderUri, name: folderData.name, index });
|
||||
}
|
||||
});
|
||||
} else {
|
||||
newWorkspaceFolders.push(...folders.map(({ uri, name, index }) => ({ uri: URI.revive(uri), name, index })));
|
||||
}
|
||||
|
||||
// make sure to restore sort order based on index
|
||||
newWorkspaceFolders.sort((f1, f2) => f1.index < f2.index ? -1 : 1);
|
||||
|
||||
const workspace = new ExtHostWorkspaceImpl(id, name, newWorkspaceFolders);
|
||||
const { added, removed } = delta(oldWorkspace ? oldWorkspace.workspaceFolders : [], workspace.workspaceFolders, compareWorkspaceFolderByUri);
|
||||
|
||||
return { workspace, added, removed };
|
||||
}
|
||||
|
||||
private static _findFolder(workspace: ExtHostWorkspaceImpl, folderUriToFind: URI): MutableWorkspaceFolder {
|
||||
for (let i = 0; i < workspace.folders.length; i++) {
|
||||
const folder = workspace.workspaceFolders[i];
|
||||
if (isFolderEqual(folder.uri, folderUriToFind)) {
|
||||
return folder;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
private readonly _workspaceFolders: vscode.WorkspaceFolder[] = [];
|
||||
private readonly _structure = TernarySearchTree.forPaths<vscode.WorkspaceFolder>();
|
||||
|
||||
private constructor(data: IWorkspaceData) {
|
||||
super(data.id, data.name, data.folders.map(folder => new WorkspaceFolder(folder)));
|
||||
private constructor(id: string, name: string, folders: vscode.WorkspaceFolder[]) {
|
||||
super(id, name, folders.map(f => new WorkspaceFolder(f)));
|
||||
|
||||
// setup the workspace folder data structure
|
||||
this.folders.forEach(({ name, uri, index }) => {
|
||||
const workspaceFolder = { name, uri, index };
|
||||
this._workspaceFolders.push(workspaceFolder);
|
||||
this._structure.set(workspaceFolder.uri.toString(), workspaceFolder);
|
||||
folders.forEach(folder => {
|
||||
this._workspaceFolders.push(folder);
|
||||
this._structure.set(folder.uri.toString(), folder);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -54,44 +133,122 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
|
||||
|
||||
private readonly _onDidChangeWorkspace = new Emitter<vscode.WorkspaceFoldersChangeEvent>();
|
||||
private readonly _proxy: MainThreadWorkspaceShape;
|
||||
private _workspace: Workspace2;
|
||||
|
||||
private _confirmedWorkspace: ExtHostWorkspaceImpl;
|
||||
private _unconfirmedWorkspace: ExtHostWorkspaceImpl;
|
||||
|
||||
private _messageService: MainThreadMessageServiceShape;
|
||||
|
||||
readonly onDidChangeWorkspace: Event<vscode.WorkspaceFoldersChangeEvent> = this._onDidChangeWorkspace.event;
|
||||
|
||||
constructor(mainContext: IMainContext, data: IWorkspaceData) {
|
||||
this._proxy = mainContext.get(MainContext.MainThreadWorkspace);
|
||||
this._workspace = Workspace2.fromData(data);
|
||||
constructor(
|
||||
mainContext: IMainContext,
|
||||
data: IWorkspaceData,
|
||||
private _logService: ILogService
|
||||
) {
|
||||
this._proxy = mainContext.getProxy(MainContext.MainThreadWorkspace);
|
||||
this._messageService = mainContext.getProxy(MainContext.MainThreadMessageService);
|
||||
this._confirmedWorkspace = ExtHostWorkspaceImpl.toExtHostWorkspace(data).workspace;
|
||||
}
|
||||
|
||||
// --- workspace ---
|
||||
|
||||
get workspace(): Workspace {
|
||||
return this._workspace;
|
||||
return this._actualWorkspace;
|
||||
}
|
||||
|
||||
private get _actualWorkspace(): ExtHostWorkspaceImpl {
|
||||
return this._unconfirmedWorkspace || this._confirmedWorkspace;
|
||||
}
|
||||
|
||||
getWorkspaceFolders(): vscode.WorkspaceFolder[] {
|
||||
if (!this._workspace) {
|
||||
if (!this._actualWorkspace) {
|
||||
return undefined;
|
||||
} else {
|
||||
return this._workspace.workspaceFolders.slice(0);
|
||||
}
|
||||
return this._actualWorkspace.workspaceFolders.slice(0);
|
||||
}
|
||||
|
||||
updateWorkspaceFolders(extension: IExtensionDescription, index: number, deleteCount: number, ...workspaceFoldersToAdd: { uri: vscode.Uri, name?: string }[]): boolean {
|
||||
const validatedDistinctWorkspaceFoldersToAdd: { uri: vscode.Uri, name?: string }[] = [];
|
||||
if (Array.isArray(workspaceFoldersToAdd)) {
|
||||
workspaceFoldersToAdd.forEach(folderToAdd => {
|
||||
if (URI.isUri(folderToAdd.uri) && !validatedDistinctWorkspaceFoldersToAdd.some(f => isFolderEqual(f.uri, folderToAdd.uri))) {
|
||||
validatedDistinctWorkspaceFoldersToAdd.push({ uri: folderToAdd.uri, name: folderToAdd.name || basenameOrAuthority(folderToAdd.uri) });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!!this._unconfirmedWorkspace) {
|
||||
return false; // prevent accumulated calls without a confirmed workspace
|
||||
}
|
||||
|
||||
if ([index, deleteCount].some(i => typeof i !== 'number' || i < 0)) {
|
||||
return false; // validate numbers
|
||||
}
|
||||
|
||||
if (deleteCount === 0 && validatedDistinctWorkspaceFoldersToAdd.length === 0) {
|
||||
return false; // nothing to delete or add
|
||||
}
|
||||
|
||||
const currentWorkspaceFolders: MutableWorkspaceFolder[] = this._actualWorkspace ? this._actualWorkspace.workspaceFolders : [];
|
||||
if (index + deleteCount > currentWorkspaceFolders.length) {
|
||||
return false; // cannot delete more than we have
|
||||
}
|
||||
|
||||
// Simulate the updateWorkspaceFolders method on our data to do more validation
|
||||
const newWorkspaceFolders = currentWorkspaceFolders.slice(0);
|
||||
newWorkspaceFolders.splice(index, deleteCount, ...validatedDistinctWorkspaceFoldersToAdd.map(f => ({ uri: f.uri, name: f.name || basenameOrAuthority(f.uri), index: undefined })));
|
||||
|
||||
for (let i = 0; i < newWorkspaceFolders.length; i++) {
|
||||
const folder = newWorkspaceFolders[i];
|
||||
if (newWorkspaceFolders.some((otherFolder, index) => index !== i && isFolderEqual(folder.uri, otherFolder.uri))) {
|
||||
return false; // cannot add the same folder multiple times
|
||||
}
|
||||
}
|
||||
|
||||
newWorkspaceFolders.forEach((f, index) => f.index = index); // fix index
|
||||
const { added, removed } = delta(currentWorkspaceFolders, newWorkspaceFolders, compareWorkspaceFolderByUriAndNameAndIndex);
|
||||
if (added.length === 0 && removed.length === 0) {
|
||||
return false; // nothing actually changed
|
||||
}
|
||||
|
||||
// Trigger on main side
|
||||
if (this._proxy) {
|
||||
const extName = extension.displayName || extension.name;
|
||||
this._proxy.$updateWorkspaceFolders(extName, index, deleteCount, validatedDistinctWorkspaceFoldersToAdd).then(null, error => {
|
||||
|
||||
// in case of an error, make sure to clear out the unconfirmed workspace
|
||||
// because we cannot expect the acknowledgement from the main side for this
|
||||
this._unconfirmedWorkspace = undefined;
|
||||
|
||||
// show error to user
|
||||
this._messageService.$showMessage(Severity.Error, localize('updateerror', "Extension '{0}' failed to update workspace folders: {1}", extName, error.toString()), { extension }, []);
|
||||
});
|
||||
}
|
||||
|
||||
// Try to accept directly
|
||||
this.trySetWorkspaceFolders(newWorkspaceFolders);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
getWorkspaceFolder(uri: vscode.Uri, resolveParent?: boolean): vscode.WorkspaceFolder {
|
||||
if (!this._workspace) {
|
||||
if (!this._actualWorkspace) {
|
||||
return undefined;
|
||||
}
|
||||
return this._workspace.getWorkspaceFolder(uri, resolveParent);
|
||||
return this._actualWorkspace.getWorkspaceFolder(uri, resolveParent);
|
||||
}
|
||||
|
||||
getPath(): string {
|
||||
|
||||
// this is legacy from the days before having
|
||||
// multi-root and we keep it only alive if there
|
||||
// is just one workspace folder.
|
||||
if (!this._workspace) {
|
||||
if (!this._actualWorkspace) {
|
||||
return undefined;
|
||||
}
|
||||
const { folders } = this._workspace;
|
||||
|
||||
const { folders } = this._actualWorkspace;
|
||||
if (folders.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -121,7 +278,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
|
||||
}
|
||||
|
||||
if (typeof includeWorkspace === 'undefined') {
|
||||
includeWorkspace = this.workspace.folders.length > 1;
|
||||
includeWorkspace = this._actualWorkspace.folders.length > 1;
|
||||
}
|
||||
|
||||
let result = relative(folder.uri.fsPath, path);
|
||||
@@ -131,17 +288,30 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
|
||||
return normalize(result, true);
|
||||
}
|
||||
|
||||
private trySetWorkspaceFolders(folders: vscode.WorkspaceFolder[]): void {
|
||||
|
||||
// Update directly here. The workspace is unconfirmed as long as we did not get an
|
||||
// acknowledgement from the main side (via $acceptWorkspaceData)
|
||||
if (this._actualWorkspace) {
|
||||
this._unconfirmedWorkspace = ExtHostWorkspaceImpl.toExtHostWorkspace({
|
||||
id: this._actualWorkspace.id,
|
||||
name: this._actualWorkspace.name,
|
||||
configuration: this._actualWorkspace.configuration,
|
||||
folders
|
||||
} as IWorkspaceData, this._actualWorkspace).workspace;
|
||||
}
|
||||
}
|
||||
|
||||
$acceptWorkspaceData(data: IWorkspaceData): void {
|
||||
|
||||
// keep old workspace folder, build new workspace, and
|
||||
// capture new workspace folders. Compute delta between
|
||||
// them send that as event
|
||||
const oldRoots = this._workspace ? this._workspace.workspaceFolders.sort(ExtHostWorkspace._compareWorkspaceFolder) : [];
|
||||
const { workspace, added, removed } = ExtHostWorkspaceImpl.toExtHostWorkspace(data, this._confirmedWorkspace, this._unconfirmedWorkspace);
|
||||
|
||||
this._workspace = Workspace2.fromData(data);
|
||||
const newRoots = this._workspace ? this._workspace.workspaceFolders.sort(ExtHostWorkspace._compareWorkspaceFolder) : [];
|
||||
// Update our workspace object. We have a confirmed workspace, so we drop our
|
||||
// unconfirmed workspace.
|
||||
this._confirmedWorkspace = workspace;
|
||||
this._unconfirmedWorkspace = undefined;
|
||||
|
||||
const { added, removed } = delta(oldRoots, newRoots, ExtHostWorkspace._compareWorkspaceFolder);
|
||||
// Events
|
||||
// {{SQL CARBON EDIT}} - fix build break Argument of type 'Readonly<...
|
||||
this._onDidChangeWorkspace.fire({
|
||||
added: added,
|
||||
@@ -149,13 +319,11 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
|
||||
});
|
||||
}
|
||||
|
||||
private static _compareWorkspaceFolder(a: vscode.WorkspaceFolder, b: vscode.WorkspaceFolder): number {
|
||||
return compare(a.uri.toString(), b.uri.toString());
|
||||
}
|
||||
|
||||
// --- search ---
|
||||
|
||||
findFiles(include: vscode.GlobPattern, exclude: vscode.GlobPattern, maxResults?: number, token?: vscode.CancellationToken): Thenable<vscode.Uri[]> {
|
||||
findFiles(include: vscode.GlobPattern, exclude: vscode.GlobPattern, maxResults: number, extensionId: string, token?: vscode.CancellationToken): Thenable<vscode.Uri[]> {
|
||||
this._logService.trace(`extHostWorkspace#findFiles: fileSearch, extension: ${extensionId}, entryPoint: findFiles`);
|
||||
|
||||
const requestId = ExtHostWorkspace._requestIdPool++;
|
||||
|
||||
let includePattern: string;
|
||||
@@ -169,20 +337,22 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
|
||||
}
|
||||
}
|
||||
|
||||
let excludePattern: string;
|
||||
if (exclude) {
|
||||
let excludePatternOrDisregardExcludes: string | false;
|
||||
if (exclude === null) {
|
||||
excludePatternOrDisregardExcludes = false;
|
||||
} else if (exclude) {
|
||||
if (typeof exclude === 'string') {
|
||||
excludePattern = exclude;
|
||||
excludePatternOrDisregardExcludes = exclude;
|
||||
} else {
|
||||
excludePattern = exclude.pattern;
|
||||
excludePatternOrDisregardExcludes = exclude.pattern;
|
||||
}
|
||||
}
|
||||
|
||||
const result = this._proxy.$startSearch(includePattern, includeFolder, excludePattern, maxResults, requestId);
|
||||
const result = this._proxy.$startSearch(includePattern, includeFolder, excludePatternOrDisregardExcludes, maxResults, requestId);
|
||||
if (token) {
|
||||
token.onCancellationRequested(() => this._proxy.$cancelSearch(requestId));
|
||||
}
|
||||
return result;
|
||||
return result.then(data => data.map(URI.revive));
|
||||
}
|
||||
|
||||
saveAll(includeUntitled?: boolean): Thenable<boolean> {
|
||||
|
||||
Reference in New Issue
Block a user