Merge remote-tracking branch 'origin/master' into 46192_terminal_renderer

This commit is contained in:
Daniel Imms
2018-06-13 18:51:23 +02:00
1189 changed files with 30024 additions and 15226 deletions

View File

@@ -46,7 +46,7 @@ import { CancellationTokenSource } from 'vs/base/common/cancellation';
import * as vscode from 'vscode';
import * as paths from 'vs/base/common/paths';
import * as files from 'vs/platform/files/common/files';
import { MainContext, ExtHostContext, IInitData, IExtHostContext } from './extHost.protocol';
import { MainContext, ExtHostContext, IInitData, IMainContext } from './extHost.protocol';
import * as languageConfiguration from 'vs/editor/common/modes/languageConfiguration';
import { TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions';
import { ProxyIdentifier } from 'vs/workbench/services/extensions/node/proxyIdentifier';
@@ -58,6 +58,7 @@ import { ExtensionActivatedByAPI } from 'vs/workbench/api/node/extHostExtensionA
import { OverviewRulerLane } from 'vs/editor/common/model';
import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService';
import { ExtHostWebviews } from 'vs/workbench/api/node/extHostWebview';
import { ExtHostComments } from './extHostComments';
import { ExtHostSearch } from './extHostSearch';
import { ExtHostUrls } from './extHostUrls';
@@ -79,7 +80,7 @@ function proposedApiFunction<T>(extension: IExtensionDescription, fn: T): T {
if (extension.enableProposedApi) {
return fn;
} else {
return <any>throwProposedApiError;
return throwProposedApiError.bind(null, extension);
}
}
@@ -88,7 +89,7 @@ function proposedApiFunction<T>(extension: IExtensionDescription, fn: T): T {
*/
export function createApiFactory(
initData: IInitData,
rpcProtocol: IExtHostContext,
rpcProtocol: IMainContext,
extHostWorkspace: ExtHostWorkspace,
extHostConfiguration: ExtHostConfiguration,
extensionService: ExtHostExtensionService,
@@ -111,7 +112,6 @@ export function createApiFactory(
const extHostCommands = rpcProtocol.set(ExtHostContext.ExtHostCommands, new ExtHostCommands(rpcProtocol, extHostHeapService, extHostLogService));
const extHostTreeViews = rpcProtocol.set(ExtHostContext.ExtHostTreeViews, new ExtHostTreeViews(rpcProtocol.getProxy(MainContext.MainThreadTreeViews), extHostCommands));
rpcProtocol.set(ExtHostContext.ExtHostWorkspace, extHostWorkspace);
const extHostDebugService = rpcProtocol.set(ExtHostContext.ExtHostDebugService, new ExtHostDebugService(rpcProtocol, extHostWorkspace, extensionService, extHostDocumentsAndEditors, extHostConfiguration));
rpcProtocol.set(ExtHostContext.ExtHostConfiguration, extHostConfiguration);
const extHostDiagnostics = rpcProtocol.set(ExtHostContext.ExtHostDiagnostics, new ExtHostDiagnostics(rpcProtocol));
const extHostLanguageFeatures = rpcProtocol.set(ExtHostContext.ExtHostLanguageFeatures, new ExtHostLanguageFeatures(rpcProtocol, schemeTransformer, extHostDocuments, extHostCommands, extHostHeapService, extHostDiagnostics));
@@ -119,12 +119,14 @@ export function createApiFactory(
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, extHostConfiguration, extHostLogService));
const extHostDebugService = rpcProtocol.set(ExtHostContext.ExtHostDebugService, new ExtHostDebugService(rpcProtocol, extHostWorkspace, extensionService, extHostDocumentsAndEditors, extHostConfiguration, extHostTerminalService));
const extHostSCM = rpcProtocol.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(rpcProtocol, extHostCommands, extHostLogService));
const extHostSearch = rpcProtocol.set(ExtHostContext.ExtHostSearch, new ExtHostSearch(rpcProtocol, schemeTransformer));
const extHostTask = rpcProtocol.set(ExtHostContext.ExtHostTask, new ExtHostTask(rpcProtocol, extHostWorkspace, extHostDocumentsAndEditors, extHostConfiguration));
const extHostWindow = rpcProtocol.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(rpcProtocol));
rpcProtocol.set(ExtHostContext.ExtHostExtensionService, extensionService);
const extHostProgress = rpcProtocol.set(ExtHostContext.ExtHostProgress, new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress)));
const exthostCommentProviders = rpcProtocol.set(ExtHostContext.ExtHostComments, new ExtHostComments(rpcProtocol, extHostCommands.converter, extHostDocuments));
// Check that no named customers are missing
const expected: ProxyIdentifier<any>[] = Object.keys(ExtHostContext).map((key) => (<any>ExtHostContext)[key]);
@@ -386,13 +388,13 @@ export function createApiFactory(
return extHostMessageService.showMessage(extension, Severity.Error, message, first, rest);
},
showQuickPick(items: any, options: vscode.QuickPickOptions, token?: vscode.CancellationToken): any {
return extHostQuickOpen.showQuickPick(undefined, items, options, token);
return extHostQuickOpen.showQuickPick(items, options, token);
},
showWorkspaceFolderPick(options: vscode.WorkspaceFolderPickOptions) {
return extHostQuickOpen.showWorkspaceFolderPick(options);
},
showInputBox(options?: vscode.InputBoxOptions, token?: vscode.CancellationToken) {
return extHostQuickOpen.showInput(undefined, options, token);
return extHostQuickOpen.showInput(options, token);
},
showOpenDialog(options) {
return extHostDialogs.showOpenDialog(options);
@@ -446,7 +448,13 @@ export function createApiFactory(
}),
registerProtocolHandler: proposedApiFunction(extension, (handler: vscode.ProtocolHandler) => {
return extHostUrls.registerProtocolHandler(extension.id, handler);
})
}),
createQuickPick: proposedApiFunction(extension, (): vscode.QuickPick => {
return extHostQuickOpen.createQuickPick(extension.id);
}),
createInputBox: proposedApiFunction(extension, (): vscode.InputBox => {
return extHostQuickOpen.createInputBox(extension.id);
}),
};
// namespace: workspace
@@ -545,33 +553,21 @@ export function createApiFactory(
registerTaskProvider: (type: string, provider: vscode.TaskProvider) => {
return extHostTask.registerTaskProvider(extension, provider);
},
fetchTasks: proposedApiFunction(extension, (filter?: vscode.TaskFilter): Thenable<vscode.Task[]> => {
return extHostTask.fetchTasks(filter);
}),
executeTask: proposedApiFunction(extension, (task: vscode.Task): Thenable<vscode.TaskExecution> => {
return extHostTask.executeTask(extension, task);
}),
get taskExecutions(): vscode.TaskExecution[] {
return extHostTask.taskExecutions;
},
onDidStartTask: (listeners, thisArgs?, disposables?) => {
return extHostTask.onDidStartTask(listeners, thisArgs, disposables);
},
onDidEndTask: (listeners, thisArgs?, disposables?) => {
return extHostTask.onDidEndTask(listeners, thisArgs, disposables);
},
registerFileSystemProvider(scheme, provider, options) {
return extHostFileSystem.registerFileSystemProvider(scheme, provider, options);
},
registerDeprecatedFileSystemProvider: proposedApiFunction(extension, (scheme, provider) => {
return extHostFileSystem.registerDeprecatedFileSystemProvider(scheme, provider);
}),
registerSearchProvider: proposedApiFunction(extension, (scheme, provider) => {
return extHostSearch.registerSearchProvider(scheme, provider);
}),
registerDocumentCommentProvider: proposedApiFunction(extension, (provider: vscode.DocumentCommentProvider) => {
return exthostCommentProviders.registerDocumentCommentProvider(provider);
}),
registerWorkspaceCommentProvider: proposedApiFunction(extension, (provider: vscode.WorkspaceCommentProvider) => {
return exthostCommentProviders.registerWorkspaceCommentProvider(provider);
}),
onDidRenameResource: proposedApiFunction(extension, (listener, thisArg?, disposables?) => {
return extHostDocuments.onDidRenameResource(listener, thisArg, disposables);
}),
})
};
// namespace: scm
@@ -705,18 +701,7 @@ export function createApiFactory(
SourceBreakpoint: extHostTypes.SourceBreakpoint,
StatusBarAlignment: extHostTypes.StatusBarAlignment,
SymbolInformation: extHostTypes.SymbolInformation,
SymbolInformation2: class extends extHostTypes.SymbolInformation2 {
constructor(name, detail, kind, range, location) {
checkProposedApiEnabled(extension);
super(name, detail, kind, range, location);
}
},
Hierarchy: class <T> extends extHostTypes.Hierarchy<T> {
constructor(parent: T) {
checkProposedApiEnabled(extension);
super(parent);
}
},
DocumentSymbol: extHostTypes.DocumentSymbol,
SymbolKind: extHostTypes.SymbolKind,
SourceControlInputBoxValidationType: extHostTypes.SourceControlInputBoxValidationType,
TextDocumentSaveReason: extHostTypes.TextDocumentSaveReason,
@@ -746,17 +731,29 @@ export function createApiFactory(
ConfigurationTarget: extHostTypes.ConfigurationTarget,
RelativePattern: extHostTypes.RelativePattern,
DeprecatedFileChangeType: extHostTypes.DeprecatedFileChangeType,
DeprecatedFileType: extHostTypes.DeprecatedFileType,
FileChangeType: extHostTypes.FileChangeType,
FileType: files.FileType,
FileSystemError: extHostTypes.FileSystemError,
FoldingRange: extHostTypes.FoldingRange,
FoldingRangeKind: extHostTypes.FoldingRangeKind
FoldingRangeKind: extHostTypes.FoldingRangeKind,
CommentThreadCollapsibleState: extHostTypes.CommentThreadCollapsibleState
};
};
}
/**
* Returns the original fs path (using the original casing for the drive letter)
*/
export function originalFSPath(uri: URI): string {
const result = uri.fsPath;
if (/^[a-zA-Z]:/.test(result) && uri.path.charAt(1).toLowerCase() === result.charAt(0)) {
// Restore original drive letter casing
return uri.path.charAt(1) + result.substr(1);
}
return result;
}
class Extension<T> implements vscode.Extension<T> {
private _extensionService: ExtHostExtensionService;
@@ -768,7 +765,7 @@ class Extension<T> implements vscode.Extension<T> {
constructor(extensionService: ExtHostExtensionService, description: IExtensionDescription) {
this._extensionService = extensionService;
this.id = description.id;
this.extensionPath = paths.normalize(description.extensionLocation.fsPath, true);
this.extensionPath = paths.normalize(originalFSPath(description.extensionLocation), true);
this.packageJSON = description;
}

View File

@@ -18,7 +18,7 @@ import { IExtensionDescription } from 'vs/workbench/services/extensions/common/e
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';
import { IProgressOptions, IProgressStep } from 'vs/platform/progress/common/progress';
import { IProgressOptions, IProgressStep } from 'vs/workbench/services/progress/common/progress';
import * as editorCommon from 'vs/editor/common/editorCommon';
import * as modes from 'vs/editor/common/modes';
@@ -26,7 +26,7 @@ import * as modes from 'vs/editor/common/modes';
import { IConfigurationData, ConfigurationTarget, IConfigurationModel } from 'vs/platform/configuration/common/configuration';
import { IConfig, IAdapterExecutable, ITerminalSettings } from 'vs/workbench/parts/debug/common/debug';
import { IPickOpenEntry, IPickOptions } from 'vs/platform/quickinput/common/quickInput';
import { IQuickPickItem, IPickOptions, IQuickInputButton } from 'vs/platform/quickinput/common/quickInput';
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
import { TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions';
import { EndOfLine, TextEditorLineNumbersStyle } from 'vs/workbench/api/node/extHostTypes';
@@ -102,6 +102,14 @@ export interface MainThreadCommandsShape extends IDisposable {
$getCommands(): Thenable<string[]>;
}
export interface MainThreadCommentsShape extends IDisposable {
$registerDocumentCommentProvider(handle: number): void;
$unregisterDocumentCommentProvider(handle: number): void;
$registerWorkspaceCommentProvider(handle: number): void;
$unregisterWorkspaceCommentProvider(handle: number): void;
$onDidCommentThreadsChange(handle: number, event: modes.CommentThreadChangedEvent): void;
}
export interface MainThreadConfigurationShape extends IDisposable {
$updateConfigurationOption(target: ConfigurationTarget, key: string, value: any, resource: UriComponents): TPromise<void>;
$removeConfigurationOption(target: ConfigurationTarget, key: string, resource: UriComponents): TPromise<void>;
@@ -330,15 +338,74 @@ export interface MainThreadTerminalServiceShape extends IDisposable {
$sendProcessExit(terminalId: number, exitCode: number): void;
}
export interface MyQuickPickItems extends IPickOpenEntry {
export interface TransferQuickPickItems extends IQuickPickItem {
handle: number;
}
export interface TransferQuickInputButton extends IQuickInputButton {
handle: number;
}
export type TransferQuickInput = TransferQuickPick | TransferInputBox;
export interface BaseTransferQuickInput {
id: number;
type?: 'quickPick' | 'inputBox';
enabled?: boolean;
busy?: boolean;
visible?: boolean;
}
export interface TransferQuickPick extends BaseTransferQuickInput {
type?: 'quickPick';
value?: string;
placeholder?: string;
buttons?: TransferQuickInputButton[];
items?: TransferQuickPickItems[];
canSelectMany?: boolean;
ignoreFocusOut?: boolean;
matchOnDescription?: boolean;
matchOnDetail?: boolean;
}
export interface TransferInputBox extends BaseTransferQuickInput {
type?: 'inputBox';
value?: string;
placeholder?: string;
password?: boolean;
buttons?: TransferQuickInputButton[];
prompt?: string;
validationMessage?: string;
}
export interface MainThreadQuickOpenShape extends IDisposable {
$show(multiStepHandle: number | undefined, options: IPickOptions): TPromise<number | number[]>;
$setItems(items: MyQuickPickItems[]): TPromise<any>;
$show(options: IPickOptions): TPromise<number | number[]>;
$setItems(items: TransferQuickPickItems[]): TPromise<any>;
$setError(error: Error): TPromise<any>;
$input(multiStepHandle: number | undefined, options: vscode.InputBoxOptions, validateInput: boolean): TPromise<string>;
$multiStep(handle: number): TPromise<never>;
$input(options: vscode.InputBoxOptions, validateInput: boolean): TPromise<string>;
$createOrUpdate(params: TransferQuickInput): TPromise<void>;
$dispose(id: number): TPromise<void>;
}
export interface MainThreadStatusBarShape extends IDisposable {
@@ -666,17 +733,15 @@ export interface LocationDto {
range: IRange;
}
export interface SymbolInformationDto extends IdObject {
export interface WorkspaceSymbolDto extends IdObject {
name: string;
containerName?: string;
kind: modes.SymbolKind;
location: LocationDto;
definingRange: IRange;
children?: SymbolInformationDto[];
}
export interface WorkspaceSymbolsDto extends IdObject {
symbols: SymbolInformationDto[];
symbols: WorkspaceSymbolDto[];
}
export interface ResourceFileEditDto {
@@ -720,7 +785,7 @@ export interface CodeActionDto {
}
export interface ExtHostLanguageFeaturesShape {
$provideDocumentSymbols(handle: number, resource: UriComponents): TPromise<SymbolInformationDto[]>;
$provideDocumentSymbols(handle: number, resource: UriComponents): TPromise<modes.DocumentSymbol[]>;
$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[]>;
@@ -734,7 +799,7 @@ export interface ExtHostLanguageFeaturesShape {
$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>;
$resolveWorkspaceSymbol(handle: number, symbol: WorkspaceSymbolDto): TPromise<WorkspaceSymbolDto>;
$releaseWorkspaceSymbols(handle: number, id: number): void;
$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string): TPromise<WorkspaceEditDto>;
$resolveRenameLocation(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.RenameLocation>;
@@ -752,6 +817,10 @@ export interface ExtHostLanguageFeaturesShape {
export interface ExtHostQuickOpenShape {
$onItemSelected(handle: number): void;
$validateInput(input: string): TPromise<string>;
$onDidChangeActive(sessionId: number, handles: number[]): void;
$onDidChangeSelection(sessionId: number, handles: number[]): void;
$onDidAccept(sessionId: number): void;
$onDidTriggerButton(sessionId: number, handle: number): void;
}
export interface ShellLaunchConfigDto {
@@ -833,8 +902,6 @@ export interface ISourceMultiBreakpointDto {
export interface ExtHostDebugServiceShape {
$substituteVariables(folder: UriComponents | undefined, config: IConfig): TPromise<IConfig>;
$runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise<void>;
$isTerminalBusy(processId: number): TPromise<boolean>;
$prepareCommandForTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise<any>;
$startDASession(handle: number, debugType: string, adapterExecutableInfo: IAdapterExecutable | null, debugPort: number): TPromise<void>;
$stopDASession(handle: number): TPromise<void>;
$sendDAMessage(handle: number, message: DebugProtocol.ProtocolMessage): TPromise<void>;
@@ -874,10 +941,18 @@ export interface ExtHostProgressShape {
$acceptProgressCanceled(handle: number): void;
}
export interface ExtHostCommentsShape {
$provideDocumentComments(handle: number, document: UriComponents): TPromise<modes.CommentInfo>;
$createNewCommentThread?(handle: number, document: UriComponents, range: IRange, text: string): TPromise<modes.CommentThread>;
$replyToCommentThread?(handle: number, document: UriComponents, range: IRange, commentThread: modes.CommentThread, text: string): TPromise<modes.CommentThread>;
$provideWorkspaceComments(handle: number): TPromise<modes.CommentThread[]>;
}
// --- proxy identifiers
export const MainContext = {
MainThreadCommands: <ProxyIdentifier<MainThreadCommandsShape>>createMainId<MainThreadCommandsShape>('MainThreadCommands'),
MainThreadComments: createMainId<MainThreadCommentsShape>('MainThreadComments'),
MainThreadConfiguration: createMainId<MainThreadConfigurationShape>('MainThreadConfiguration'),
MainThreadDebugService: createMainId<MainThreadDebugServiceShape>('MainThreadDebugService'),
MainThreadDecorations: createMainId<MainThreadDecorationsShape>('MainThreadDecorations'),
@@ -935,6 +1010,7 @@ export const ExtHostContext = {
ExtHostWorkspace: createExtId<ExtHostWorkspaceShape>('ExtHostWorkspace'),
ExtHostWindow: createExtId<ExtHostWindowShape>('ExtHostWindow'),
ExtHostWebviews: createExtId<ExtHostWebviewsShape>('ExtHostWebviews'),
ExtHostUrls: createExtId<ExtHostUrlsShape>('ExtHostUrls'),
ExtHostProgress: createMainId<ExtHostProgressShape>('ExtHostProgress')
ExtHostProgress: createMainId<ExtHostProgressShape>('ExtHostProgress'),
ExtHostComments: createMainId<ExtHostCommentsShape>('ExtHostComments'),
ExtHostUrls: createExtId<ExtHostUrlsShape>('ExtHostUrls')
};

View File

@@ -11,12 +11,11 @@ import * as vscode from 'vscode';
import * as typeConverters from 'vs/workbench/api/node/extHostTypeConverters';
import * as types from 'vs/workbench/api/node/extHostTypes';
import { IRawColorInfo } from 'vs/workbench/api/node/extHost.protocol';
import { ISingleEditOperation } from 'vs/editor/common/model';
import * as modes from 'vs/editor/common/modes';
import * as search from 'vs/workbench/parts/search/common/search';
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
import { IWorkspaceSymbolProvider } from 'vs/workbench/parts/search/common/search';
import { CustomCodeAction } from 'vs/workbench/api/node/extHostLanguageFeatures';
import { ICommandsExecutor, PreviewHTMLAPICommand, OpenFolderAPICommand, DiffAPICommand, OpenAPICommand, RemoveFromRecentlyOpenedAPICommand } from './apiCommands';
@@ -266,11 +265,11 @@ export class ExtHostApiCommands {
* @return A promise that resolves to an array of symbol information.
*/
private _executeWorkspaceSymbolProvider(query: string): Thenable<types.SymbolInformation[]> {
return this._commands.executeCommand<[IWorkspaceSymbolProvider, modes.SymbolInformation[]][]>('_executeWorkspaceSymbolProvider', { query }).then(value => {
return this._commands.executeCommand<[search.IWorkspaceSymbolProvider, search.IWorkspaceSymbol[]][]>('_executeWorkspaceSymbolProvider', { query }).then(value => {
const result: types.SymbolInformation[] = [];
if (Array.isArray(value)) {
for (let tuple of value) {
result.push(...tuple[1].map(typeConverters.SymbolInformation.to));
result.push(...tuple[1].map(typeConverters.WorkspaceSymbol.to));
}
}
return result;
@@ -404,13 +403,13 @@ export class ExtHostApiCommands {
});
}
private _executeDocumentSymbolProvider(resource: URI): Thenable<types.SymbolInformation[]> {
private _executeDocumentSymbolProvider(resource: URI): Thenable<vscode.DocumentSymbol[]> {
const args = {
resource
};
return this._commands.executeCommand<modes.IOutline>('_executeDocumentSymbolProvider', args).then(value => {
if (value && Array.isArray(value.entries)) {
return value.entries.map(typeConverters.SymbolInformation.to);
return this._commands.executeCommand<modes.DocumentSymbol[]>('_executeDocumentSymbolProvider', args).then(value => {
if (value && Array.isArray(value)) {
return value.map(typeConverters.DocumentSymbol.to);
}
return undefined;
});

View File

@@ -131,6 +131,8 @@ export class ExtHostCommands implements ExtHostCommandsShape {
}
$executeContributedCommand<T>(id: string, ...args: any[]): Thenable<T> {
this._logService.trace('ExtHostCommands#$executeContributedCommand', id);
if (!this._commands.has(id)) {
return Promise.reject(new Error(`Contributed command '${id}' does not exist.`));
} else {

View File

@@ -0,0 +1,179 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { asWinJsPromise } from 'vs/base/common/async';
import URI, { UriComponents } from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import * as modes from 'vs/editor/common/modes';
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
import * as extHostTypeConverter from 'vs/workbench/api/node/extHostTypeConverters';
import * as vscode from 'vscode';
import { ExtHostCommentsShape, IMainContext, MainContext, MainThreadCommentsShape } from './extHost.protocol';
import { CommandsConverter } from './extHostCommands';
import { IRange } from 'vs/editor/common/core/range';
export class ExtHostComments implements ExtHostCommentsShape {
private static handlePool = 0;
private _proxy: MainThreadCommentsShape;
private _documentProviders = new Map<number, vscode.DocumentCommentProvider>();
private _workspaceProviders = new Map<number, vscode.WorkspaceCommentProvider>();
constructor(
mainContext: IMainContext,
private readonly _commandsConverter: CommandsConverter,
private readonly _documents: ExtHostDocuments,
) {
this._proxy = mainContext.getProxy(MainContext.MainThreadComments);
}
registerWorkspaceCommentProvider(
provider: vscode.WorkspaceCommentProvider
): vscode.Disposable {
const handle = ExtHostComments.handlePool++;
this._workspaceProviders.set(handle, provider);
this._proxy.$registerWorkspaceCommentProvider(handle);
this.registerListeners(handle, provider);
return {
dispose: () => {
this._proxy.$unregisterWorkspaceCommentProvider(handle);
this._workspaceProviders.delete(handle);
}
};
}
registerDocumentCommentProvider(
provider: vscode.DocumentCommentProvider
): vscode.Disposable {
const handle = ExtHostComments.handlePool++;
this._documentProviders.set(handle, provider);
this._proxy.$registerDocumentCommentProvider(handle);
this.registerListeners(handle, provider);
return {
dispose: () => {
this._proxy.$unregisterDocumentCommentProvider(handle);
this._documentProviders.delete(handle);
}
};
}
$createNewCommentThread(handle: number, uri: UriComponents, range: IRange, text: string): TPromise<modes.CommentThread> {
const data = this._documents.getDocumentData(URI.revive(uri));
const ran = <vscode.Range>extHostTypeConverter.Range.to(range);
if (!data || !data.document) {
return TPromise.as(null);
}
return asWinJsPromise(token => {
let provider = this._documentProviders.get(handle);
return provider.createNewCommentThread(data.document, ran, text, token);
}).then(commentThread => commentThread ? convertToCommentThread(commentThread, this._commandsConverter) : null);
}
$replyToCommentThread(handle: number, uri: UriComponents, range: IRange, thread: modes.CommentThread, text: string): TPromise<modes.CommentThread> {
const data = this._documents.getDocumentData(URI.revive(uri));
const ran = <vscode.Range>extHostTypeConverter.Range.to(range);
if (!data || !data.document) {
return TPromise.as(null);
}
return asWinJsPromise(token => {
let provider = this._documentProviders.get(handle);
return provider.replyToCommentThread(data.document, ran, convertFromCommentThread(thread), text, token);
}).then(commentThread => commentThread ? convertToCommentThread(commentThread, this._commandsConverter) : null);
}
$provideDocumentComments(handle: number, uri: UriComponents): TPromise<modes.CommentInfo> {
const data = this._documents.getDocumentData(URI.revive(uri));
if (!data || !data.document) {
return TPromise.as(null);
}
return asWinJsPromise(token => {
let provider = this._documentProviders.get(handle);
return provider.provideDocumentComments(data.document, token);
})
.then(commentInfo => commentInfo ? convertCommentInfo(handle, commentInfo, this._commandsConverter) : null);
}
$provideWorkspaceComments(handle: number): TPromise<modes.CommentThread[]> {
const provider = this._workspaceProviders.get(handle);
if (!provider) {
return TPromise.as(null);
}
return asWinJsPromise(token => {
return provider.provideWorkspaceComments(token);
}).then(comments =>
comments.map(x => convertToCommentThread(x, this._commandsConverter)
));
}
private registerListeners(handle: number, provider: vscode.DocumentCommentProvider | vscode.WorkspaceCommentProvider) {
provider.onDidChangeCommentThreads(event => {
this._proxy.$onDidCommentThreadsChange(handle, {
owner: handle,
changed: event.changed.map(x => convertToCommentThread(x, this._commandsConverter)),
added: event.added.map(x => convertToCommentThread(x, this._commandsConverter)),
removed: event.removed.map(x => convertToCommentThread(x, this._commandsConverter))
});
});
}
}
function convertCommentInfo(owner: number, vscodeCommentInfo: vscode.CommentInfo, commandsConverter: CommandsConverter): modes.CommentInfo {
return {
owner: owner,
threads: vscodeCommentInfo.threads.map(x => convertToCommentThread(x, commandsConverter)),
commentingRanges: vscodeCommentInfo.commentingRanges ? vscodeCommentInfo.commentingRanges.map(range => extHostTypeConverter.Range.from(range)) : []
};
}
function convertToCommentThread(vscodeCommentThread: vscode.CommentThread, commandsConverter: CommandsConverter): modes.CommentThread {
return {
threadId: vscodeCommentThread.threadId,
resource: vscodeCommentThread.resource.toString(),
range: extHostTypeConverter.Range.from(vscodeCommentThread.range),
comments: vscodeCommentThread.comments.map(comment => convertToComment(comment, commandsConverter)),
collapsibleState: vscodeCommentThread.collapsibleState
};
}
function convertFromCommentThread(commentThread: modes.CommentThread): vscode.CommentThread {
return {
threadId: commentThread.threadId,
resource: URI.parse(commentThread.resource),
range: extHostTypeConverter.Range.to(commentThread.range),
comments: commentThread.comments.map(convertFromComment),
collapsibleState: commentThread.collapsibleState
};
}
function convertFromComment(comment: modes.Comment): vscode.Comment {
return {
commentId: comment.commentId,
body: extHostTypeConverter.MarkdownString.to(comment.body),
userName: comment.userName,
gravatar: comment.gravatar
};
}
function convertToComment(vscodeComment: vscode.Comment, commandsConverter: CommandsConverter): modes.Comment {
return {
commentId: vscodeComment.commentId,
body: extHostTypeConverter.MarkdownString.from(vscodeComment.body),
userName: vscodeComment.userName,
gravatar: vscodeComment.gravatar,
command: vscodeComment.command ? commandsConverter.toInternal(vscodeComment.command) : null
};
}

View File

@@ -10,6 +10,7 @@ import URI, { UriComponents } from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { Event, Emitter } from 'vs/base/common/event';
import { asWinJsPromise } from 'vs/base/common/async';
import * as nls from 'vs/nls';
import {
MainContext, MainThreadDebugServiceShape, ExtHostDebugServiceShape, DebugSessionUUID,
IMainContext, IBreakpointsDeltaDto, ISourceMultiBreakpointDto, IFunctionBreakpointDto
@@ -24,10 +25,11 @@ import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumen
import { IAdapterExecutable, ITerminalSettings, IDebuggerContribution, IConfig, IDebugAdapter } from 'vs/workbench/parts/debug/common/debug';
import { getTerminalLauncher, hasChildprocesses, prepareCommand } from 'vs/workbench/parts/debug/node/terminals';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { VariableResolver } from 'vs/workbench/services/configurationResolver/node/variableResolver';
import { IStringDictionary } from 'vs/base/common/collections';
import { AbstractVariableResolverService } from 'vs/workbench/services/configurationResolver/node/variableResolver';
import { ExtHostConfiguration } from './extHostConfiguration';
import { convertToVSCPaths, convertToDAPaths } from 'vs/workbench/parts/debug/common/debugUtils';
import { ExtHostTerminalService } from 'vs/workbench/api/node/extHostTerminalService';
import { IDisposable } from 'vs/base/common/lifecycle';
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
@@ -66,12 +68,16 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
private _variableResolver: IConfigurationResolverService;
private _integratedTerminalInstance: vscode.Terminal;
private _terminalDisposedListener: IDisposable;
constructor(mainContext: IMainContext,
private _workspaceService: ExtHostWorkspace,
private _extensionService: ExtHostExtensionService,
private _editorsService: ExtHostDocumentsAndEditors,
private _configurationService: ExtHostConfiguration
private _configurationService: ExtHostConfiguration,
private _terminalService: ExtHostTerminalService
) {
this._handleCounter = 0;
@@ -117,22 +123,45 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
}
}
public $runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise<void> {
const terminalLauncher = getTerminalLauncher();
if (terminalLauncher) {
return terminalLauncher.runInTerminal(args, config);
public async $runInTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise<void> {
if (args.kind === 'integrated') {
if (!this._terminalDisposedListener) {
// React on terminal disposed and check if that is the debug terminal #12956
this._terminalDisposedListener = this._terminalService.onDidCloseTerminal(terminal => {
if (this._integratedTerminalInstance && this._integratedTerminalInstance === terminal) {
this._integratedTerminalInstance = null;
}
});
}
let t = this._integratedTerminalInstance;
if ((t && hasChildprocesses(await t.processId)) || !t) {
t = this._terminalService.createTerminal(args.title || nls.localize('debug.terminal.title', "debuggee"));
this._integratedTerminalInstance = t;
}
t.show();
return new TPromise((resolve, error) => {
setTimeout(_ => {
const command = prepareCommand(args, config);
t.sendText(command, true);
resolve(void 0);
}, 500);
});
} else if (args.kind === 'external') {
const terminalLauncher = getTerminalLauncher();
if (terminalLauncher) {
return terminalLauncher.runInTerminal(args, config);
}
}
return void 0;
}
public $isTerminalBusy(processId: number): TPromise<boolean> {
return asWinJsPromise(token => hasChildprocesses(processId));
}
public $prepareCommandForTerminal(args: DebugProtocol.RunInTerminalRequestArguments, config: ITerminalSettings): TPromise<any> {
return asWinJsPromise(token => prepareCommand(args, config));
}
public $substituteVariables(folderUri: UriComponents | undefined, config: IConfig): TPromise<IConfig> {
if (!this._variableResolver) {
this._variableResolver = new ExtHostVariableResolverService(this._workspaceService, this._editorsService, this._configurationService);
@@ -146,7 +175,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
throw new Error('Not implemented');
}
};
return asWinJsPromise(token => DebugAdapter.substituteVariables(ws, config, this._variableResolver));
return asWinJsPromise(token => this._variableResolver.resolveAny(ws, config));
}
public $startDASession(handle: number, debugType: string, adpaterExecutable: IAdapterExecutable | null, debugPort: number): TPromise<void> {
@@ -558,15 +587,12 @@ export class ExtHostDebugConsole implements vscode.DebugConsole {
}
}
export class ExtHostVariableResolverService implements IConfigurationResolverService {
export class ExtHostVariableResolverService extends AbstractVariableResolverService {
_serviceBrand: any;
_variableResolver: VariableResolver;
constructor(workspace: ExtHostWorkspace, editors: ExtHostDocumentsAndEditors, configuration: ExtHostConfiguration) {
this._variableResolver = new VariableResolver({
constructor(workspaceService: ExtHostWorkspace, editorService: ExtHostDocumentsAndEditors, configurationService: ExtHostConfiguration) {
super({
getFolderUri: (folderName: string): URI => {
const folders = workspace.getWorkspaceFolders();
const folders = workspaceService.getWorkspaceFolders();
const found = folders.filter(f => f.name === folderName);
if (found && found.length > 0) {
return found[0].uri;
@@ -574,16 +600,16 @@ export class ExtHostVariableResolverService implements IConfigurationResolverSer
return undefined;
},
getWorkspaceFolderCount: (): number => {
return workspace.getWorkspaceFolders().length;
return workspaceService.getWorkspaceFolders().length;
},
getConfigurationValue: (folderUri: URI, section: string) => {
return configuration.getConfiguration(undefined, folderUri).get<string>(section);
return configurationService.getConfiguration(undefined, folderUri).get<string>(section);
},
getExecPath: (): string | undefined => {
return undefined; // does not exist in EH
},
getFilePath: (): string | undefined => {
const activeEditor = editors.activeEditor();
const activeEditor = editorService.activeEditor();
if (activeEditor) {
const resource = activeEditor.document.uri;
if (resource.scheme === Schemas.file) {
@@ -593,34 +619,19 @@ export class ExtHostVariableResolverService implements IConfigurationResolverSer
return undefined;
},
getSelectedText: (): string | undefined => {
const activeEditor = editors.activeEditor();
const activeEditor = editorService.activeEditor();
if (activeEditor && !activeEditor.selection.isEmpty) {
return activeEditor.document.getText(activeEditor.selection);
}
return undefined;
},
getLineNumber: (): string => {
const activeEditor = editors.activeEditor();
const activeEditor = editorService.activeEditor();
if (activeEditor) {
return String(activeEditor.selection.end.line + 1);
}
return undefined;
}
}, process.env);
}
public resolve(root: IWorkspaceFolder, value: string): string;
public resolve(root: IWorkspaceFolder, value: string[]): string[];
public resolve(root: IWorkspaceFolder, value: IStringDictionary<string>): IStringDictionary<string>;
public resolve(root: IWorkspaceFolder, value: any): any {
return this._variableResolver.resolveAny(root ? root.uri : undefined, value);
}
public resolveAny<T>(root: IWorkspaceFolder, value: T, commandMapping?: IStringDictionary<string>): T {
return this._variableResolver.resolveAny(root ? root.uri : undefined, value, commandMapping);
}
public executeCommandVariables(configuration: any, variables: IStringDictionary<string>): TPromise<IStringDictionary<string>> {
throw new Error('findAndExecuteCommandVariables not implemented.');
});
}
}

View File

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

View File

@@ -78,32 +78,32 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
return Promise.resolve(false);
}
return this._deliverEventAsync(listener, thisArg, stubEvent).then(() => {
return this._deliverEventAsync(extension, listener, thisArg, stubEvent).then(() => {
// don't send result across the wire
return true;
}, err => {
this._logService.error('[onWillSaveTextDocument]', extension.id);
this._logService.error(`onWillSaveTextDocument-listener from extension '${extension.id}' threw ERROR`);
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);
// todo@joh signal to the listener?
// if (errors === this._thresholds.errors) {
// console.warn('BAD onWillSaveTextDocumentEvent-listener is from now on being ignored');
// }
if (errors > this._thresholds.errors) {
this._logService.info(`onWillSaveTextDocument-listener from extension '${extension.id}' will now be IGNORED because of timeouts and/or errors`);
}
}
return false;
});
}
private _deliverEventAsync(listener: Function, thisArg: any, stubEvent: vscode.TextDocumentWillSaveEvent): Promise<any> {
private _deliverEventAsync(extension: IExtensionDescription, listener: Function, thisArg: any, stubEvent: vscode.TextDocumentWillSaveEvent): Promise<any> {
const promises: Promise<vscode.TextEdit[]>[] = [];
const t1 = Date.now();
const { document, reason } = stubEvent;
const { version } = document;
@@ -133,6 +133,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
const handle = setTimeout(() => reject(new Error('timeout')), this._thresholds.timeout);
return Promise.all(promises).then(edits => {
this._logService.debug(`onWillSaveTextDocument-listener from extension '${extension.id}' finished after ${(Date.now() - t1)}ms`);
clearTimeout(handle);
resolve(edits);
}).catch(err => {

View File

@@ -13,7 +13,7 @@ import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/n
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { ExtHostStorage } from 'vs/workbench/api/node/extHostStorage';
import { createApiFactory, initializeExtensionApi, checkProposedApiEnabled } from 'vs/workbench/api/node/extHost.api.impl';
import { MainContext, MainThreadExtensionServiceShape, IWorkspaceData, IEnvironment, IInitData, ExtHostExtensionServiceShape, MainThreadTelemetryShape, IExtHostContext } from './extHost.protocol';
import { MainContext, MainThreadExtensionServiceShape, IWorkspaceData, IEnvironment, IInitData, ExtHostExtensionServiceShape, MainThreadTelemetryShape, IMainContext } from './extHost.protocol';
import { IExtensionMemento, ExtensionsActivator, ActivatedExtension, IExtensionAPI, IExtensionContext, EmptyExtension, IExtensionModule, ExtensionActivationTimesBuilder, ExtensionActivationTimes, ExtensionActivationReason, ExtensionActivatedByEvent } from 'vs/workbench/api/node/extHostExtensionActivator';
import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
@@ -136,7 +136,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
* This class is constructed manually because it is a service, so it doesn't use any ctor injection
*/
constructor(initData: IInitData,
extHostContext: IExtHostContext,
extHostContext: IMainContext,
extHostWorkspace: ExtHostWorkspace,
extHostConfiguration: ExtHostConfiguration,
extHostLogService: ExtHostLogService

View File

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

View File

@@ -9,7 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { mixin } from 'vs/base/common/objects';
import * as vscode from 'vscode';
import * as typeConvert from 'vs/workbench/api/node/extHostTypeConverters';
import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, SymbolInformation, Hierarchy, SymbolInformation2 } from 'vs/workbench/api/node/extHostTypes';
import { Range, Disposable, CompletionList, SnippetString, CodeActionKind, SymbolInformation, DocumentSymbol } 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';
@@ -17,10 +17,10 @@ import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands';
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
import { asWinJsPromise } from 'vs/base/common/async';
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, SymbolInformationDto, SuggestResultDto, WorkspaceSymbolsDto, SuggestionDto, CodeActionDto, ISerializedDocumentFilter } from './extHost.protocol';
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IdObject, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, ISerializedLanguageConfiguration, WorkspaceSymbolDto, SuggestResultDto, WorkspaceSymbolsDto, SuggestionDto, CodeActionDto, ISerializedDocumentFilter } from './extHost.protocol';
import { regExpLeadsToEndlessLoop } from 'vs/base/common/strings';
import { IPosition } from 'vs/editor/common/core/position';
import { IRange } from 'vs/editor/common/core/range';
import { IRange, Range as EditorRange } from 'vs/editor/common/core/range';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import { isObject } from 'vs/base/common/types';
import { ISelection, Selection } from 'vs/editor/common/core/selection';
@@ -37,21 +37,21 @@ class OutlineAdapter {
this._provider = provider;
}
provideDocumentSymbols(resource: URI): TPromise<SymbolInformationDto[]> {
provideDocumentSymbols(resource: URI): TPromise<modes.DocumentSymbol[]> {
let doc = this._documents.getDocumentData(resource).document;
return asWinJsPromise(token => this._provider.provideDocumentSymbols(doc, token)).then(value => {
if (isFalsyOrEmpty(value)) {
return undefined;
}
let [probe] = value;
if (!(probe instanceof Hierarchy)) {
value = OutlineAdapter._asSymbolHierarchy(<SymbolInformation[]>value);
if (value[0] instanceof DocumentSymbol) {
return (<DocumentSymbol[]>value).map(typeConvert.DocumentSymbol.from);
} else {
return OutlineAdapter._asDocumentSymbolTree(resource, <SymbolInformation[]>value);
}
return (<Hierarchy<SymbolInformation2>[]>value).map(typeConvert.HierarchicalSymbolInformation.from);
});
}
private static _asSymbolHierarchy(info: SymbolInformation[]): vscode.Hierarchy<SymbolInformation2>[] {
private static _asDocumentSymbolTree(resource: URI, info: SymbolInformation[]): modes.DocumentSymbol[] {
// first sort by start (and end) and then loop over all elements
// and build a tree based on containment.
info = info.slice(0).sort((a, b) => {
@@ -61,12 +61,17 @@ class OutlineAdapter {
}
return res;
});
let res: Hierarchy<SymbolInformation2>[] = [];
let parentStack: Hierarchy<SymbolInformation2>[] = [];
let res: modes.DocumentSymbol[] = [];
let parentStack: modes.DocumentSymbol[] = [];
for (let i = 0; i < info.length; i++) {
let element = new Hierarchy(new SymbolInformation2(info[i].name, '', info[i].kind, info[i].location.range, info[i].location));
element.parent.containerName = info[i].containerName;
element.parent.location = info[i].location; // todo@joh make this proper
let element = <modes.DocumentSymbol>{
name: info[i].name,
kind: typeConvert.SymbolKind.from(info[i].kind),
containerName: info[i].containerName,
fullRange: typeConvert.Range.from(info[i].location.range),
identifierRange: typeConvert.Range.from(info[i].location.range),
children: []
};
while (true) {
if (parentStack.length === 0) {
@@ -75,7 +80,7 @@ class OutlineAdapter {
break;
}
let parent = parentStack[parentStack.length - 1];
if (parent.parent.range.contains(element.parent.range) && !parent.parent.range.isEqual(element.parent.range)) {
if (EditorRange.containsRange(parent.fullRange, element.fullRange) && !EditorRange.equalsRange(parent.fullRange, element.fullRange)) {
parent.children.push(element);
parentStack.push(element);
break;
@@ -428,7 +433,7 @@ class NavigateTypeAdapter {
console.warn('INVALID SymbolInformation, lacks name', item);
continue;
}
const symbol = IdObject.mixin(typeConvert.SymbolInformation.from(item));
const symbol = IdObject.mixin(typeConvert.WorkspaceSymbol.from(item));
this._symbolCache[symbol._id] = item;
result.symbols.push(symbol);
}
@@ -441,7 +446,7 @@ class NavigateTypeAdapter {
});
}
resolveWorkspaceSymbol(symbol: SymbolInformationDto): TPromise<SymbolInformationDto> {
resolveWorkspaceSymbol(symbol: WorkspaceSymbolDto): TPromise<WorkspaceSymbolDto> {
if (typeof this._provider.resolveWorkspaceSymbol !== 'function') {
return TPromise.as(symbol);
@@ -450,7 +455,7 @@ class NavigateTypeAdapter {
const item = this._symbolCache[symbol._id];
if (item) {
return asWinJsPromise(token => this._provider.resolveWorkspaceSymbol(item, token)).then(value => {
return value && mixin(symbol, typeConvert.SymbolInformation.from(value), true);
return value && mixin(symbol, typeConvert.WorkspaceSymbol.from(value), true);
});
}
return undefined;
@@ -930,7 +935,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideDocumentSymbols(handle: number, resource: UriComponents): TPromise<SymbolInformationDto[]> {
$provideDocumentSymbols(handle: number, resource: UriComponents): TPromise<modes.DocumentSymbol[]> {
return this._withAdapter(handle, OutlineAdapter, adapter => adapter.provideDocumentSymbols(URI.revive(resource)));
}
@@ -1085,7 +1090,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.provideWorkspaceSymbols(search));
}
$resolveWorkspaceSymbol(handle: number, symbol: SymbolInformationDto): TPromise<SymbolInformationDto> {
$resolveWorkspaceSymbol(handle: number, symbol: WorkspaceSymbolDto): TPromise<WorkspaceSymbolDto> {
return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.resolveWorkspaceSymbol(symbol));
}

View File

@@ -8,10 +8,11 @@ import { ProgressOptions } from 'vscode';
import { MainThreadProgressShape, ExtHostProgressShape } from './extHost.protocol';
import { ProgressLocation } from './extHostTypeConverters';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { IProgressStep, Progress } from 'vs/platform/progress/common/progress';
import { Progress } from 'vs/platform/progress/common/progress';
import { localize } from 'vs/nls';
import { CancellationTokenSource, CancellationToken } from 'vs/base/common/cancellation';
import { debounce } from 'vs/base/common/decorators';
import { IProgressStep } from 'vs/workbench/services/progress/common/progress';
export class ExtHostProgress implements ExtHostProgressShape {

View File

@@ -4,13 +4,18 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { wireCancellationToken, asWinJsPromise } from 'vs/base/common/async';
import { asWinJsPromise, wireCancellationToken } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation';
import { QuickPickOptions, QuickPickItem, InputBoxOptions, WorkspaceFolderPickOptions, WorkspaceFolder } from 'vscode';
import { MainContext, MainThreadQuickOpenShape, ExtHostQuickOpenShape, MyQuickPickItems, IMainContext } from './extHost.protocol';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { Emitter } from 'vs/base/common/event';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
import { assign } from 'vs/base/common/objects';
import { TPromise } from 'vs/base/common/winjs.base';
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { InputBox, InputBoxOptions, QuickInput, QuickInputButton, QuickPick, QuickPickItem, QuickPickOptions, WorkspaceFolder, WorkspaceFolderPickOptions } from 'vscode';
import { ExtHostQuickOpenShape, IMainContext, MainContext, MainThreadQuickOpenShape, TransferQuickPickItems, TransferQuickInput, TransferQuickInputButton } from './extHost.protocol';
import URI from 'vs/base/common/uri';
import { ThemeIcon } from 'vs/workbench/api/node/extHostTypes';
export type Item = string | QuickPickItem;
@@ -23,23 +28,25 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
private _onDidSelectItem: (handle: number) => void;
private _validateInput: (input: string) => string | Thenable<string>;
private _sessions = new Map<number, ExtHostQuickInput>();
constructor(mainContext: IMainContext, workspace: ExtHostWorkspace, commands: ExtHostCommands) {
this._proxy = mainContext.getProxy(MainContext.MainThreadQuickOpen);
this._workspace = workspace;
this._commands = commands;
}
showQuickPick(multiStepHandle: number | undefined, itemsOrItemsPromise: QuickPickItem[] | Thenable<QuickPickItem[]>, options: QuickPickOptions & { canPickMany: true; }, token?: CancellationToken): Thenable<QuickPickItem[] | undefined>;
showQuickPick(multiStepHandle: number | undefined, itemsOrItemsPromise: string[] | Thenable<string[]>, options?: QuickPickOptions, token?: CancellationToken): Thenable<string | undefined>;
showQuickPick(multiStepHandle: number | undefined, itemsOrItemsPromise: QuickPickItem[] | Thenable<QuickPickItem[]>, options?: QuickPickOptions, token?: CancellationToken): Thenable<QuickPickItem | undefined>;
showQuickPick(multiStepHandle: number | undefined, itemsOrItemsPromise: Item[] | Thenable<Item[]>, options?: QuickPickOptions, token: CancellationToken = CancellationToken.None): Thenable<Item | Item[] | undefined> {
showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Thenable<QuickPickItem[]>, options: QuickPickOptions & { canPickMany: true; }, token?: CancellationToken): Thenable<QuickPickItem[] | undefined>;
showQuickPick(itemsOrItemsPromise: string[] | Thenable<string[]>, options?: QuickPickOptions, token?: CancellationToken): Thenable<string | undefined>;
showQuickPick(itemsOrItemsPromise: QuickPickItem[] | Thenable<QuickPickItem[]>, options?: QuickPickOptions, token?: CancellationToken): Thenable<QuickPickItem | undefined>;
showQuickPick(itemsOrItemsPromise: Item[] | Thenable<Item[]>, options?: QuickPickOptions, token: CancellationToken = CancellationToken.None): Thenable<Item | Item[] | undefined> {
// clear state from last invocation
this._onDidSelectItem = undefined;
const itemsPromise = <TPromise<Item[]>>TPromise.wrap(itemsOrItemsPromise);
const quickPickWidget = this._proxy.$show(multiStepHandle, {
const quickPickWidget = this._proxy.$show({
placeHolder: options && options.placeHolder,
matchOnDescription: options && options.matchOnDescription,
matchOnDetail: options && options.matchOnDetail,
@@ -54,7 +61,7 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
return itemsPromise.then(items => {
let pickItems: MyQuickPickItems[] = [];
let pickItems: TransferQuickPickItems[] = [];
for (let handle = 0; handle < items.length; handle++) {
let item = items[handle];
@@ -115,12 +122,12 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
// ---- input
showInput(multiStepHandle: number | undefined, options?: InputBoxOptions, token: CancellationToken = CancellationToken.None): Thenable<string> {
showInput(options?: InputBoxOptions, token: CancellationToken = CancellationToken.None): Thenable<string> {
// global validate fn used in callback below
this._validateInput = options && options.validateInput;
const promise = this._proxy.$input(multiStepHandle, options, typeof this._validateInput === 'function');
const promise = this._proxy.$input(options, typeof this._validateInput === 'function');
return wireCancellationToken(token, promise, true);
}
@@ -142,4 +149,406 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
return this._workspace.getWorkspaceFolders().filter(folder => folder.uri.toString() === selectedFolder.uri.toString())[0];
});
}
// ---- QuickInput
createQuickPick(extensionId: string): QuickPick {
const session = new ExtHostQuickPick(this._proxy, extensionId, () => this._sessions.delete(session._id));
this._sessions.set(session._id, session);
return session;
}
createInputBox(extensionId: string): InputBox {
const session = new ExtHostInputBox(this._proxy, extensionId, () => this._sessions.delete(session._id));
this._sessions.set(session._id, session);
return session;
}
$onDidAccept(sessionId: number): void {
const session = this._sessions.get(sessionId);
if (session instanceof ExtHostQuickPick) {
session._fireDidAccept();
}
}
$onDidChangeActive(sessionId: number, handles: number[]): void {
const session = this._sessions.get(sessionId);
if (session instanceof ExtHostQuickPick) {
session._fireDidChangeFocus(handles);
}
}
$onDidChangeSelection(sessionId: number, handles: number[]): void {
const session = this._sessions.get(sessionId);
if (session instanceof ExtHostQuickPick) {
session._fireDidChangeSelection(handles);
}
}
$onDidTriggerButton(sessionId: number, handle: number): void {
const session = this._sessions.get(sessionId);
if (session) {
session._fireDidTriggerButton(handle);
}
}
}
class ExtHostQuickInput implements QuickInput {
private static _nextId = 1;
_id = ExtHostQuickPick._nextId++;
private _visible = false;
private _enabled = true;
private _busy = false;
private _ignoreFocusOut = true;
private _buttons: QuickInputButton[] = [];
private _handlesToButtons = new Map<number, QuickInputButton>();
private _onDidTriggerButtonEmitter = new Emitter<QuickInputButton>();
private _onDidHideEmitter = new Emitter<void>();
private _updateTimeout: number;
private _pendingUpdate: TransferQuickInput = { id: this._id };
private _disposed = false;
protected _disposables: IDisposable[] = [
this._onDidTriggerButtonEmitter,
this._onDidHideEmitter,
];
constructor(protected _proxy: MainThreadQuickOpenShape, protected _extensionId: string, private _onDidDispose: () => void) {
}
get enabled() {
return this._enabled;
}
set enabled(enabled: boolean) {
this._enabled = enabled;
this.update({ enabled });
}
get busy() {
return this._busy;
}
set busy(busy: boolean) {
this._busy = busy;
this.update({ busy });
}
get ignoreFocusOut() {
return this._ignoreFocusOut;
}
set ignoreFocusOut(ignoreFocusOut: boolean) {
this._ignoreFocusOut = ignoreFocusOut;
this.update({ ignoreFocusOut });
}
get buttons() {
return this._buttons;
}
set buttons(buttons: QuickInputButton[]) {
this._buttons = buttons;
this._handlesToButtons.clear();
buttons.forEach((button, i) => {
this._handlesToButtons.set(i, button);
});
this.update({
buttons: buttons.map<TransferQuickInputButton>((button, i) => ({
iconPath: getIconUris(button.iconPath),
toolTip: button.tooltip,
handle: i,
}))
});
}
onDidTriggerButton = this._onDidTriggerButtonEmitter.event;
show(): void {
this._visible = true;
this.update({ visible: true });
}
hide(): void {
this._visible = false;
this.update({ visible: false });
}
onDidHide = this._onDidHideEmitter.event;
_fireDidTriggerButton(handle: number) {
const button = this._handlesToButtons.get(handle);
this._onDidTriggerButtonEmitter.fire(button);
}
public dispose(): void {
if (this._disposed) {
return;
}
this._disposed = true;
this._disposables = dispose(this._disposables);
if (this._updateTimeout) {
clearTimeout(this._updateTimeout);
this._updateTimeout = undefined;
}
this._proxy.$dispose(this._id);
this._onDidDispose();
}
protected update(properties: Record<string, any>): void {
if (this._disposed) {
return;
}
assign(this._pendingUpdate, properties);
if (!this._visible) {
return;
}
if (properties.visible) {
if (this._updateTimeout) {
clearTimeout(this._updateTimeout);
this._updateTimeout = undefined;
}
this.dispatchUpdate();
} else if (!this._updateTimeout) {
// Defer the update so that multiple changes to setters dont cause a redraw each
this._updateTimeout = setTimeout(() => {
this._updateTimeout = undefined;
this.dispatchUpdate();
}, 0);
}
}
private dispatchUpdate() {
this._proxy.$createOrUpdate(this._pendingUpdate);
this._pendingUpdate = { id: this._id };
}
}
function getIconUris(iconPath: QuickInputButton['iconPath']) {
const light = getLightIconUri(iconPath);
return { dark: getDarkIconUri(iconPath) || light, light };
}
function getLightIconUri(iconPath: QuickInputButton['iconPath']) {
if (iconPath && !(iconPath instanceof ThemeIcon)) {
if (typeof iconPath === 'string'
|| iconPath instanceof URI) {
return getIconUri(iconPath);
}
return getIconUri(iconPath['light']);
}
return undefined;
}
function getDarkIconUri(iconPath: QuickInputButton['iconPath']) {
if (iconPath && !(iconPath instanceof ThemeIcon) && iconPath['dark']) {
return getIconUri(iconPath['dark']);
}
return undefined;
}
function getIconUri(iconPath: string | URI) {
if (iconPath instanceof URI) {
return iconPath;
}
return URI.file(iconPath);
}
class ExtHostQuickPick extends ExtHostQuickInput implements QuickPick {
private _value = '';
private _placeholder: string;
private _onDidChangeValueEmitter = new Emitter<string>();
private _onDidAcceptEmitter = new Emitter<void>();
private _items: QuickPickItem[] = [];
private _handlesToItems = new Map<number, QuickPickItem>();
private _canSelectMany = false;
private _matchOnDescription = true;
private _matchOnDetail = true;
private _focusedItems: QuickPickItem[] = [];
private _onDidChangeActiveEmitter = new Emitter<QuickPickItem[]>();
private _selectedItems: QuickPickItem[] = [];
private _onDidChangeSelectionEmitter = new Emitter<QuickPickItem[]>();
constructor(proxy: MainThreadQuickOpenShape, extensionId: string, onDispose: () => void) {
super(proxy, extensionId, onDispose);
this._disposables.push(
this._onDidChangeValueEmitter,
this._onDidAcceptEmitter,
this._onDidChangeActiveEmitter,
this._onDidChangeSelectionEmitter,
);
this.update({ type: 'quickPick' });
}
get value() {
return this._value;
}
set value(value: string) {
this._value = value;
this.update({ value });
}
get placeholder() {
return this._placeholder;
}
set placeholder(placeholder: string) {
this._placeholder = placeholder;
this.update({ placeholder });
}
onDidChangeValue = this._onDidChangeValueEmitter.event;
onDidAccept = this._onDidAcceptEmitter.event;
get items() {
return this._items;
}
set items(items: QuickPickItem[]) {
this._items = items;
this._handlesToItems.clear();
items.forEach((item, i) => {
this._handlesToItems.set(i, item);
});
this.update({
items: items.map((item, i) => ({
label: item.label,
description: item.description,
handle: i,
detail: item.detail,
picked: item.picked
}))
});
}
get canSelectMany() {
return this._canSelectMany;
}
set canSelectMany(canSelectMany: boolean) {
this._canSelectMany = canSelectMany;
this.update({ canSelectMany });
}
get matchOnDescription() {
return this._matchOnDescription;
}
set matchOnDescription(matchOnDescription: boolean) {
this._matchOnDescription = matchOnDescription;
this.update({ matchOnDescription });
}
get matchOnDetail() {
return this._matchOnDetail;
}
set matchOnDetail(matchOnDetail: boolean) {
this._matchOnDetail = matchOnDetail;
this.update({ matchOnDetail });
}
get activeItems() {
return this._focusedItems;
}
onDidChangeActive = this._onDidChangeActiveEmitter.event;
get selectedItems() {
return this._selectedItems;
}
onDidChangeSelection = this._onDidChangeSelectionEmitter.event;
_fireDidAccept() {
this._onDidAcceptEmitter.fire();
}
_fireDidChangeFocus(handles: number[]) {
const items = handles.map(handle => this._handlesToItems.get(handle));
this._focusedItems = items;
this._onDidChangeActiveEmitter.fire(items);
}
_fireDidChangeSelection(handles: number[]) {
const items = handles.map(handle => this._handlesToItems.get(handle));
this._selectedItems = items;
this._onDidChangeSelectionEmitter.fire(items);
}
}
class ExtHostInputBox extends ExtHostQuickInput implements InputBox {
private _value = '';
private _placeholder: string;
private _password: boolean;
private _prompt: string;
private _validationMessage: string;
private _onDidChangeValueEmitter = new Emitter<string>();
private _onDidAcceptEmitter = new Emitter<string>();
constructor(proxy: MainThreadQuickOpenShape, extensionId: string, onDispose: () => void) {
super(proxy, extensionId, onDispose);
this._disposables.push(
this._onDidChangeValueEmitter,
this._onDidAcceptEmitter,
);
this.update({ type: 'inputBox' });
}
get value() {
return this._value;
}
set value(value: string) {
this._value = value;
this.update({ value });
}
get placeholder() {
return this._placeholder;
}
set placeholder(placeholder: string) {
this._placeholder = placeholder;
this.update({ placeholder });
}
get password() {
return this._password;
}
set password(password: boolean) {
this._password = password;
this.update({ password });
}
get prompt() {
return this._prompt;
}
set prompt(prompt: string) {
this._prompt = prompt;
this.update({ prompt });
}
get validationMessage() {
return this._validationMessage;
}
set validationMessage(validationMessage: string) {
this._validationMessage = validationMessage;
this.update({ validationMessage });
}
onDidChangeValue = this._onDidChangeValueEmitter.event;
onDidAccept = this._onDidAcceptEmitter.event;
}

View File

@@ -454,7 +454,7 @@ class TextSearchEngine {
new TPromise(resolve => process.nextTick(resolve))
.then(() => {
this.activeCancellationTokens.add(cancellation);
return this.provider.provideTextSearchResults(this.pattern, searchOptions, progress, cancellation.token);
return this.provider.provideTextSearchResults(patternInfoToQuery(this.pattern), searchOptions, progress, cancellation.token);
})
.then(() => {
this.activeCancellationTokens.delete(cancellation);
@@ -500,6 +500,15 @@ class TextSearchEngine {
}
}
function patternInfoToQuery(patternInfo: IPatternInfo): vscode.TextSearchQuery {
return <vscode.TextSearchQuery>{
isCaseSensitive: patternInfo.isCaseSensitive || false,
isRegExp: patternInfo.isRegExp || false,
isWordMatch: patternInfo.isWordMatch || false,
pattern: patternInfo.pattern
};
}
class FileSearchEngine {
private filePattern: string;
private normalizedFilePatternLowercase: string;

View File

@@ -28,8 +28,6 @@ import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumen
import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
export { TaskExecutionDTO };
/*
namespace ProblemPattern {
export function from(value: vscode.ProblemPattern | vscode.MultiLineProblemPattern): Problems.ProblemPattern | Problems.MultiLineProblemPattern {
@@ -234,13 +232,14 @@ namespace TaskPanelKind {
namespace PresentationOptions {
export function from(value: vscode.TaskPresentationOptions): tasks.PresentationOptions {
if (value === void 0 || value === null) {
return { reveal: tasks.RevealKind.Always, echo: true, focus: false, panel: tasks.PanelKind.Shared };
return { reveal: tasks.RevealKind.Always, echo: true, focus: false, panel: tasks.PanelKind.Shared, showReuseMessage: true };
}
return {
reveal: TaskRevealKind.from(value.reveal),
echo: value.echo === void 0 ? true : !!value.echo,
focus: !!value.focus,
panel: TaskPanelKind.from(value.panel)
panel: TaskPanelKind.from(value.panel),
showReuseMessage: value.showReuseMessage === void 0 ? true : !!value.showReuseMessage
};
}
}
@@ -385,21 +384,16 @@ namespace Tasks {
// in shape and we don't have backwards converting function. So transfer the URI and resolve the
// workspace folder on the main side.
(source as any as tasks.ExtensionTaskSourceTransfer).__workspaceFolder = workspaceFolder ? workspaceFolder.uri as URI : undefined;
(source as any as tasks.ExtensionTaskSourceTransfer).__definition = task.definition;
let label = nls.localize('task.label', '{0}: {1}', source.label, task.name);
let key = (task as types.Task).definitionKey;
let kind = (task as types.Task).definition;
let id = `${extension.id}.${key}`;
let taskKind: tasks.TaskIdentifier = {
_key: key,
type: kind.type
};
Objects.assign(taskKind, kind);
// The definition id will be prefix on the main side since we compute it there.
let id = `${extension.id}`;
let result: tasks.ContributedTask = {
_id: id, // uuidMap.getUUID(identifier),
_id: id,
_source: source,
_label: label,
type: kind.type,
defines: taskKind,
type: task.definition.type,
defines: undefined,
name: task.name,
identifier: label,
group: task.group ? (task.group as types.TaskGroup).id : undefined,

View File

@@ -6,13 +6,14 @@
import * as modes from 'vs/editor/common/modes';
import * as types from './extHostTypes';
import * as search from 'vs/workbench/parts/search/common/search';
import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { EditorViewColumn } from 'vs/workbench/api/shared/editor';
import { IDecorationOptions } from 'vs/editor/common/editorCommon';
import { EndOfLineSequence } from 'vs/editor/common/model';
import * as vscode from 'vscode';
import URI from 'vs/base/common/uri';
import { ProgressLocation as MainProgressLocation } from 'vs/platform/progress/common/progress';
import { ProgressLocation as MainProgressLocation } from 'vs/workbench/services/progress/common/progress';
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
import { IPosition } from 'vs/editor/common/core/position';
import { IRange } from 'vs/editor/common/core/range';
@@ -355,16 +356,16 @@ export namespace SymbolKind {
}
}
export namespace SymbolInformation {
export function from(info: vscode.SymbolInformation): modes.SymbolInformation {
return <modes.SymbolInformation>{
export namespace WorkspaceSymbol {
export function from(info: vscode.SymbolInformation): search.IWorkspaceSymbol {
return <search.IWorkspaceSymbol>{
name: info.name,
kind: SymbolKind.from(info.kind),
containerName: info.containerName,
location: location.from(info.location)
};
}
export function to(info: modes.SymbolInformation): types.SymbolInformation {
export function to(info: search.IWorkspaceSymbol): types.SymbolInformation {
return new types.SymbolInformation(
info.name,
SymbolKind.to(info.kind),
@@ -374,31 +375,30 @@ export namespace SymbolInformation {
}
}
export namespace HierarchicalSymbolInformation {
export function from(info: vscode.Hierarchy<vscode.SymbolInformation2>): modes.SymbolInformation {
let result: modes.SymbolInformation = {
name: info.parent.name,
detail: info.parent.detail,
location: location.from(info.parent.location),
definingRange: Range.from(info.parent.range),
kind: SymbolKind.from(info.parent.kind),
containerName: info.parent.containerName
export namespace DocumentSymbol {
export function from(info: vscode.DocumentSymbol): modes.DocumentSymbol {
let result: modes.DocumentSymbol = {
name: info.name,
detail: info.detail,
fullRange: Range.from(info.fullRange),
identifierRange: Range.from(info.gotoRange),
kind: SymbolKind.from(info.kind)
};
if (info.children) {
result.children = info.children.map(from);
}
return result;
}
export function to(info: modes.SymbolInformation): types.Hierarchy<vscode.SymbolInformation2> {
let result = new types.Hierarchy<vscode.SymbolInformation2>(new types.SymbolInformation2(
export function to(info: modes.DocumentSymbol): vscode.DocumentSymbol {
let result = new types.DocumentSymbol(
info.name,
info.detail,
SymbolKind.to(info.kind),
Range.to(info.definingRange),
location.to(info.location),
));
Range.to(info.fullRange),
Range.to(info.identifierRange),
);
if (info.children) {
result.children = info.children.map(to);
result.children = info.children.map(to) as any;
}
return result;
}

View File

@@ -881,28 +881,29 @@ export class SymbolInformation {
}
}
export class SymbolInformation2 extends SymbolInformation {
export class DocumentSymbol {
name: string;
detail: string;
range: Range;
kind: SymbolKind;
fullRange: Range;
gotoRange: Range;
children: DocumentSymbol[];
constructor(name: string, detail: string, kind: SymbolKind, range: Range, location: Location) {
super(name, kind, undefined, location);
constructor(name: string, detail: string, kind: SymbolKind, fullRange: Range, gotoRange: Range) {
this.name = name;
this.detail = detail;
this.range = range;
}
}
export class Hierarchy<T> {
parent: T;
children: Hierarchy<T>[];
constructor(parent: T) {
this.parent = parent;
this.kind = kind;
this.fullRange = fullRange;
this.gotoRange = gotoRange;
this.children = [];
if (!this.fullRange.contains(this.gotoRange)) {
throw new Error('gotoRange must be contained in fullRange');
}
}
}
export enum CodeActionTrigger {
Automatic = 1,
Manual = 2,
@@ -1494,7 +1495,6 @@ export class Task implements vscode.Task {
private __id: string;
private _definition: vscode.TaskDefinition;
private _definitionKey: string;
private _scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder;
private _name: string;
private _execution: ProcessExecution | ShellExecution;
@@ -1555,7 +1555,6 @@ export class Task implements vscode.Task {
}
this.__id = undefined;
this._scope = undefined;
this._definitionKey = undefined;
this._definition = undefined;
if (this._execution instanceof ProcessExecution) {
this._definition = {
@@ -1579,19 +1578,9 @@ export class Task implements vscode.Task {
throw illegalArgument('Kind can\'t be undefined or null');
}
this.clear();
this._definitionKey = undefined;
this._definition = value;
}
get definitionKey(): string {
if (!this._definitionKey) {
const hash = crypto.createHash('md5');
hash.update(JSON.stringify(this._definition));
this._definitionKey = hash.digest('hex');
}
return this._definitionKey;
}
get scope(): vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder {
return this._scope;
}
@@ -1845,12 +1834,6 @@ export enum LogLevel {
}
//#region file api
// todo@remote
export enum DeprecatedFileChangeType {
Updated = 0,
Added = 1,
Deleted = 2
}
export enum FileChangeType {
Changed = 1,
@@ -1858,12 +1841,6 @@ export enum FileChangeType {
Deleted = 3,
}
export enum DeprecatedFileType {
File = 0,
Dir = 1,
Symlink = 2
}
export class FileSystemError extends Error {
static FileExists(messageOrUri?: string | URI): FileSystemError {
@@ -1928,3 +1905,15 @@ export enum FoldingRangeKind {
}
//#endregion
export enum CommentThreadCollapsibleState {
/**
* Determines an item is collapsed
*/
Collapsed = 0,
/**
* Determines an item is expanded
*/
Expanded = 1
}