Merge with master

This commit is contained in:
Gabriel DeBacker
2019-02-12 09:21:33 -08:00
429 changed files with 8684 additions and 4623 deletions

View File

@@ -58,7 +58,7 @@ import * as extHostTypes from 'vs/workbench/api/node/extHostTypes';
import { ExtHostUrls } from 'vs/workbench/api/node/extHostUrls';
import { ExtHostWebviews } from 'vs/workbench/api/node/extHostWebview';
import { ExtHostWindow } from 'vs/workbench/api/node/extHostWindow';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { ExtHostWorkspace, ExtHostWorkspaceProvider } from 'vs/workbench/api/node/extHostWorkspace';
import { IExtensionDescription, throwProposedApiError, checkProposedApiEnabled, nullExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { ProxyIdentifier } from 'vs/workbench/services/extensions/node/proxyIdentifier';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry';
@@ -66,7 +66,7 @@ import * as vscode from 'vscode';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
export interface IExtensionApiFactory {
(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode;
(extension: IExtensionDescription, registry: ExtensionDescriptionRegistry, workspaceProvider: ExtHostWorkspaceProvider, configProvider: ExtHostConfigProvider): typeof vscode;
}
function proposedApiFunction<T>(extension: IExtensionDescription, fn: T): T {
@@ -142,7 +142,7 @@ export function createApiFactory(
// Register API-ish commands
ExtHostApiCommands.register(extHostCommands);
return function (extension: IExtensionDescription, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): typeof vscode {
return function (extension: IExtensionDescription, extensionRegistry: ExtensionDescriptionRegistry, workspaceProvider: ExtHostWorkspaceProvider, configProvider: ExtHostConfigProvider): typeof vscode {
// Check document selectors for being overly generic. Technically this isn't a problem but
// in practice many extensions say they support `fooLang` but need fs-access to do so. Those
@@ -219,7 +219,7 @@ export function createApiFactory(
});
},
registerDiffInformationCommand: proposedApiFunction(extension, (id: string, callback: (diff: vscode.LineChange[], ...args: any[]) => any, thisArg?: any): vscode.Disposable => {
return extHostCommands.registerCommand(true, id, async (...args: any[]) => {
return extHostCommands.registerCommand(true, id, async (...args: any[]): Promise<any> => {
let activeTextEditor = extHostEditors.getActiveTextEditor();
if (!activeTextEditor) {
console.warn('Cannot execute ' + id + ' because there is no active text editor.');
@@ -242,9 +242,9 @@ export function createApiFactory(
const env: typeof vscode.env = Object.freeze({
get machineId() { return initData.telemetryInfo.machineId; },
get sessionId() { return initData.telemetryInfo.sessionId; },
get language() { return platform.language; },
get language() { return platform.language!; },
get appName() { return product.nameLong; },
get appRoot() { return initData.environment.appRoot.fsPath; },
get appRoot() { return initData.environment.appRoot!.fsPath; },
get logLevel() {
checkProposedApiEnabled(extension);
return typeConverters.LogLevel.to(extHostLogService.getLevel());
@@ -263,8 +263,8 @@ export function createApiFactory(
// namespace: extensions
const extensions: typeof vscode.extensions = {
getExtension(extensionId: string): Extension<any> {
let desc = extensionRegistry.getExtensionDescription(extensionId);
getExtension(extensionId: string): Extension<any> | undefined {
const desc = extensionRegistry.getExtensionDescription(extensionId);
if (desc) {
return new Extension(extensionService, desc);
}
@@ -443,7 +443,7 @@ 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(items, extension.enableProposedApi, options, token);
return extHostQuickOpen.showQuickPick(items, !!extension.enableProposedApi, options, token);
},
showWorkspaceFolderPick(options: vscode.WorkspaceFolderPickOptions) {
return extHostQuickOpen.showWorkspaceFolderPick(options);
@@ -511,34 +511,34 @@ export function createApiFactory(
// namespace: workspace
const workspace: typeof vscode.workspace = {
get rootPath() {
return extHostWorkspace.getPath();
return workspaceProvider.getPath();
},
set rootPath(value) {
throw errors.readonly();
},
getWorkspaceFolder(resource) {
return extHostWorkspace.getWorkspaceFolder(resource);
return workspaceProvider.getWorkspaceFolder(resource);
},
get workspaceFolders() {
return extHostWorkspace.getWorkspaceFolders();
return workspaceProvider.getWorkspaceFolders();
},
get name() {
return extHostWorkspace.name;
return workspaceProvider.name;
},
set name(value) {
throw errors.readonly();
},
updateWorkspaceFolders: (index, deleteCount, ...workspaceFoldersToAdd) => {
return extHostWorkspace.updateWorkspaceFolders(extension, index, deleteCount || 0, ...workspaceFoldersToAdd);
return workspaceProvider.updateWorkspaceFolders(extension, index, deleteCount || 0, ...workspaceFoldersToAdd);
},
onDidChangeWorkspaceFolders: function (listener, thisArgs?, disposables?) {
return extHostWorkspace.onDidChangeWorkspace(listener, thisArgs, disposables);
return workspaceProvider.onDidChangeWorkspace(listener, thisArgs, disposables);
},
asRelativePath: (pathOrUri, includeWorkspace) => {
return extHostWorkspace.getRelativePath(pathOrUri, includeWorkspace);
return workspaceProvider.getRelativePath(pathOrUri, includeWorkspace);
},
findFiles: (include, exclude, maxResults?, token?) => {
return extHostWorkspace.findFiles(typeConverters.GlobPattern.from(include), typeConverters.GlobPattern.from(exclude), maxResults, extension.identifier, token);
return workspaceProvider.findFiles(typeConverters.GlobPattern.from(include), typeConverters.GlobPattern.from(exclude), maxResults, extension.identifier, token);
},
findTextInFiles: (query: vscode.TextSearchQuery, optionsOrCallback, callbackOrToken?, token?: vscode.CancellationToken) => {
let options: vscode.FindTextInFilesOptions;
@@ -553,10 +553,10 @@ export function createApiFactory(
token = callbackOrToken;
}
return extHostWorkspace.findTextInFiles(query, options || {}, callback, extension.identifier, token);
return workspaceProvider.findTextInFiles(query, options || {}, callback, extension.identifier, token);
},
saveAll: (includeUntitled?) => {
return extHostWorkspace.saveAll(includeUntitled);
return workspaceProvider.saveAll(includeUntitled);
},
applyEdit(edit: vscode.WorkspaceEdit): Thenable<boolean> {
return extHostEditors.applyWorkspaceEdit(edit);
@@ -774,7 +774,7 @@ export function createApiFactory(
DocumentSymbol: extHostTypes.DocumentSymbol,
EndOfLine: extHostTypes.EndOfLine,
EventEmitter: Emitter,
ExtensionCallbackExecution: extHostTypes.ExtensionCallbackExecution,
CustomTaskExecution: extHostTypes.CustomTaskExecution,
FileChangeType: extHostTypes.FileChangeType,
FileSystemError: extHostTypes.FileSystemError,
FileType: files.FileType,
@@ -809,7 +809,7 @@ export function createApiFactory(
SymbolInformation: extHostTypes.SymbolInformation,
SymbolKind: extHostTypes.SymbolKind,
Task: extHostTypes.Task,
TaskWithExtensionCallback: extHostTypes.Task,
TaskWithCustomTaskExecution: extHostTypes.Task,
TaskGroup: extHostTypes.TaskGroup,
TaskPanelKind: extHostTypes.TaskPanelKind,
TaskRevealKind: extHostTypes.TaskRevealKind,
@@ -852,7 +852,7 @@ class Extension<T> implements vscode.Extension<T> {
public id: string;
public extensionPath: string;
public packageJSON: any;
public packageJSON: IExtensionDescription;
constructor(extensionService: ExtHostExtensionService, description: IExtensionDescription) {
this._extensionService = extensionService;
@@ -867,6 +867,9 @@ class Extension<T> implements vscode.Extension<T> {
}
get exports(): T {
if (this.packageJSON.api === 'none') {
return undefined;
}
return <T>this._extensionService.getExtensionExports(this._identifier);
}
@@ -875,11 +878,11 @@ class Extension<T> implements vscode.Extension<T> {
}
}
export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: IExtensionApiFactory, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): Promise<void> {
return extensionService.getExtensionPathIndex().then(trie => defineAPI(apiFactory, trie, extensionRegistry, configProvider));
export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: IExtensionApiFactory, extensionRegistry: ExtensionDescriptionRegistry, workspaceProvider: ExtHostWorkspaceProvider, configProvider: ExtHostConfigProvider): Promise<void> {
return extensionService.getExtensionPathIndex().then(trie => defineAPI(apiFactory, trie, extensionRegistry, workspaceProvider, configProvider));
}
function defineAPI(factory: IExtensionApiFactory, extensionPaths: TernarySearchTree<IExtensionDescription>, extensionRegistry: ExtensionDescriptionRegistry, configProvider: ExtHostConfigProvider): void {
function defineAPI(factory: IExtensionApiFactory, extensionPaths: TernarySearchTree<IExtensionDescription>, extensionRegistry: ExtensionDescriptionRegistry, workspaceProvider: ExtHostWorkspaceProvider, configProvider: ExtHostConfigProvider): void {
// each extension is meant to get its own api implementation
const extApiImpl = new Map<string, typeof vscode>();
@@ -897,7 +900,7 @@ function defineAPI(factory: IExtensionApiFactory, extensionPaths: TernarySearchT
if (ext) {
let apiImpl = extApiImpl.get(ExtensionIdentifier.toKey(ext.identifier));
if (!apiImpl) {
apiImpl = factory(ext, extensionRegistry, configProvider);
apiImpl = factory(ext, extensionRegistry, workspaceProvider, configProvider);
extApiImpl.set(ExtensionIdentifier.toKey(ext.identifier), apiImpl);
}
return apiImpl;
@@ -908,7 +911,7 @@ function defineAPI(factory: IExtensionApiFactory, extensionPaths: TernarySearchT
let extensionPathsPretty = '';
extensionPaths.forEach((value, index) => extensionPathsPretty += `\t${index} -> ${value.identifier.value}\n`);
console.warn(`Could not identify extension for 'vscode' require call from ${parent.filename}. These are the extension path mappings: \n${extensionPathsPretty}`);
defaultApiImpl = factory(nullExtensionDescription, extensionRegistry, configProvider);
defaultApiImpl = factory(nullExtensionDescription, extensionRegistry, workspaceProvider, configProvider);
}
return defaultApiImpl;
};

View File

@@ -25,7 +25,7 @@ import { ResourceLabelFormatter } from 'vs/platform/label/common/label';
import { LogLevel } from 'vs/platform/log/common/log';
import { IMarkerData } from 'vs/platform/markers/common/markers';
import { IPickOptions, IQuickInputButton, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
import { IPatternInfo, IRawFileMatch2, IRawQuery, IRawTextQuery, ISearchCompleteStats } from 'vs/platform/search/common/search';
import { IPatternInfo, IRawFileMatch2, IRawQuery, IRawTextQuery, ISearchCompleteStats } from 'vs/workbench/services/search/common/search';
import { StatusbarAlignment as MainThreadStatusBarAlignment } from 'vs/platform/statusbar/common/statusbar';
import { ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
import { ThemeColor } from 'vs/platform/theme/common/themeService';
@@ -48,26 +48,30 @@ import { IRemoteConsoleLog } from 'vs/base/node/console';
export interface IEnvironment {
isExtensionDevelopmentDebug: boolean;
appRoot: URI;
appSettingsHome: URI;
extensionDevelopmentLocationURI: URI;
extensionTestsPath: string;
appRoot?: URI;
appSettingsHome?: URI;
extensionDevelopmentLocationURI?: URI;
extensionTestsPath?: string;
globalStorageHome: URI;
}
export interface IWorkspaceData {
export interface IStaticWorkspaceData {
id: string;
name: string;
folders: { uri: UriComponents, name: string, index: number }[];
configuration?: UriComponents;
}
export interface IWorkspaceData extends IStaticWorkspaceData {
folders: { uri: UriComponents, name: string, index: number }[];
}
export interface IInitData {
commit: string;
commit?: string;
parentPid: number;
environment: IEnvironment;
workspace: IWorkspaceData;
workspace?: IStaticWorkspaceData;
resolvedExtensions: ExtensionIdentifier[];
hostExtensions: ExtensionIdentifier[];
extensions: IExtensionDescription[];
telemetryInfo: ITelemetryInfo;
logLevel: LogLevel;
@@ -147,14 +151,14 @@ export interface MainThreadDialogSaveOptions {
}
export interface MainThreadDiaglogsShape extends IDisposable {
$showOpenDialog(options: MainThreadDialogOpenOptions): Promise<UriComponents[]>;
$showSaveDialog(options: MainThreadDialogSaveOptions): Promise<UriComponents>;
$showOpenDialog(options: MainThreadDialogOpenOptions): Promise<UriComponents[] | undefined>;
$showSaveDialog(options: MainThreadDialogSaveOptions): Promise<UriComponents | undefined>;
}
export interface MainThreadDecorationsShape extends IDisposable {
$registerDecorationProvider(handle: number, label: string): void;
$unregisterDecorationProvider(handle: number): void;
$onDidChange(handle: number, resources: UriComponents[]): void;
$onDidChange(handle: number, resources: UriComponents[] | null): void;
}
export interface MainThreadDocumentContentProvidersShape extends IDisposable {
@@ -294,7 +298,7 @@ export interface ISerializedSignatureHelpProviderMetadata {
export interface MainThreadLanguageFeaturesShape extends IDisposable {
$unregister(handle: number): void;
$registerDocumentSymbolProvider(handle: number, selector: ISerializedDocumentFilter[], label: string): void;
$registerCodeLensSupport(handle: number, selector: ISerializedDocumentFilter[], eventHandle: number): void;
$registerCodeLensSupport(handle: number, selector: ISerializedDocumentFilter[], eventHandle: number | undefined): void;
$emitCodeLensEvent(eventHandle: number, event?: any): void;
$registerDefinitionSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
$registerDeclarationSupport(handle: number, selector: ISerializedDocumentFilter[]): void;
@@ -329,17 +333,17 @@ export interface MainThreadMessageOptions {
}
export interface MainThreadMessageServiceShape extends IDisposable {
$showMessage(severity: Severity, message: string, options: MainThreadMessageOptions, commands: { title: string; isCloseAffordance: boolean; handle: number; }[]): Promise<number>;
$showMessage(severity: Severity, message: string, options: MainThreadMessageOptions, commands: { title: string; isCloseAffordance: boolean; handle: number; }[]): Promise<number | undefined>;
}
export interface MainThreadOutputServiceShape extends IDisposable {
$register(label: string, log: boolean, file?: UriComponents): Promise<string>;
$append(channelId: string, value: string): Promise<void>;
$update(channelId: string): Promise<void>;
$clear(channelId: string, till: number): Promise<void>;
$reveal(channelId: string, preserveFocus: boolean): Promise<void>;
$close(channelId: string): Promise<void>;
$dispose(channelId: string): Promise<void>;
$append(channelId: string, value: string): Promise<void> | undefined;
$update(channelId: string): Promise<void> | undefined;
$clear(channelId: string, till: number): Promise<void> | undefined;
$reveal(channelId: string, preserveFocus: boolean): Promise<void> | undefined;
$close(channelId: string): Promise<void> | undefined;
$dispose(channelId: string): Promise<void> | undefined;
}
export interface MainThreadProgressShape extends IDisposable {
@@ -440,7 +444,7 @@ export interface TransferInputBox extends BaseTransferQuickInput {
}
export interface MainThreadQuickOpenShape extends IDisposable {
$show(instance: number, options: IPickOptions<TransferQuickPickItems>, token: CancellationToken): Promise<number | number[]>;
$show(instance: number, options: IPickOptions<TransferQuickPickItems>, token: CancellationToken): Promise<number | number[] | undefined>;
$setItems(instance: number, items: TransferQuickPickItems[]): Promise<void>;
$setError(instance: number, error: Error): Promise<void>;
$input(options: vscode.InputBoxOptions, validateInput: boolean, token: CancellationToken): Promise<string>;
@@ -506,7 +510,7 @@ export interface ExtHostUrlsShape {
}
export interface MainThreadWorkspaceShape extends IDisposable {
$startFileSearch(includePattern: string, includeFolder: URI, excludePatternOrDisregardExcludes: string | false, maxResults: number, token: CancellationToken): Promise<UriComponents[]> | undefined;
$startFileSearch(includePattern: string | undefined, includeFolder: URI | undefined, excludePatternOrDisregardExcludes: string | false, maxResults: number, token: CancellationToken): Promise<UriComponents[] | undefined>;
$startTextSearch(query: IPatternInfo, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Promise<vscode.TextSearchComplete>;
$checkExists(includes: string[], token: CancellationToken): Promise<boolean>;
$saveAll(includeUntitled?: boolean): Promise<boolean>;
@@ -549,6 +553,7 @@ export interface MainThreadTaskShape extends IDisposable {
export interface MainThreadExtensionServiceShape extends IDisposable {
$localShowMessage(severity: Severity, msg: string): void;
$activateExtension(extensionId: ExtensionIdentifier, activationEvent: string): Promise<void>;
$onWillActivateExtension(extensionId: ExtensionIdentifier): void;
$onDidActivateExtension(extensionId: ExtensionIdentifier, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationEvent: string): void;
$onExtensionActivationFailed(extensionId: ExtensionIdentifier): void;
@@ -653,7 +658,7 @@ export interface ExtHostDiagnosticsShape {
}
export interface ExtHostDocumentContentProvidersShape {
$provideTextDocumentContent(handle: number, uri: UriComponents): Promise<string>;
$provideTextDocumentContent(handle: number, uri: UriComponents): Promise<string | null | undefined>;
}
export interface IModelAddedData {
@@ -721,6 +726,7 @@ export interface ExtHostTreeViewsShape {
}
export interface ExtHostWorkspaceShape {
$initializeWorkspace(workspace: IWorkspaceData | null): void;
$acceptWorkspaceData(workspace: IWorkspaceData | null): void;
$handleTextSearchResult(result: IRawFileMatch2, requestId: number): void;
}
@@ -752,7 +758,7 @@ export interface ExtHostExtensionServiceShape {
$resolveAuthority(remoteAuthority: string): Promise<ResolvedAuthority>;
$startExtensionHost(enabledExtensionIds: ExtensionIdentifier[]): Promise<void>;
$activateByEvent(activationEvent: string): Promise<void>;
$activate(extensionId: ExtensionIdentifier, activationEvent: string): Promise<void>;
$activate(extensionId: ExtensionIdentifier, activationEvent: string): Promise<boolean>;
$deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise<void>;
@@ -883,38 +889,42 @@ export interface CodeActionDto {
export type LinkDto = ObjectIdentifier & modes.ILink;
export type CodeLensDto = ObjectIdentifier & modes.ICodeLensSymbol;
export interface CodeLensDto extends ObjectIdentifier {
range: IRange;
id?: string;
command?: CommandDto;
}
export interface ExtHostLanguageFeaturesShape {
$provideDocumentSymbols(handle: number, resource: UriComponents, token: CancellationToken): Promise<modes.DocumentSymbol[]>;
$provideDocumentSymbols(handle: number, resource: UriComponents, token: CancellationToken): Promise<modes.DocumentSymbol[] | undefined>;
$provideCodeLenses(handle: number, resource: UriComponents, token: CancellationToken): Promise<CodeLensDto[]>;
$resolveCodeLens(handle: number, resource: UriComponents, symbol: CodeLensDto, token: CancellationToken): Promise<CodeLensDto>;
$provideDefinition(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<DefinitionLinkDto[]>;
$provideDeclaration(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<DefinitionLinkDto[]>;
$provideImplementation(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<DefinitionLinkDto[]>;
$provideTypeDefinition(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<DefinitionLinkDto[]>;
$provideHover(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.Hover>;
$provideDocumentHighlights(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.DocumentHighlight[]>;
$provideReferences(handle: number, resource: UriComponents, position: IPosition, context: modes.ReferenceContext, token: CancellationToken): Promise<LocationDto[]>;
$provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise<CodeActionDto[]>;
$provideDocumentFormattingEdits(handle: number, resource: UriComponents, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]>;
$provideDocumentRangeFormattingEdits(handle: number, resource: UriComponents, range: IRange, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]>;
$provideOnTypeFormattingEdits(handle: number, resource: UriComponents, position: IPosition, ch: string, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]>;
$provideHover(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.Hover | undefined>;
$provideDocumentHighlights(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.DocumentHighlight[] | undefined>;
$provideReferences(handle: number, resource: UriComponents, position: IPosition, context: modes.ReferenceContext, token: CancellationToken): Promise<LocationDto[] | undefined>;
$provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise<CodeActionDto[] | undefined>;
$provideDocumentFormattingEdits(handle: number, resource: UriComponents, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined>;
$provideDocumentRangeFormattingEdits(handle: number, resource: UriComponents, range: IRange, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined>;
$provideOnTypeFormattingEdits(handle: number, resource: UriComponents, position: IPosition, ch: string, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined>;
$provideWorkspaceSymbols(handle: number, search: string, token: CancellationToken): Promise<WorkspaceSymbolsDto>;
$resolveWorkspaceSymbol(handle: number, symbol: WorkspaceSymbolDto, token: CancellationToken): Promise<WorkspaceSymbolDto>;
$resolveWorkspaceSymbol(handle: number, symbol: WorkspaceSymbolDto, token: CancellationToken): Promise<WorkspaceSymbolDto | undefined>;
$releaseWorkspaceSymbols(handle: number, id: number): void;
$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string, token: CancellationToken): Promise<WorkspaceEditDto>;
$resolveRenameLocation(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.RenameLocation>;
$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string, token: CancellationToken): Promise<WorkspaceEditDto | undefined>;
$resolveRenameLocation(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.RenameLocation | undefined>;
$provideCompletionItems(handle: number, resource: UriComponents, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise<SuggestResultDto>;
$resolveCompletionItem(handle: number, resource: UriComponents, position: IPosition, suggestion: modes.CompletionItem, token: CancellationToken): Promise<modes.CompletionItem>;
$releaseCompletionItems(handle: number, id: number): void;
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise<modes.SignatureHelp>;
$provideDocumentLinks(handle: number, resource: UriComponents, token: CancellationToken): Promise<LinkDto[]>;
$resolveDocumentLink(handle: number, link: LinkDto, token: CancellationToken): Promise<LinkDto>;
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise<modes.SignatureHelp | undefined>;
$provideDocumentLinks(handle: number, resource: UriComponents, token: CancellationToken): Promise<LinkDto[] | undefined>;
$resolveDocumentLink(handle: number, link: LinkDto, token: CancellationToken): Promise<LinkDto | undefined>;
$provideDocumentColors(handle: number, resource: UriComponents, token: CancellationToken): Promise<IRawColorInfo[]>;
$provideColorPresentations(handle: number, resource: UriComponents, colorInfo: IRawColorInfo, token: CancellationToken): Promise<modes.IColorPresentation[]>;
$provideFoldingRanges(handle: number, resource: UriComponents, context: modes.FoldingContext, token: CancellationToken): Promise<modes.FoldingRange[]>;
$provideSelectionRanges(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.SelectionRange[]>;
$provideSelectionRanges(handle: number, resource: UriComponents, positions: IPosition[], token: CancellationToken): Promise<modes.SelectionRange[][]>;
}
export interface ExtHostQuickOpenShape {
@@ -933,7 +943,7 @@ export interface ShellLaunchConfigDto {
executable?: string;
args?: string[] | string;
cwd?: string | URI;
env?: { [key: string]: string };
env?: { [key: string]: string | null };
}
export interface ExtHostTerminalServiceShape {
@@ -954,7 +964,7 @@ export interface ExtHostTerminalServiceShape {
}
export interface ExtHostSCMShape {
$provideOriginalResource(sourceControlHandle: number, uri: UriComponents, token: CancellationToken): Promise<UriComponents>;
$provideOriginalResource(sourceControlHandle: number, uri: UriComponents, token: CancellationToken): Promise<UriComponents | null>;
$onInputBoxValueChange(sourceControlHandle: number, value: string): void;
$executeResourceCommand(sourceControlHandle: number, groupHandle: number, handle: number): Promise<void>;
$validateInput(sourceControlHandle: number, value: string, cursorPosition: number): Promise<[string, number] | undefined>;
@@ -1033,7 +1043,7 @@ export interface ExtHostDebugServiceShape {
$provideDebugAdapter(handle: number, session: IDebugSessionDto): Promise<IAdapterDescriptor>;
$acceptDebugSessionStarted(session: IDebugSessionDto): void;
$acceptDebugSessionTerminated(session: IDebugSessionDto): void;
$acceptDebugSessionActiveChanged(session: IDebugSessionDto): void;
$acceptDebugSessionActiveChanged(session: IDebugSessionDto | undefined): void;
$acceptDebugSessionCustomEvent(session: IDebugSessionDto, event: any): void;
$acceptBreakpointsDelta(delta: IBreakpointsDeltaDto): void;
}

View File

@@ -17,7 +17,7 @@ import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
import { CustomCodeAction } from 'vs/workbench/api/node/extHostLanguageFeatures';
import { ICommandsExecutor, PreviewHTMLAPICommand, OpenFolderAPICommand, DiffAPICommand, OpenAPICommand, RemoveFromRecentlyOpenedAPICommand, SetEditorLayoutAPICommand } from './apiCommands';
import { EditorGroupLayout } from 'vs/workbench/services/editor/common/editorGroupsService';
import { isFalsyOrEmpty, isNonEmptyArray } from 'vs/base/common/arrays';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
export class ExtHostApiCommands {
@@ -199,7 +199,7 @@ export class ExtHostApiCommands {
description: 'Execute selection range provider.',
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
{ name: 'position', description: 'Position in a text document', constraint: types.Position }
{ name: 'positions', description: 'Positions in a text document', constraint: a => Array.isArray(a) }
],
returns: 'A promise that resolves to an array of ranges.'
});
@@ -420,16 +420,15 @@ export class ExtHostApiCommands {
});
}
private _executeSelectionRangeProvider(resource: URI, position: types.Position): Promise<vscode.SelectionRange[]> {
private _executeSelectionRangeProvider(resource: URI, positions: types.Position[]): Promise<vscode.SelectionRange[][]> {
let pos = positions.map(typeConverters.Position.from);
const args = {
resource,
position: position && typeConverters.Position.from(position)
position: pos[0],
positions: pos
};
return this._commands.executeCommand<modes.SelectionRange[]>('_executeSelectionRangeProvider', args).then(result => {
if (isNonEmptyArray(result)) {
return result.map(typeConverters.SelectionRange.to);
}
return [];
return this._commands.executeCommand<modes.SelectionRange[][]>('_executeSelectionRangeProvider', args).then(result => {
return result.map(oneResult => oneResult.map(typeConverters.SelectionRange.to));
});
}

View File

@@ -138,7 +138,11 @@ export class ExtHostCommands implements ExtHostCommandsShape {
}
private _executeContributedCommand<T>(id: string, args: any[]): Promise<T> {
let { callback, thisArg, description } = this._commands.get(id);
const command = this._commands.get(id);
if (!command) {
throw new Error('Unknown command');
}
let { callback, thisArg, description } = command;
if (description) {
for (let i = 0; i < description.args.length; i++) {
try {
@@ -207,7 +211,7 @@ export class CommandsConverter {
this._commands.registerCommand(true, this._delegatingCommandId, this._executeConvertedCommand, this);
}
toInternal(command: vscode.Command): CommandDto {
toInternal(command: vscode.Command | undefined): CommandDto | undefined {
if (!command) {
return undefined;
@@ -237,7 +241,7 @@ export class CommandsConverter {
return result;
}
fromInternal(command: modes.Command): vscode.Command {
fromInternal(command: modes.Command | undefined): vscode.Command | undefined {
if (!command) {
return undefined;
@@ -258,7 +262,7 @@ export class CommandsConverter {
private _executeConvertedCommand<R>(...args: any[]): Promise<R> {
const actualCmd = this._heap.get<vscode.Command>(args[0]);
return this._commands.executeCommand(actualCmd.command, ...actualCmd.arguments);
return this._commands.executeCommand(actualCmd.command, ...(actualCmd.arguments || []));
}
}

View File

@@ -111,107 +111,68 @@ export class ExtHostComments implements ExtHostCommentsShape {
}
$editComment(handle: number, uri: UriComponents, comment: modes.Comment, text: string): Promise<void> {
const data = this._documents.getDocumentData(URI.revive(uri));
if (!data || !data.document) {
throw new Error('Unable to retrieve document from URI');
}
const document = this._documents.getDocument(URI.revive(uri));
const handlerData = this._documentProviders.get(handle);
return asPromise(() => {
return handlerData.provider.editComment(data.document, convertFromComment(comment), text, CancellationToken.None);
return handlerData.provider.editComment(document, convertFromComment(comment), text, CancellationToken.None);
});
}
$deleteComment(handle: number, uri: UriComponents, comment: modes.Comment): Promise<void> {
const data = this._documents.getDocumentData(URI.revive(uri));
if (!data || !data.document) {
throw new Error('Unable to retrieve document from URI');
}
const document = this._documents.getDocument(URI.revive(uri));
const handlerData = this._documentProviders.get(handle);
return asPromise(() => {
return handlerData.provider.deleteComment(data.document, convertFromComment(comment), CancellationToken.None);
return handlerData.provider.deleteComment(document, convertFromComment(comment), CancellationToken.None);
});
}
$startDraft(handle: number, uri: UriComponents): Promise<void> {
const data = this._documents.getDocumentData(URI.revive(uri));
if (!data || !data.document) {
throw new Error('Unable to retrieve document from URI');
}
const document = this._documents.getDocument(URI.revive(uri));
const handlerData = this._documentProviders.get(handle);
return asPromise(() => {
return handlerData.provider.startDraft(data.document, CancellationToken.None);
return handlerData.provider.startDraft(document, CancellationToken.None);
});
}
$deleteDraft(handle: number, uri: UriComponents): Promise<void> {
const data = this._documents.getDocumentData(URI.revive(uri));
if (!data || !data.document) {
throw new Error('Unable to retrieve document from URI');
}
const document = this._documents.getDocument(URI.revive(uri));
const handlerData = this._documentProviders.get(handle);
return asPromise(() => {
return handlerData.provider.deleteDraft(data.document, CancellationToken.None);
return handlerData.provider.deleteDraft(document, CancellationToken.None);
});
}
$finishDraft(handle: number, uri: UriComponents): Promise<void> {
const data = this._documents.getDocumentData(URI.revive(uri));
if (!data || !data.document) {
throw new Error('Unable to retrieve document from URI');
}
const document = this._documents.getDocument(URI.revive(uri));
const handlerData = this._documentProviders.get(handle);
return asPromise(() => {
return handlerData.provider.finishDraft(data.document, CancellationToken.None);
return handlerData.provider.finishDraft(document, CancellationToken.None);
});
}
$addReaction(handle: number, uri: UriComponents, comment: modes.Comment, reaction: modes.CommentReaction): Promise<void> {
const data = this._documents.getDocumentData(URI.revive(uri));
if (!data || !data.document) {
throw new Error('Unable to retrieve document from URI');
}
const document = this._documents.getDocument(URI.revive(uri));
const handlerData = this._documentProviders.get(handle);
return asPromise(() => {
return handlerData.provider.addReaction(data.document, convertFromComment(comment), reaction);
return handlerData.provider.addReaction(document, convertFromComment(comment), reaction);
});
}
$deleteReaction(handle: number, uri: UriComponents, comment: modes.Comment, reaction: modes.CommentReaction): Promise<void> {
const data = this._documents.getDocumentData(URI.revive(uri));
if (!data || !data.document) {
throw new Error('Unable to retrieve document from URI');
}
const document = this._documents.getDocument(URI.revive(uri));
const handlerData = this._documentProviders.get(handle);
return asPromise(() => {
return handlerData.provider.deleteReaction(data.document, convertFromComment(comment), reaction);
return handlerData.provider.deleteReaction(document, convertFromComment(comment), reaction);
});
}
$provideDocumentComments(handle: number, uri: UriComponents): Promise<modes.CommentInfo> {
const data = this._documents.getDocumentData(URI.revive(uri));
if (!data || !data.document) {
return Promise.resolve(null);
}
const document = this._documents.getDocument(URI.revive(uri));
const handlerData = this._documentProviders.get(handle);
return asPromise(() => {
return handlerData.provider.provideDocumentComments(data.document, CancellationToken.None);
return handlerData.provider.provideDocumentComments(document, CancellationToken.None);
}).then(commentInfo => commentInfo ? convertCommentInfo(handle, handlerData.extensionId, handlerData.provider, commentInfo, this._commandsConverter) : null);
}
@@ -297,6 +258,9 @@ function convertToComment(provider: vscode.DocumentCommentProvider | vscode.Work
const canEdit = !!(provider as vscode.DocumentCommentProvider).editComment && vscodeComment.canEdit;
const canDelete = !!(provider as vscode.DocumentCommentProvider).deleteComment && vscodeComment.canDelete;
const iconPath = vscodeComment.userIconPath ? vscodeComment.userIconPath.toString() : vscodeComment.gravatar;
const providerCanDeleteReaction = !!(provider as vscode.DocumentCommentProvider).deleteReaction;
const providerCanAddReaction = !!(provider as vscode.DocumentCommentProvider).addReaction;
return {
commentId: vscodeComment.commentId,
body: extHostTypeConverter.MarkdownString.from(vscodeComment.body),
@@ -306,6 +270,12 @@ function convertToComment(provider: vscode.DocumentCommentProvider | vscode.Work
canDelete: canDelete,
command: vscodeComment.command ? commandsConverter.toInternal(vscodeComment.command) : null,
isDraft: vscodeComment.isDraft,
commentReactions: vscodeComment.commentReactions
commentReactions: vscodeComment.commentReactions.map(reaction => {
return {
label: reaction.label,
hasReacted: reaction.hasReacted,
canEdit: (reaction.hasReacted && providerCanDeleteReaction) || (!reaction.hasReacted && providerCanAddReaction)
};
})
};
}

View File

@@ -7,7 +7,7 @@ import { mixin, deepClone } from 'vs/base/common/objects';
import { URI } from 'vs/base/common/uri';
import { Event, Emitter } from 'vs/base/common/event';
import * as vscode from 'vscode';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { ExtHostWorkspace, ExtHostWorkspaceProvider } from 'vs/workbench/api/node/extHostWorkspace';
import { ExtHostConfigurationShape, MainThreadConfigurationShape, IWorkspaceConfigurationChangeEventData, IConfigurationInitData } from './extHost.protocol';
import { ConfigurationTarget as ExtHostConfigurationTarget } from './extHostTypes';
import { IConfigurationData, ConfigurationTarget, IConfigurationModel } from 'vs/platform/configuration/common/configuration';
@@ -57,8 +57,10 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
}
$initializeConfiguration(data: IConfigurationInitData): void {
this._actual = new ExtHostConfigProvider(this._proxy, this._extHostWorkspace, data);
this._barrier.open();
this._extHostWorkspace.getWorkspaceProvider().then(workspaceProvider => {
this._actual = new ExtHostConfigProvider(this._proxy, workspaceProvider, data);
this._barrier.open();
});
}
$acceptConfigurationChanged(data: IConfigurationInitData, eventData: IWorkspaceConfigurationChangeEventData): void {
@@ -70,11 +72,11 @@ export class ExtHostConfigProvider {
private readonly _onDidChangeConfiguration = new Emitter<vscode.ConfigurationChangeEvent>();
private readonly _proxy: MainThreadConfigurationShape;
private readonly _extHostWorkspace: ExtHostWorkspace;
private readonly _extHostWorkspace: ExtHostWorkspaceProvider;
private _configurationScopes: { [key: string]: ConfigurationScope };
private _configuration: Configuration;
constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspace, data: IConfigurationInitData) {
constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspaceProvider, data: IConfigurationInitData) {
this._proxy = proxy;
this._extHostWorkspace = extHostWorkspace;
this._configuration = ExtHostConfigProvider.parse(data);

View File

@@ -16,15 +16,15 @@ import {
import * as vscode from 'vscode';
import { Disposable, Position, Location, SourceBreakpoint, FunctionBreakpoint, DebugAdapterServer, DebugAdapterExecutable } from 'vs/workbench/api/node/extHostTypes';
import { ExecutableDebugAdapter, SocketDebugAdapter, AbstractDebugAdapter } from 'vs/workbench/contrib/debug/node/debugAdapter';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { ExtHostWorkspace, ExtHostWorkspaceProvider } from 'vs/workbench/api/node/extHostWorkspace';
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumentsAndEditors';
import { ITerminalSettings, IDebuggerContribution, IConfig, IDebugAdapter, IDebugAdapterServer, IDebugAdapterExecutable, IAdapterDescriptor } from 'vs/workbench/contrib/debug/common/debug';
import { getTerminalLauncher, hasChildProcesses, prepareCommand } from 'vs/workbench/contrib/debug/node/terminals';
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { AbstractVariableResolverService } from 'vs/workbench/services/configurationResolver/node/variableResolver';
import { AbstractVariableResolverService } from 'vs/workbench/services/configurationResolver/common/variableResolver';
import { ExtHostConfiguration, ExtHostConfigProvider } from './extHostConfiguration';
import { convertToVSCPaths, convertToDAPaths } from 'vs/workbench/contrib/debug/common/debugUtils';
import { convertToVSCPaths, convertToDAPaths, isDebuggerMainContribution } from 'vs/workbench/contrib/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';
@@ -128,8 +128,7 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
const debuggers = <IDebuggerContribution[]>ed.contributes['debuggers'];
if (debuggers && debuggers.length > 0) {
for (const dbg of debuggers) {
// only debugger contributions with a label, program, or runtime attribute are considered a "defining" debugger contribution
if (dbg.type && (dbg.label || dbg.program || dbg.runtime)) {
if (isDebuggerMainContribution(dbg)) {
debugTypes.push(dbg.type);
if (dbg.adapterExecutableCommand) {
this._aexCommands.set(dbg.type, dbg.adapterExecutableCommand);
@@ -360,12 +359,12 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
}
public async $substituteVariables(folderUri: UriComponents | undefined, config: IConfig): Promise<IConfig> {
const configProvider = await this._configurationService.getConfigProvider();
const [workspaceProvider, configProvider] = await Promise.all([this._workspaceService.getWorkspaceProvider(), this._configurationService.getConfigProvider()]);
if (!this._variableResolver) {
this._variableResolver = new ExtHostVariableResolverService(this._workspaceService, this._editorsService, configProvider);
this._variableResolver = new ExtHostVariableResolverService(workspaceProvider, this._editorsService, configProvider);
}
let ws: IWorkspaceFolder;
const folder = this.getFolder(folderUri);
const folder = this.getFolder(folderUri, workspaceProvider);
if (folder) {
ws = {
uri: folder.uri,
@@ -379,10 +378,11 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
return this._variableResolver.resolveAny(ws, config);
}
public $startDASession(debugAdapterHandle: number, sessionDto: IDebugSessionDto): Promise<void> {
public async $startDASession(debugAdapterHandle: number, sessionDto: IDebugSessionDto): Promise<void> {
const workspaceProvider = await this._workspaceService.getWorkspaceProvider();
const mythis = this;
const session = this.getSession(sessionDto);
const session = this.getSession(sessionDto, workspaceProvider);
return this.getAdapterDescriptor(this.getAdapterFactoryByType(session.type), session).then(x => {
const adapter = this.convertToDto(x);
@@ -546,7 +546,8 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
this.fireBreakpointChanges(a, r, c);
}
public $provideDebugConfigurations(configProviderHandle: number, folderUri: UriComponents | undefined): Promise<vscode.DebugConfiguration[]> {
public async $provideDebugConfigurations(configProviderHandle: number, folderUri: UriComponents | undefined): Promise<vscode.DebugConfiguration[]> {
const workspaceProvider = await this._workspaceService.getWorkspaceProvider();
let provider = this.getConfigProviderByHandle(configProviderHandle);
if (!provider) {
return Promise.reject(new Error('no handler found'));
@@ -554,10 +555,11 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
if (!provider.provideDebugConfigurations) {
return Promise.reject(new Error('handler has no method provideDebugConfigurations'));
}
return asPromise(() => provider.provideDebugConfigurations(this.getFolder(folderUri), CancellationToken.None));
return asPromise(() => provider.provideDebugConfigurations(this.getFolder(folderUri, workspaceProvider), CancellationToken.None));
}
public $resolveDebugConfiguration(configProviderHandle: number, folderUri: UriComponents | undefined, debugConfiguration: vscode.DebugConfiguration): Promise<vscode.DebugConfiguration> {
public async $resolveDebugConfiguration(configProviderHandle: number, folderUri: UriComponents | undefined, debugConfiguration: vscode.DebugConfiguration): Promise<vscode.DebugConfiguration> {
const workspaceProvider = await this._workspaceService.getWorkspaceProvider();
let provider = this.getConfigProviderByHandle(configProviderHandle);
if (!provider) {
return Promise.reject(new Error('no handler found'));
@@ -565,11 +567,12 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
if (!provider.resolveDebugConfiguration) {
return Promise.reject(new Error('handler has no method resolveDebugConfiguration'));
}
return asPromise(() => provider.resolveDebugConfiguration(this.getFolder(folderUri), debugConfiguration, CancellationToken.None));
return asPromise(() => provider.resolveDebugConfiguration(this.getFolder(folderUri, workspaceProvider), debugConfiguration, CancellationToken.None));
}
// TODO@AW legacy
public $legacyDebugAdapterExecutable(configProviderHandle: number, folderUri: UriComponents | undefined): Promise<IAdapterDescriptor> {
public async $legacyDebugAdapterExecutable(configProviderHandle: number, folderUri: UriComponents | undefined): Promise<IAdapterDescriptor> {
const workspaceProvider = await this._workspaceService.getWorkspaceProvider();
let provider = this.getConfigProviderByHandle(configProviderHandle);
if (!provider) {
return Promise.reject(new Error('no handler found'));
@@ -577,41 +580,42 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
if (!provider.debugAdapterExecutable) {
return Promise.reject(new Error('handler has no method debugAdapterExecutable'));
}
return asPromise(() => provider.debugAdapterExecutable(this.getFolder(folderUri), CancellationToken.None)).then(x => this.convertToDto(x));
return asPromise(() => provider.debugAdapterExecutable(this.getFolder(folderUri, workspaceProvider), CancellationToken.None)).then(x => this.convertToDto(x));
}
public $provideDebugAdapter(adapterProviderHandle: number, sessionDto: IDebugSessionDto): Promise<IAdapterDescriptor> {
public async $provideDebugAdapter(adapterProviderHandle: number, sessionDto: IDebugSessionDto): Promise<IAdapterDescriptor> {
const workspaceProvider = await this._workspaceService.getWorkspaceProvider();
let adapterProvider = this.getAdapterProviderByHandle(adapterProviderHandle);
if (!adapterProvider) {
return Promise.reject(new Error('no handler found'));
}
return this.getAdapterDescriptor(adapterProvider, this.getSession(sessionDto)).then(x => this.convertToDto(x));
return this.getAdapterDescriptor(adapterProvider, this.getSession(sessionDto, workspaceProvider)).then(x => this.convertToDto(x));
}
public $acceptDebugSessionStarted(sessionDto: IDebugSessionDto): void {
this._onDidStartDebugSession.fire(this.getSession(sessionDto));
public async $acceptDebugSessionStarted(sessionDto: IDebugSessionDto): Promise<void> {
const workspaceProvider = await this._workspaceService.getWorkspaceProvider();
this._onDidStartDebugSession.fire(this.getSession(sessionDto, workspaceProvider));
}
public $acceptDebugSessionTerminated(sessionDto: IDebugSessionDto): void {
const session = this.getSession(sessionDto);
public async $acceptDebugSessionTerminated(sessionDto: IDebugSessionDto): Promise<void> {
const workspaceProvider = await this._workspaceService.getWorkspaceProvider();
const session = this.getSession(sessionDto, workspaceProvider);
if (session) {
this._onDidTerminateDebugSession.fire(session);
this._debugSessions.delete(session.id);
}
}
public $acceptDebugSessionActiveChanged(sessionDto: IDebugSessionDto): void {
this._activeDebugSession = sessionDto ? this.getSession(sessionDto) : undefined;
public async $acceptDebugSessionActiveChanged(sessionDto: IDebugSessionDto | undefined): Promise<void> {
const workspaceProvider = await this._workspaceService.getWorkspaceProvider();
this._activeDebugSession = sessionDto ? this.getSession(sessionDto, workspaceProvider) : undefined;
this._onDidChangeActiveDebugSession.fire(this._activeDebugSession);
}
public $acceptDebugSessionCustomEvent(sessionDto: IDebugSessionDto, event: any): void {
public async $acceptDebugSessionCustomEvent(sessionDto: IDebugSessionDto, event: any): Promise<void> {
const workspaceProvider = await this._workspaceService.getWorkspaceProvider();
const ee: vscode.DebugSessionCustomEvent = {
session: this.getSession(sessionDto),
session: this.getSession(sessionDto, workspaceProvider),
event: event.event,
body: event.body
};
@@ -776,12 +780,12 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
}
}
private getSession(dto: IDebugSessionDto): ExtHostDebugSession {
private getSession(dto: IDebugSessionDto, workspaceProvider: ExtHostWorkspaceProvider): ExtHostDebugSession {
if (dto) {
if (typeof dto === 'string') {
return this._debugSessions.get(dto);
} else {
const debugSession = new ExtHostDebugSession(this._debugServiceProxy, dto.id, dto.type, dto.name, this.getFolder(dto.folderUri), dto.configuration);
const debugSession = new ExtHostDebugSession(this._debugServiceProxy, dto.id, dto.type, dto.name, this.getFolder(dto.folderUri, workspaceProvider), dto.configuration);
this._debugSessions.set(debugSession.id, debugSession);
return debugSession;
}
@@ -789,10 +793,10 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
return undefined;
}
private getFolder(_folderUri: UriComponents | undefined): vscode.WorkspaceFolder | undefined {
private getFolder(_folderUri: UriComponents | undefined, workspaceProvider: ExtHostWorkspaceProvider): vscode.WorkspaceFolder | undefined {
if (_folderUri) {
const folderURI = URI.revive(_folderUri);
return this._workspaceService.resolveWorkspaceFolder(folderURI);
return workspaceProvider.resolveWorkspaceFolder(folderURI);
}
return undefined;
}
@@ -853,7 +857,7 @@ export class ExtHostDebugConsole implements vscode.DebugConsole {
export class ExtHostVariableResolverService extends AbstractVariableResolverService {
constructor(workspaceService: ExtHostWorkspace, editorService: ExtHostDocumentsAndEditors, configurationService: ExtHostConfigProvider) {
constructor(workspaceService: ExtHostWorkspaceProvider, editorService: ExtHostDocumentsAndEditors, configurationService: ExtHostConfigProvider) {
super({
getFolderUri: (folderName: string): URI => {
const folders = workspaceService.getWorkspaceFolders();

View File

@@ -46,16 +46,20 @@ export class ExtHostDecorations implements ExtHostDecorationsShape {
const result: DecorationReply = Object.create(null);
return Promise.all(requests.map(request => {
const { handle, uri, id } = request;
if (!this._provider.has(handle)) {
const entry = this._provider.get(handle);
if (!entry) {
// might have been unregistered in the meantime
return undefined;
}
const { provider, extensionId } = this._provider.get(handle);
const { provider, extensionId } = entry;
return Promise.resolve(provider.provideDecoration(URI.revive(uri), token)).then(data => {
if (data && data.letter && data.letter.length !== 1) {
console.warn(`INVALID decoration from extension '${extensionId.value}'. The 'letter' must be set and be one character, not '${data.letter}'.`);
}
result[id] = data && <DecorationData>[data.priority, data.bubble, data.title, data.letter, data.color, data.source];
if (data) {
result[id] = <DecorationData>[data.priority, data.bubble, data.title, data.letter, data.color, data.source];
}
}, err => {
console.error(err);
});

View File

@@ -60,7 +60,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
// the actual implementation for #set
this._checkDisposed();
let toSync: vscode.Uri[];
let toSync: vscode.Uri[] = [];
let hasChanged = true;
if (first instanceof URI) {
@@ -81,7 +81,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
} else if (Array.isArray(first)) {
// update many rows
toSync = [];
let lastUri: vscode.Uri;
let lastUri: vscode.Uri | undefined;
// ensure stable-sort
mergeSort(first, DiagnosticCollection._compareIndexedTuplesByUri);
@@ -255,7 +255,7 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
this._proxy = mainContext.getProxy(MainContext.MainThreadDiagnostics);
}
createDiagnosticCollection(name: string): vscode.DiagnosticCollection {
createDiagnosticCollection(name?: string): vscode.DiagnosticCollection {
let { _collections, _proxy, _onDidChangeDiagnostics } = this;
let owner: string;
if (!name) {
@@ -272,7 +272,7 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
const result = new class extends DiagnosticCollection {
constructor() {
super(name, owner, ExtHostDiagnostics._maxDiagnosticsPerFile, _proxy, _onDidChangeDiagnostics);
super(name!, owner, ExtHostDiagnostics._maxDiagnosticsPerFile, _proxy, _onDidChangeDiagnostics);
_collections.set(owner, this);
}
dispose() {
@@ -286,6 +286,7 @@ export class ExtHostDiagnostics implements ExtHostDiagnosticsShape {
getDiagnostics(resource: vscode.Uri): vscode.Diagnostic[];
getDiagnostics(): [vscode.Uri, vscode.Diagnostic[]][];
getDiagnostics(resource?: vscode.Uri): vscode.Diagnostic[] | [vscode.Uri, vscode.Diagnostic[]][];
getDiagnostics(resource?: vscode.Uri): vscode.Diagnostic[] | [vscode.Uri, vscode.Diagnostic[]][] {
if (resource) {
return this._getDiagnostics(resource);

View File

@@ -15,15 +15,15 @@ export class ExtHostDialogs {
this._proxy = mainContext.getProxy(MainContext.MainThreadDialogs);
}
showOpenDialog(options: vscode.OpenDialogOptions): Promise<URI[]> {
showOpenDialog(options: vscode.OpenDialogOptions): Promise<URI[] | undefined> {
return this._proxy.$showOpenDialog(options).then(filepaths => {
return filepaths && filepaths.map(URI.revive);
return filepaths ? filepaths.map(URI.revive) : undefined;
});
}
showSaveDialog(options: vscode.SaveDialogOptions): Promise<URI> {
showSaveDialog(options: vscode.SaveDialogOptions): Promise<URI | undefined> {
return this._proxy.$showSaveDialog(options).then(filepath => {
return filepath && URI.revive(filepath);
return filepath ? URI.revive(filepath) : undefined;
});
}
}

View File

@@ -45,7 +45,7 @@ export class ExtHostDocumentContentProvider implements ExtHostDocumentContentPro
this._documentContentProviders.set(handle, provider);
this._proxy.$registerTextContentProvider(handle, scheme);
let subscription: IDisposable;
let subscription: IDisposable | undefined;
if (typeof provider.onDidChange === 'function') {
subscription = provider.onDidChange(uri => {
if (uri.scheme !== scheme) {
@@ -54,6 +54,9 @@ export class ExtHostDocumentContentProvider implements ExtHostDocumentContentPro
}
if (this._documentsAndEditors.getDocument(uri.toString())) {
this.$provideTextDocumentContent(handle, uri).then(value => {
if (!value) {
return;
}
const document = this._documentsAndEditors.getDocument(uri.toString());
if (!document) {
@@ -84,7 +87,7 @@ export class ExtHostDocumentContentProvider implements ExtHostDocumentContentPro
});
}
$provideTextDocumentContent(handle: number, uri: UriComponents): Promise<string> {
$provideTextDocumentContent(handle: number, uri: UriComponents): Promise<string | null | undefined> {
const provider = this._documentContentProviders.get(handle);
if (!provider) {
return Promise.reject(new Error(`unsupported uri-scheme: ${uri.scheme}`));

View File

@@ -14,10 +14,10 @@ import { EndOfLine, Position, Range } from 'vs/workbench/api/node/extHostTypes';
import * as vscode from 'vscode';
const _modeId2WordDefinition = new Map<string, RegExp>();
export function setWordDefinitionFor(modeId: string, wordDefinition: RegExp): void {
export function setWordDefinitionFor(modeId: string, wordDefinition: RegExp | undefined): void {
_modeId2WordDefinition.set(modeId, wordDefinition);
}
export function getWordDefinitionFor(modeId: string): RegExp {
export function getWordDefinitionFor(modeId: string): RegExp | undefined {
return _modeId2WordDefinition.get(modeId);
}
@@ -131,14 +131,14 @@ export class ExtHostDocumentData extends MirrorTextModel {
private _lineAt(lineOrPosition: number | vscode.Position): vscode.TextLine {
let line: number;
let line: number | undefined;
if (lineOrPosition instanceof Position) {
line = lineOrPosition.line;
} else if (typeof lineOrPosition === 'number') {
line = lineOrPosition;
}
if (line < 0 || line >= this._lines.length) {
if (typeof line !== 'number' || line < 0 || line >= this._lines.length) {
throw new Error('Illegal value for `line`');
}
@@ -146,7 +146,7 @@ export class ExtHostDocumentData extends MirrorTextModel {
if (!result || result.lineNumber !== line || result.text !== this._lines[line]) {
const text = this._lines[line];
const firstNonWhitespaceCharacterIndex = /^(\s*)/.exec(text)[1].length;
const firstNonWhitespaceCharacterIndex = /^(\s*)/.exec(text)![1].length;
const range = new Range(line, 0, line, text.length);
const rangeIncludingLineBreak = line < this._lines.length - 1
? new Range(line, 0, line + 1, 0)
@@ -170,7 +170,7 @@ export class ExtHostDocumentData extends MirrorTextModel {
private _offsetAt(position: vscode.Position): number {
position = this._validatePosition(position);
this._ensureLineStarts();
return this._lineStarts.getAccumulatedValue(position.line - 1) + position.character;
return this._lineStarts!.getAccumulatedValue(position.line - 1) + position.character;
}
private _positionAt(offset: number): vscode.Position {
@@ -178,7 +178,7 @@ export class ExtHostDocumentData extends MirrorTextModel {
offset = Math.max(0, offset);
this._ensureLineStarts();
let out = this._lineStarts.getIndexOf(offset);
let out = this._lineStarts!.getIndexOf(offset);
let lineLength = this._lines[out.index].length;
@@ -238,7 +238,7 @@ export class ExtHostDocumentData extends MirrorTextModel {
return new Position(line, character);
}
private _getWordRangeAtPosition(_position: vscode.Position, regexp?: RegExp): vscode.Range {
private _getWordRangeAtPosition(_position: vscode.Position, regexp?: RegExp): vscode.Range | undefined {
let position = this._validatePosition(_position);
if (!regexp) {

View File

@@ -72,7 +72,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
private _deliverEventAsyncAndBlameBadListeners([listener, thisArg, extension]: Listener, stubEvent: vscode.TextDocumentWillSaveEvent): Promise<any> {
const errors = this._badListeners.get(listener);
if (errors > this._thresholds.errors) {
if (typeof errors === 'number' && errors > this._thresholds.errors) {
// bad listener - ignore
return Promise.resolve(false);
}
@@ -90,7 +90,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
const errors = this._badListeners.get(listener);
this._badListeners.set(listener, !errors ? 1 : errors + 1);
if (errors > this._thresholds.errors) {
if (typeof errors === 'number' && errors > this._thresholds.errors) {
this._logService.info(`onWillSaveTextDocument-listener from extension '${extension.identifier.value}' will now be IGNORED because of timeouts and/or errors`);
}
}

View File

@@ -56,7 +56,7 @@ export class ExtHostDocuments implements ExtHostDocumentsShape {
return this._documentsAndEditors.allDocuments();
}
public getDocumentData(resource: vscode.Uri): ExtHostDocumentData {
public getDocumentData(resource: vscode.Uri): ExtHostDocumentData | undefined {
if (!resource) {
return undefined;
}
@@ -67,6 +67,14 @@ export class ExtHostDocuments implements ExtHostDocumentsShape {
return undefined;
}
public getDocument(resource: vscode.Uri): vscode.TextDocument {
const data = this.getDocumentData(resource);
if (!data || !data.document) {
throw new Error('Unable to retrieve document from URI');
}
return data.document;
}
public ensureDocumentData(uri: URI): Promise<ExtHostDocumentData> {
let cached = this._documentsAndEditors.getDocument(uri.toString());
@@ -143,7 +151,7 @@ export class ExtHostDocuments implements ExtHostDocumentsShape {
});
}
public setWordDefinitionFor(modeId: string, wordDefinition: RegExp): void {
public setWordDefinitionFor(modeId: string, wordDefinition: RegExp | undefined): void {
setWordDefinitionFor(modeId, wordDefinition);
}
}

View File

@@ -52,7 +52,9 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
const id = uri.toString();
const data = this._documents.get(id);
this._documents.delete(id);
removedDocuments.push(data);
if (data) {
removedDocuments.push(data);
}
}
}
@@ -79,7 +81,9 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
for (const id of delta.removedEditors) {
const editor = this._editors.get(id);
this._editors.delete(id);
removedEditors.push(editor);
if (editor) {
removedEditors.push(editor);
}
}
}
@@ -97,7 +101,7 @@ export class ExtHostDocumentsAndEditors implements ExtHostDocumentsAndEditorsSha
data.selections.map(typeConverters.Selection.to),
data.options,
data.visibleRanges.map(typeConverters.Range.to),
typeConverters.ViewColumn.to(data.editorPosition)
typeof data.editorPosition === 'number' ? typeConverters.ViewColumn.to(data.editorPosition) : undefined
);
this._editors.set(data.id, editor);
}

View File

@@ -6,7 +6,6 @@
import * as nls from 'vs/nls';
import { IDisposable } from 'vs/base/common/lifecycle';
import Severity from 'vs/base/common/severity';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
@@ -161,6 +160,12 @@ export class EmptyExtension extends ActivatedExtension {
}
}
export class HostExtension extends ActivatedExtension {
constructor() {
super(false, null, ExtensionActivationTimes.NONE, { activate: undefined, deactivate: undefined }, undefined, []);
}
}
export class FailedExtension extends ActivatedExtension {
constructor(activationError: Error) {
super(true, activationError, ExtensionActivationTimes.NONE, { activate: undefined, deactivate: undefined }, undefined, []);
@@ -170,7 +175,7 @@ export class FailedExtension extends ActivatedExtension {
export interface IExtensionsActivatorHost {
showMessage(severity: Severity, message: string): void;
actualActivateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise<ActivatedExtension>;
actualActivateExtension(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<ActivatedExtension>;
}
export class ExtensionActivatedByEvent {
@@ -192,6 +197,7 @@ export class ExtensionsActivator {
private readonly _registry: ExtensionDescriptionRegistry;
private readonly _resolvedExtensionsSet: Set<string>;
private readonly _hostExtensionsMap: Map<string, ExtensionIdentifier>;
private readonly _host: IExtensionsActivatorHost;
private readonly _activatingExtensions: Map<string, Promise<void>>;
private readonly _activatedExtensions: Map<string, ActivatedExtension>;
@@ -200,10 +206,12 @@ export class ExtensionsActivator {
*/
private readonly _alreadyActivatedEvents: { [activationEvent: string]: boolean; };
constructor(registry: ExtensionDescriptionRegistry, resolvedExtensions: ExtensionIdentifier[], host: IExtensionsActivatorHost) {
constructor(registry: ExtensionDescriptionRegistry, resolvedExtensions: ExtensionIdentifier[], hostExtensions: ExtensionIdentifier[], host: IExtensionsActivatorHost) {
this._registry = registry;
this._resolvedExtensionsSet = new Set<string>();
resolvedExtensions.forEach((extensionId) => this._resolvedExtensionsSet.add(ExtensionIdentifier.toKey(extensionId)));
this._hostExtensionsMap = new Map<string, ExtensionIdentifier>();
hostExtensions.forEach((extensionId) => this._hostExtensionsMap.set(ExtensionIdentifier.toKey(extensionId), extensionId));
this._host = host;
this._activatingExtensions = new Map<string, Promise<void>>();
this._activatedExtensions = new Map<string, ActivatedExtension>();
@@ -231,7 +239,7 @@ export class ExtensionsActivator {
return NO_OP_VOID_PROMISE;
}
let activateExtensions = this._registry.getExtensionDescriptionsForActivationEvent(activationEvent);
return this._activateExtensions(activateExtensions, reason, 0).then(() => {
return this._activateExtensions(activateExtensions.map(e => e.identifier), reason).then(() => {
this._alreadyActivatedEvents[activationEvent] = true;
});
}
@@ -242,14 +250,20 @@ export class ExtensionsActivator {
throw new Error('Extension `' + extensionId + '` is not known');
}
return this._activateExtensions([desc], reason, 0);
return this._activateExtensions([desc.identifier], reason);
}
/**
* Handle semantics related to dependencies for `currentExtension`.
* semantics: `redExtensions` must wait for `greenExtensions`.
*/
private _handleActivateRequest(currentExtension: IExtensionDescription, greenExtensions: { [id: string]: IExtensionDescription; }, redExtensions: IExtensionDescription[]): void {
private _handleActivateRequest(currentExtensionId: ExtensionIdentifier, greenExtensions: { [id: string]: ExtensionIdentifier; }, redExtensions: ExtensionIdentifier[]): void {
if (this._hostExtensionsMap.has(ExtensionIdentifier.toKey(currentExtensionId))) {
greenExtensions[ExtensionIdentifier.toKey(currentExtensionId)] = currentExtensionId;
return;
}
const currentExtension = this._registry.getExtensionDescription(currentExtensionId)!;
let depIds = (typeof currentExtension.extensionDependencies === 'undefined' ? [] : currentExtension.extensionDependencies);
let currentExtensionGetsGreenLight = true;
@@ -261,72 +275,71 @@ export class ExtensionsActivator {
continue;
}
const depDesc = this._registry.getExtensionDescription(depId);
const dep = this._activatedExtensions.get(ExtensionIdentifier.toKey(depId));
if (dep && !dep.activationFailed) {
// the dependency is already activated OK
continue;
}
if (!depDesc) {
// Error condition 1: unknown dependency
this._host.showMessage(Severity.Error, nls.localize('unknownDep', "Cannot activate extension '{0}' because it depends on extension '{1}', which is not installed or disabled. Please install or enable '{1}' and reload the window.", currentExtension.displayName || currentExtension.identifier.value, depId));
const error = new Error(`Unknown dependency '${depId}'`);
if (dep && dep.activationFailed) {
// Error condition 2: a dependency has already failed activation
this._host.showMessage(Severity.Error, nls.localize('failedDep1', "Cannot activate extension '{0}' because it depends on extension '{1}', which failed to activate.", currentExtension.displayName || currentExtension.identifier.value, depId));
const error = new Error(`Dependency ${depId} failed to activate`);
(<any>error).detail = dep.activationFailedError;
this._activatedExtensions.set(ExtensionIdentifier.toKey(currentExtension.identifier), new FailedExtension(error));
return;
}
const dep = this._activatedExtensions.get(ExtensionIdentifier.toKey(depId));
if (dep) {
if (dep.activationFailed) {
// Error condition 2: a dependency has already failed activation
this._host.showMessage(Severity.Error, nls.localize('failedDep1', "Cannot activate extension '{0}' because it depends on extension '{1}', which failed to activate.", currentExtension.displayName || currentExtension.identifier.value, depId));
const error = new Error(`Dependency ${depId} failed to activate`);
(<any>error).detail = dep.activationFailedError;
this._activatedExtensions.set(ExtensionIdentifier.toKey(currentExtension.identifier), new FailedExtension(error));
return;
}
} else {
if (this._hostExtensionsMap.has(ExtensionIdentifier.toKey(depId))) {
// must first wait for the dependency to activate
currentExtensionGetsGreenLight = false;
greenExtensions[ExtensionIdentifier.toKey(depId)] = depDesc;
greenExtensions[ExtensionIdentifier.toKey(depId)] = this._hostExtensionsMap.get(ExtensionIdentifier.toKey(depId))!;
continue;
}
const depDesc = this._registry.getExtensionDescription(depId);
if (depDesc) {
// must first wait for the dependency to activate
currentExtensionGetsGreenLight = false;
greenExtensions[ExtensionIdentifier.toKey(depId)] = depDesc.identifier;
continue;
}
// Error condition 1: unknown dependency
this._host.showMessage(Severity.Error, nls.localize('unknownDep', "Cannot activate extension '{0}' because it depends on extension '{1}', which is not installed or disabled. Please install or enable '{1}' and reload the window.", currentExtension.displayName || currentExtension.identifier.value, depId));
const error = new Error(`Unknown dependency '${depId}'`);
this._activatedExtensions.set(ExtensionIdentifier.toKey(currentExtension.identifier), new FailedExtension(error));
return;
}
if (currentExtensionGetsGreenLight) {
greenExtensions[ExtensionIdentifier.toKey(currentExtension.identifier)] = currentExtension;
greenExtensions[ExtensionIdentifier.toKey(currentExtension.identifier)] = currentExtensionId;
} else {
redExtensions.push(currentExtension);
redExtensions.push(currentExtensionId);
}
}
private _activateExtensions(extensionDescriptions: IExtensionDescription[], reason: ExtensionActivationReason, recursionLevel: number): Promise<void> {
// console.log(recursionLevel, '_activateExtensions: ', extensionDescriptions.map(p => p.id));
if (extensionDescriptions.length === 0) {
private _activateExtensions(extensionIds: ExtensionIdentifier[], reason: ExtensionActivationReason): Promise<void> {
// console.log('_activateExtensions: ', extensionIds.map(p => p.value));
if (extensionIds.length === 0) {
return Promise.resolve(undefined);
}
extensionDescriptions = extensionDescriptions.filter((p) => !this._activatedExtensions.has(ExtensionIdentifier.toKey(p.identifier)));
if (extensionDescriptions.length === 0) {
extensionIds = extensionIds.filter((p) => !this._activatedExtensions.has(ExtensionIdentifier.toKey(p)));
if (extensionIds.length === 0) {
return Promise.resolve(undefined);
}
if (recursionLevel > 10) {
// 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].identifier.value));
const error = new Error('More than 10 levels of dependencies (most likely a dependency loop)');
this._activatedExtensions.set(ExtensionIdentifier.toKey(extensionDescriptions[i].identifier), new FailedExtension(error));
}
return Promise.resolve(undefined);
}
let greenMap: { [id: string]: ExtensionIdentifier; } = Object.create(null),
red: ExtensionIdentifier[] = [];
let greenMap: { [id: string]: IExtensionDescription; } = Object.create(null),
red: IExtensionDescription[] = [];
for (let i = 0, len = extensionDescriptions.length; i < len; i++) {
this._handleActivateRequest(extensionDescriptions[i], greenMap, red);
for (let i = 0, len = extensionIds.length; i < len; i++) {
this._handleActivateRequest(extensionIds[i], greenMap, red);
}
// Make sure no red is also green
for (let i = 0, len = red.length; i < len; i++) {
const redExtensionKey = ExtensionIdentifier.toKey(red[i].identifier);
const redExtensionKey = ExtensionIdentifier.toKey(red[i]);
if (greenMap[redExtensionKey]) {
delete greenMap[redExtensionKey];
}
@@ -342,13 +355,13 @@ export class ExtensionsActivator {
return Promise.all(green.map((p) => this._activateExtension(p, reason))).then(_ => undefined);
}
return this._activateExtensions(green, reason, recursionLevel + 1).then(_ => {
return this._activateExtensions(red, reason, recursionLevel + 1);
return this._activateExtensions(green, reason).then(_ => {
return this._activateExtensions(red, reason);
});
}
private _activateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise<void> {
const extensionKey = ExtensionIdentifier.toKey(extensionDescription.identifier);
private _activateExtension(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void> {
const extensionKey = ExtensionIdentifier.toKey(extensionId);
if (this._activatedExtensions.has(extensionKey)) {
return Promise.resolve(undefined);
@@ -359,9 +372,9 @@ export class ExtensionsActivator {
return currentlyActivatingExtension;
}
const newlyActivatingExtension = this._host.actualActivateExtension(extensionDescription, reason).then(undefined, (err) => {
this._host.showMessage(Severity.Error, nls.localize('activationError', "Activating extension '{0}' failed: {1}.", extensionDescription.identifier.value, err.message));
console.error('Activating extension `' + extensionDescription.identifier.value + '` failed: ', err.message);
const newlyActivatingExtension = this._host.actualActivateExtension(extensionId, reason).then(undefined, (err) => {
this._host.showMessage(Severity.Error, nls.localize('activationError', "Activating extension '{0}' failed: {1}.", extensionId.value, err.message));
console.error('Activating extension `' + extensionId.value + '` failed: ', err.message);
console.log('Here is the error stack: ', err.stack);
// Treat the extension as being empty
return new FailedExtension(err);

View File

@@ -13,12 +13,12 @@ import { URI } from 'vs/base/common/uri';
import * as pfs from 'vs/base/node/pfs';
import { ILogService } from 'vs/platform/log/common/log';
import { createApiFactory, initializeExtensionApi, IExtensionApiFactory } from 'vs/workbench/api/node/extHost.api.impl';
import { ExtHostExtensionServiceShape, IEnvironment, IInitData, IMainContext, IWorkspaceData, MainContext, MainThreadExtensionServiceShape, MainThreadTelemetryShape, MainThreadWorkspaceShape } from 'vs/workbench/api/node/extHost.protocol';
import { ExtHostExtensionServiceShape, IEnvironment, IInitData, IMainContext, MainContext, MainThreadExtensionServiceShape, MainThreadTelemetryShape, MainThreadWorkspaceShape, IStaticWorkspaceData } from 'vs/workbench/api/node/extHost.protocol';
import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration';
import { ActivatedExtension, EmptyExtension, ExtensionActivatedByAPI, ExtensionActivatedByEvent, ExtensionActivationReason, ExtensionActivationTimes, ExtensionActivationTimesBuilder, ExtensionsActivator, IExtensionAPI, IExtensionContext, IExtensionMemento, IExtensionModule } from 'vs/workbench/api/node/extHostExtensionActivator';
import { ActivatedExtension, EmptyExtension, ExtensionActivatedByAPI, ExtensionActivatedByEvent, ExtensionActivationReason, ExtensionActivationTimes, ExtensionActivationTimesBuilder, ExtensionsActivator, IExtensionAPI, IExtensionContext, IExtensionMemento, IExtensionModule, HostExtension } from 'vs/workbench/api/node/extHostExtensionActivator';
import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService';
import { ExtHostStorage } from 'vs/workbench/api/node/extHostStorage';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { ExtHostWorkspace, ExtHostWorkspaceProvider } from 'vs/workbench/api/node/extHostWorkspace';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry';
import { connectProxyResolver } from 'vs/workbench/services/extensions/node/proxyResolver';
@@ -26,6 +26,7 @@ import { CancellationTokenSource } from 'vs/base/common/cancellation';
import * as errors from 'vs/base/common/errors';
import { ResolvedAuthority } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IWorkspace } from 'vs/platform/workspace/common/workspace';
class ExtensionMemento implements IExtensionMemento {
@@ -80,13 +81,13 @@ class ExtensionMemento implements IExtensionMemento {
class ExtensionStoragePath {
private readonly _workspace: IWorkspaceData;
private readonly _workspace?: IStaticWorkspaceData;
private readonly _environment: IEnvironment;
private readonly _ready: Promise<string>;
private _value: string;
private readonly _ready: Promise<string | undefined>;
private _value?: string;
constructor(workspace: IWorkspaceData, environment: IEnvironment) {
constructor(workspace: IStaticWorkspaceData | undefined, environment: IEnvironment) {
this._workspace = workspace;
this._environment = environment;
this._ready = this._getOrCreateWorkspaceStoragePath().then(value => this._value = value);
@@ -96,7 +97,7 @@ class ExtensionStoragePath {
return this._ready;
}
workspaceValue(extension: IExtensionDescription): string {
workspaceValue(extension: IExtensionDescription): string | undefined {
if (this._value) {
return path.join(this._value, extension.identifier.value);
}
@@ -107,7 +108,7 @@ class ExtensionStoragePath {
return path.join(this._environment.globalStorageHome.fsPath, extension.identifier.value.toLowerCase());
}
private async _getOrCreateWorkspaceStoragePath(): Promise<string> {
private async _getOrCreateWorkspaceStoragePath(): Promise<string | undefined> {
if (!this._workspace) {
return Promise.resolve(undefined);
}
@@ -192,7 +193,11 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
this._registry = new ExtensionDescriptionRegistry(initData.extensions);
this._storage = new ExtHostStorage(this._extHostContext);
this._storagePath = new ExtensionStoragePath(initData.workspace, initData.environment);
this._activator = new ExtensionsActivator(this._registry, initData.resolvedExtensions, {
const hostExtensions = new Set<string>();
initData.hostExtensions.forEach((extensionId) => hostExtensions.add(ExtensionIdentifier.toKey(extensionId)));
this._activator = new ExtensionsActivator(this._registry, initData.resolvedExtensions, initData.hostExtensions, {
showMessage: (severity: Severity, message: string): void => {
this._mainThreadExtensionsProxy.$localShowMessage(severity, message);
@@ -208,7 +213,13 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
}
},
actualActivateExtension: (extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise<ActivatedExtension> => {
actualActivateExtension: async (extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<ActivatedExtension> => {
if (hostExtensions.has(ExtensionIdentifier.toKey(extensionId))) {
let activationEvent = (reason instanceof ExtensionActivatedByEvent ? reason.activationEvent : null);
await this._mainThreadExtensionsProxy.$activateExtension(extensionId, activationEvent);
return new HostExtension();
}
const extensionDescription = this._registry.getExtensionDescription(extensionId);
return this._activateExtension(extensionDescription, reason);
}
});
@@ -229,9 +240,10 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
private async _initialize(): Promise<void> {
try {
const configProvider = await this._extHostConfiguration.getConfigProvider();
await initializeExtensionApi(this, this._extensionApiFactory, this._registry, configProvider);
const workspaceProvider = await this._extHostWorkspace.getWorkspaceProvider();
await initializeExtensionApi(this, this._extensionApiFactory, this._registry, workspaceProvider, configProvider);
// Do this when extension service exists, but extensions are not being activated yet.
await connectProxyResolver(this._extHostWorkspace, configProvider, this, this._extHostLogService, this._mainThreadTelemetryProxy);
await connectProxyResolver(workspaceProvider, configProvider, this, this._extHostLogService, this._mainThreadTelemetryProxy);
this._barrier.open();
} catch (err) {
errors.onUnexpectedError(err);
@@ -473,15 +485,15 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
// -- eager activation
// Handle "eager" activation extensions
private _handleEagerExtensions(): Promise<void> {
private _handleEagerExtensions(workspaceProvider: ExtHostWorkspaceProvider): Promise<void> {
this._activateByEvent('*', true).then(undefined, (err) => {
console.error(err);
});
return this._handleWorkspaceContainsEagerExtensions(this._initData.workspace);
return this._handleWorkspaceContainsEagerExtensions(workspaceProvider.workspace);
}
private _handleWorkspaceContainsEagerExtensions(workspace: IWorkspaceData): Promise<void> {
private _handleWorkspaceContainsEagerExtensions(workspace: IWorkspace | undefined): Promise<void> {
if (!workspace || workspace.folders.length === 0) {
return Promise.resolve(undefined);
}
@@ -493,7 +505,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
).then(() => { });
}
private _handleWorkspaceContainsEagerExtension(workspace: IWorkspaceData, desc: IExtensionDescription): Promise<void> {
private _handleWorkspaceContainsEagerExtension(workspace: IWorkspace, desc: IExtensionDescription): Promise<void> {
const activationEvents = desc.activationEvents;
if (!activationEvents) {
return Promise.resolve(undefined);
@@ -523,7 +535,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
return Promise.all([fileNamePromise, globPatternPromise]).then(() => { });
}
private async _activateIfFileName(workspace: IWorkspaceData, extensionId: ExtensionIdentifier, fileName: string): Promise<void> {
private async _activateIfFileName(workspace: IWorkspace, extensionId: ExtensionIdentifier, fileName: string): Promise<void> {
// find exact path
for (const { uri } of workspace.folders) {
@@ -555,7 +567,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
.then(undefined, err => console.error(err));
}, ExtHostExtensionService.WORKSPACE_CONTAINS_TIMEOUT);
let exists: boolean;
let exists: boolean = false;
try {
exists = await searchP;
} catch (err) {
@@ -596,8 +608,8 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
}
// Require the test runner via node require from the provided path
let testRunner: ITestRunner;
let requireError: Error;
let testRunner: ITestRunner | undefined;
let requireError: Error | undefined;
try {
testRunner = <any>require.__$__nodeRequire(this._initData.environment.extensionTestsPath);
} catch (error) {
@@ -607,7 +619,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
// Execute the runner if it follows our spec
if (testRunner && typeof testRunner.run === 'function') {
return new Promise<void>((c, e) => {
testRunner.run(this._initData.environment.extensionTestsPath, (error, failures) => {
testRunner!.run(this._initData.environment.extensionTestsPath, (error, failures) => {
if (error) {
e(error.toString());
} else {
@@ -641,7 +653,8 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
this._started = true;
return this._barrier.wait()
.then(() => this._handleEagerExtensions())
.then(() => this._extHostWorkspace.getWorkspaceProvider())
.then(workspaceProvider => this._handleEagerExtensions(workspaceProvider))
.then(() => this._handleExtensionTests())
.then(() => {
this._extHostLogService.info(`eager extensions activated`);
@@ -666,11 +679,14 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
);
}
public $activate(extensionId: ExtensionIdentifier, activationEvent: string): Promise<void> {
return (
this._barrier.wait()
.then(_ => this._activateById(extensionId, new ExtensionActivatedByEvent(false, activationEvent)))
);
public async $activate(extensionId: ExtensionIdentifier, activationEvent: string): Promise<boolean> {
await this._barrier.wait();
if (!this._registry.getExtensionDescription(extensionId)) {
// unknown extension => ignore
return false;
}
await this._activateById(extensionId, new ExtensionActivatedByEvent(false, activationEvent));
return true;
}
public async $deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise<void> {

View File

@@ -39,12 +39,12 @@ class DocumentSymbolAdapter {
this._provider = provider;
}
provideDocumentSymbols(resource: URI, token: CancellationToken): Promise<modes.DocumentSymbol[]> {
let doc = this._documents.getDocumentData(resource).document;
provideDocumentSymbols(resource: URI, token: CancellationToken): Promise<modes.DocumentSymbol[] | undefined> {
const doc = this._documents.getDocument(resource);
return asPromise(() => this._provider.provideDocumentSymbols(doc, token)).then(value => {
if (isFalsyOrEmpty(value)) {
return undefined;
} else if (value[0] instanceof DocumentSymbol) {
} else if (value![0] instanceof DocumentSymbol) {
return (<DocumentSymbol[]>value).map(typeConvert.DocumentSymbol.from);
} else {
return DocumentSymbolAdapter._asDocumentSymbolTree(<SymbolInformation[]>value);
@@ -105,7 +105,7 @@ class CodeLensAdapter {
) { }
provideCodeLenses(resource: URI, token: CancellationToken): Promise<CodeLensDto[]> {
const doc = this._documents.getDocumentData(resource).document;
const doc = this._documents.getDocument(resource);
return asPromise(() => this._provider.provideCodeLenses(doc, token)).then(lenses => {
let result: CodeLensDto[] = [];
@@ -122,18 +122,18 @@ class CodeLensAdapter {
});
}
resolveCodeLens(resource: URI, symbol: CodeLensDto, token: CancellationToken): Promise<CodeLensDto> {
resolveCodeLens(resource: URI, symbol: CodeLensDto, token: CancellationToken): Promise<CodeLensDto | undefined> {
const lens = this._heapService.get<vscode.CodeLens>(ObjectIdentifier.of(symbol));
if (!lens) {
return undefined;
return Promise.resolve(undefined);
}
let resolve: Promise<vscode.CodeLens>;
let resolve: Promise<vscode.CodeLens | undefined | null>;
if (typeof this._provider.resolveCodeLens !== 'function' || lens.isResolved) {
resolve = Promise.resolve(lens);
} else {
resolve = asPromise(() => this._provider.resolveCodeLens(lens, token));
resolve = asPromise(() => this._provider.resolveCodeLens!(lens, token));
}
return resolve.then(newLens => {
@@ -150,7 +150,7 @@ function convertToLocationLinks(value: vscode.Definition): modes.LocationLink[]
} else if (value) {
return [typeConvert.DefinitionLink.from(value)];
}
return undefined;
return [];
}
class DefinitionAdapter {
@@ -161,7 +161,7 @@ class DefinitionAdapter {
) { }
provideDefinition(resource: URI, position: IPosition, token: CancellationToken): Promise<modes.LocationLink[]> {
let doc = this._documents.getDocumentData(resource).document;
const doc = this._documents.getDocument(resource);
let pos = typeConvert.Position.to(position);
return asPromise(() => this._provider.provideDefinition(doc, pos, token)).then(convertToLocationLinks);
}
@@ -175,7 +175,7 @@ class DeclarationAdapter {
) { }
provideDeclaration(resource: URI, position: IPosition, token: CancellationToken): Promise<modes.LocationLink[]> {
let doc = this._documents.getDocumentData(resource).document;
const doc = this._documents.getDocument(resource);
let pos = typeConvert.Position.to(position);
return asPromise(() => this._provider.provideDeclaration(doc, pos, token)).then(convertToLocationLinks);
}
@@ -189,7 +189,7 @@ class ImplementationAdapter {
) { }
provideImplementation(resource: URI, position: IPosition, token: CancellationToken): Promise<modes.LocationLink[]> {
let doc = this._documents.getDocumentData(resource).document;
const doc = this._documents.getDocument(resource);
let pos = typeConvert.Position.to(position);
return asPromise(() => this._provider.provideImplementation(doc, pos, token)).then(convertToLocationLinks);
}
@@ -203,7 +203,7 @@ class TypeDefinitionAdapter {
) { }
provideTypeDefinition(resource: URI, position: IPosition, token: CancellationToken): Promise<modes.LocationLink[]> {
const doc = this._documents.getDocumentData(resource).document;
const doc = this._documents.getDocument(resource);
const pos = typeConvert.Position.to(position);
return asPromise(() => this._provider.provideTypeDefinition(doc, pos, token)).then(convertToLocationLinks);
}
@@ -216,9 +216,9 @@ class HoverAdapter {
private readonly _provider: vscode.HoverProvider,
) { }
public provideHover(resource: URI, position: IPosition, token: CancellationToken): Promise<modes.Hover> {
public provideHover(resource: URI, position: IPosition, token: CancellationToken): Promise<modes.Hover | undefined> {
let doc = this._documents.getDocumentData(resource).document;
const doc = this._documents.getDocument(resource);
let pos = typeConvert.Position.to(position);
return asPromise(() => this._provider.provideHover(doc, pos, token)).then(value => {
@@ -244,9 +244,9 @@ class DocumentHighlightAdapter {
private readonly _provider: vscode.DocumentHighlightProvider
) { }
provideDocumentHighlights(resource: URI, position: IPosition, token: CancellationToken): Promise<modes.DocumentHighlight[]> {
provideDocumentHighlights(resource: URI, position: IPosition, token: CancellationToken): Promise<modes.DocumentHighlight[] | undefined> {
let doc = this._documents.getDocumentData(resource).document;
const doc = this._documents.getDocument(resource);
let pos = typeConvert.Position.to(position);
return asPromise(() => this._provider.provideDocumentHighlights(doc, pos, token)).then(value => {
@@ -265,8 +265,8 @@ class ReferenceAdapter {
private readonly _provider: vscode.ReferenceProvider
) { }
provideReferences(resource: URI, position: IPosition, context: modes.ReferenceContext, token: CancellationToken): Promise<modes.Location[]> {
let doc = this._documents.getDocumentData(resource).document;
provideReferences(resource: URI, position: IPosition, context: modes.ReferenceContext, token: CancellationToken): Promise<modes.Location[] | undefined> {
const doc = this._documents.getDocument(resource);
let pos = typeConvert.Position.to(position);
return asPromise(() => this._provider.provideReferences(doc, pos, context, token)).then(value => {
@@ -294,9 +294,9 @@ class CodeActionAdapter {
private readonly _extensionId: ExtensionIdentifier
) { }
provideCodeActions(resource: URI, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise<CodeActionDto[]> {
provideCodeActions(resource: URI, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise<CodeActionDto[] | undefined> {
const doc = this._documents.getDocumentData(resource).document;
const doc = this._documents.getDocument(resource);
const ran = Selection.isISelection(rangeOrSelection)
? <vscode.Selection>typeConvert.Selection.to(rangeOrSelection)
: <vscode.Range>typeConvert.Range.to(rangeOrSelection);
@@ -317,7 +317,7 @@ class CodeActionAdapter {
};
return asPromise(() => this._provider.provideCodeActions(doc, ran, codeActionContext, token)).then(commandsOrActions => {
if (isFalsyOrEmpty(commandsOrActions)) {
if (!isNonEmptyArray(commandsOrActions)) {
return undefined;
}
const result: CustomCodeAction[] = [];
@@ -369,9 +369,9 @@ class DocumentFormattingAdapter {
private readonly _provider: vscode.DocumentFormattingEditProvider
) { }
provideDocumentFormattingEdits(resource: URI, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]> {
provideDocumentFormattingEdits(resource: URI, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined> {
const { document } = this._documents.getDocumentData(resource);
const document = this._documents.getDocument(resource);
return asPromise(() => this._provider.provideDocumentFormattingEdits(document, <any>options, token)).then(value => {
if (Array.isArray(value)) {
@@ -389,9 +389,9 @@ class RangeFormattingAdapter {
private readonly _provider: vscode.DocumentRangeFormattingEditProvider
) { }
provideDocumentRangeFormattingEdits(resource: URI, range: IRange, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]> {
provideDocumentRangeFormattingEdits(resource: URI, range: IRange, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined> {
const { document } = this._documents.getDocumentData(resource);
const document = this._documents.getDocument(resource);
const ran = typeConvert.Range.to(range);
return asPromise(() => this._provider.provideDocumentRangeFormattingEdits(document, ran, <any>options, token)).then(value => {
@@ -412,9 +412,9 @@ class OnTypeFormattingAdapter {
autoFormatTriggerCharacters: string[] = []; // not here
provideOnTypeFormattingEdits(resource: URI, position: IPosition, ch: string, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]> {
provideOnTypeFormattingEdits(resource: URI, position: IPosition, ch: string, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined> {
const { document } = this._documents.getDocumentData(resource);
const document = this._documents.getDocument(resource);
const pos = typeConvert.Position.to(position);
return asPromise(() => this._provider.provideOnTypeFormattingEdits(document, pos, ch, <any>options, token)).then(value => {
@@ -450,7 +450,7 @@ class NavigateTypeAdapter {
continue;
}
const symbol = IdObject.mixin(typeConvert.WorkspaceSymbol.from(item));
this._symbolCache[symbol._id] = item;
this._symbolCache[symbol._id!] = item;
result.symbols.push(symbol);
}
}
@@ -462,19 +462,19 @@ class NavigateTypeAdapter {
});
}
resolveWorkspaceSymbol(symbol: WorkspaceSymbolDto, token: CancellationToken): Promise<WorkspaceSymbolDto> {
resolveWorkspaceSymbol(symbol: WorkspaceSymbolDto, token: CancellationToken): Promise<WorkspaceSymbolDto | undefined> {
if (typeof this._provider.resolveWorkspaceSymbol !== 'function') {
return Promise.resolve(symbol);
}
const item = this._symbolCache[symbol._id];
const item = this._symbolCache[symbol._id!];
if (item) {
return asPromise(() => this._provider.resolveWorkspaceSymbol(item, token)).then(value => {
return asPromise(() => this._provider.resolveWorkspaceSymbol!(item, token)).then(value => {
return value && mixin(symbol, typeConvert.WorkspaceSymbol.from(value), true);
});
}
return undefined;
return Promise.resolve(undefined);
}
releaseWorkspaceSymbols(id: number): any {
@@ -499,9 +499,9 @@ class RenameAdapter {
private readonly _provider: vscode.RenameProvider
) { }
provideRenameEdits(resource: URI, position: IPosition, newName: string, token: CancellationToken): Promise<WorkspaceEditDto> {
provideRenameEdits(resource: URI, position: IPosition, newName: string, token: CancellationToken): Promise<WorkspaceEditDto | undefined> {
let doc = this._documents.getDocumentData(resource).document;
const doc = this._documents.getDocument(resource);
let pos = typeConvert.Position.to(position);
return asPromise(() => this._provider.provideRenameEdits(doc, pos, newName, token)).then(value => {
@@ -512,7 +512,7 @@ class RenameAdapter {
}, err => {
let rejectReason = RenameAdapter._asMessage(err);
if (rejectReason) {
return <WorkspaceEditDto>{ rejectReason, edits: undefined };
return <WorkspaceEditDto>{ rejectReason, edits: undefined! };
} else {
// generic error
return Promise.reject<WorkspaceEditDto>(err);
@@ -520,17 +520,17 @@ class RenameAdapter {
});
}
resolveRenameLocation(resource: URI, position: IPosition, token: CancellationToken): Promise<modes.RenameLocation & modes.Rejection> {
resolveRenameLocation(resource: URI, position: IPosition, token: CancellationToken): Promise<(modes.RenameLocation & modes.Rejection) | undefined> {
if (typeof this._provider.prepareRename !== 'function') {
return Promise.resolve(undefined);
}
let doc = this._documents.getDocumentData(resource).document;
const doc = this._documents.getDocument(resource);
let pos = typeConvert.Position.to(position);
return asPromise(() => this._provider.prepareRename(doc, pos, token)).then(rangeOrLocation => {
let range: vscode.Range;
let range: vscode.Range | undefined;
let text: string;
if (Range.isRange(rangeOrLocation)) {
range = rangeOrLocation;
@@ -552,14 +552,14 @@ class RenameAdapter {
}, err => {
let rejectReason = RenameAdapter._asMessage(err);
if (rejectReason) {
return <modes.RenameLocation & modes.Rejection>{ rejectReason, range: undefined, text: undefined };
return <modes.RenameLocation & modes.Rejection>{ rejectReason, range: undefined!, text: undefined! };
} else {
return Promise.reject<any>(err);
}
});
}
private static _asMessage(err: any): string {
private static _asMessage(err: any): string | undefined {
if (typeof err === 'string') {
return err;
} else if (err instanceof Error && typeof err.message === 'string') {
@@ -591,7 +591,7 @@ class SuggestAdapter {
provideCompletionItems(resource: URI, position: IPosition, context: modes.CompletionContext, token: CancellationToken): Promise<SuggestResultDto> {
const doc = this._documents.getDocumentData(resource).document;
const doc = this._documents.getDocument(resource);
const pos = typeConvert.Position.to(position);
return asPromise<vscode.CompletionItem[] | vscode.CompletionList>(
@@ -643,18 +643,18 @@ class SuggestAdapter {
}
const { _parentId, _id } = (<SuggestionDto>suggestion);
const item = this._cache.has(_parentId) && this._cache.get(_parentId)[_id];
const item = this._cache.has(_parentId) ? this._cache.get(_parentId)![_id] : undefined;
if (!item) {
return Promise.resolve(suggestion);
}
return asPromise(() => this._provider.resolveCompletionItem(item, token)).then(resolvedItem => {
return asPromise(() => this._provider.resolveCompletionItem!(item, token)).then(resolvedItem => {
if (!resolvedItem) {
return suggestion;
}
const doc = this._documents.getDocumentData(resource).document;
const doc = this._documents.getDocument(resource);
const pos = typeConvert.Position.to(position);
const wordRangeBeforePos = (doc.getWordRangeAtPosition(pos) as Range || new Range(pos, pos)).with({ end: pos });
const newSuggestion = this._convertCompletionItem(resolvedItem, pos, wordRangeBeforePos, _id, _parentId);
@@ -670,7 +670,7 @@ class SuggestAdapter {
this._cache.delete(id);
}
private _convertCompletionItem(item: vscode.CompletionItem, position: vscode.Position, defaultRange: vscode.Range, _id: number, _parentId: number): SuggestionDto {
private _convertCompletionItem(item: vscode.CompletionItem, position: vscode.Position, defaultRange: vscode.Range, _id: number, _parentId: number): SuggestionDto | undefined {
if (typeof item.label !== 'string' || item.label.length === 0) {
console.warn('INVALID text edit -> must have at least a label');
return undefined;
@@ -684,7 +684,7 @@ class SuggestAdapter {
label: item.label,
kind: typeConvert.CompletionItemKind.from(item.kind),
detail: item.detail,
documentation: typeConvert.MarkdownString.fromStrict(item.documentation),
documentation: typeof item.documentation === 'undefined' ? undefined : typeConvert.MarkdownString.fromStrict(item.documentation),
filterText: item.filterText,
sortText: item.sortText,
preselect: item.preselect,
@@ -740,8 +740,8 @@ class SignatureHelpAdapter {
private readonly _heap: ExtHostHeapService,
) { }
provideSignatureHelp(resource: URI, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise<modes.SignatureHelp> {
const doc = this._documents.getDocumentData(resource).document;
provideSignatureHelp(resource: URI, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise<modes.SignatureHelp | undefined> {
const doc = this._documents.getDocument(resource);
const pos = typeConvert.Position.to(position);
const vscodeContext = this.reviveContext(context);
@@ -779,8 +779,8 @@ class LinkProviderAdapter {
private readonly _provider: vscode.DocumentLinkProvider
) { }
provideLinks(resource: URI, token: CancellationToken): Promise<LinkDto[]> {
const doc = this._documents.getDocumentData(resource).document;
provideLinks(resource: URI, token: CancellationToken): Promise<LinkDto[] | undefined> {
const doc = this._documents.getDocument(resource);
return asPromise(() => this._provider.provideDocumentLinks(doc, token)).then(links => {
if (!Array.isArray(links)) {
@@ -796,18 +796,18 @@ class LinkProviderAdapter {
});
}
resolveLink(link: LinkDto, token: CancellationToken): Promise<LinkDto> {
resolveLink(link: LinkDto, token: CancellationToken): Promise<LinkDto | undefined> {
if (typeof this._provider.resolveDocumentLink !== 'function') {
return undefined;
return Promise.resolve(undefined);
}
const id = ObjectIdentifier.of(link);
const item = this._heapService.get<vscode.DocumentLink>(id);
if (!item) {
return undefined;
return Promise.resolve(undefined);
}
return asPromise(() => this._provider.resolveDocumentLink(item, token)).then(value => {
return asPromise(() => this._provider.resolveDocumentLink!(item, token)).then(value => {
if (value) {
return typeConvert.DocumentLink.from(value);
}
@@ -824,7 +824,7 @@ class ColorProviderAdapter {
) { }
provideColors(resource: URI, token: CancellationToken): Promise<IRawColorInfo[]> {
const doc = this._documents.getDocumentData(resource).document;
const doc = this._documents.getDocument(resource);
return asPromise(() => this._provider.provideDocumentColors(doc, token)).then(colors => {
if (!Array.isArray(colors)) {
return [];
@@ -841,11 +841,14 @@ class ColorProviderAdapter {
});
}
provideColorPresentations(resource: URI, raw: IRawColorInfo, token: CancellationToken): Promise<modes.IColorPresentation[]> {
const document = this._documents.getDocumentData(resource).document;
provideColorPresentations(resource: URI, raw: IRawColorInfo, token: CancellationToken): Promise<modes.IColorPresentation[] | undefined> {
const document = this._documents.getDocument(resource);
const range = typeConvert.Range.to(raw.range);
const color = typeConvert.Color.to(raw.color);
return asPromise(() => this._provider.provideColorPresentations(color, { document, range }, token)).then(value => {
if (!Array.isArray(value)) {
return undefined;
}
return value.map(typeConvert.ColorPresentation.from);
});
}
@@ -858,8 +861,8 @@ class FoldingProviderAdapter {
private _provider: vscode.FoldingRangeProvider
) { }
provideFoldingRanges(resource: URI, context: modes.FoldingContext, token: CancellationToken): Promise<modes.FoldingRange[]> {
const doc = this._documents.getDocumentData(resource).document;
provideFoldingRanges(resource: URI, context: modes.FoldingContext, token: CancellationToken): Promise<modes.FoldingRange[] | undefined> {
const doc = this._documents.getDocument(resource);
return asPromise(() => this._provider.provideFoldingRanges(doc, context, token)).then(ranges => {
if (!Array.isArray(ranges)) {
return undefined;
@@ -876,23 +879,35 @@ class SelectionRangeAdapter {
private readonly _provider: vscode.SelectionRangeProvider
) { }
provideSelectionRanges(resource: URI, position: IPosition, token: CancellationToken): Promise<modes.SelectionRange[]> {
provideSelectionRanges(resource: URI, pos: IPosition[], token: CancellationToken): Promise<modes.SelectionRange[][]> {
const { document } = this._documents.getDocumentData(resource);
const pos = typeConvert.Position.to(position);
return asPromise(() => this._provider.provideSelectionRanges(document, pos, token)).then(selectionRanges => {
if (isFalsyOrEmpty(selectionRanges)) {
return undefined;
const positions = pos.map(typeConvert.Position.to);
return asPromise(() => this._provider.provideSelectionRanges(document, positions, token)).then(allProviderRanges => {
if (isFalsyOrEmpty(allProviderRanges)) {
return [];
}
let result: modes.SelectionRange[] = [];
let last: vscode.Position | vscode.Range = pos;
for (const sel of selectionRanges) {
if (!sel.range.contains(last)) {
throw new Error('INVALID selection range, must contain the previous range');
if (allProviderRanges.length !== positions.length) {
console.warn('BAD selection ranges, provider must return ranges for each position');
return [];
}
let allResults: modes.SelectionRange[][] = [];
for (let i = 0; i < positions.length; i++) {
const oneResult: modes.SelectionRange[] = [];
allResults.push(oneResult);
const oneProviderRanges = allProviderRanges[i];
let last: vscode.Position | vscode.Range = positions[i];
for (const selectionRange of oneProviderRanges) {
if (!selectionRange.range.contains(last)) {
throw new Error('INVALID selection range, must contain the previous range');
}
oneResult.push(typeConvert.SelectionRange.from(selectionRange));
last = selectionRange.range;
}
result.push(typeConvert.SelectionRange.from(sel));
last = sel.range;
}
return result;
return allResults;
});
}
}
@@ -918,7 +933,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
private static _handlePool: number = 0;
private readonly _schemeTransformer: ISchemeTransformer;
private readonly _schemeTransformer: ISchemeTransformer | null;
private _proxy: MainThreadLanguageFeaturesShape;
private _documents: ExtHostDocuments;
private _commands: ExtHostCommands;
@@ -929,7 +944,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
constructor(
mainContext: IMainContext,
schemeTransformer: ISchemeTransformer,
schemeTransformer: ISchemeTransformer | null,
documents: ExtHostDocuments,
commands: ExtHostCommands,
heapMonitor: ExtHostHeapService,
@@ -953,7 +968,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return [this._doTransformDocumentSelector(selector)];
}
private _doTransformDocumentSelector(selector: string | vscode.DocumentFilter): ISerializedDocumentFilter {
private _doTransformDocumentSelector(selector: string | vscode.DocumentFilter): ISerializedDocumentFilter | undefined {
if (typeof selector === 'string') {
return {
$serialized: true,
@@ -993,7 +1008,11 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
}
private _withAdapter<A, R>(handle: number, ctor: { new(...args: any[]): A }, callback: (adapter: A) => Promise<R>): Promise<R> {
let data = this._adapter.get(handle);
const data = this._adapter.get(handle);
if (!data) {
return Promise.reject(new Error('no adapter found'));
}
if (data.adapter instanceof ctor) {
let t1: number;
if (data.extension) {
@@ -1001,11 +1020,12 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
this._logService.trace(`[${data.extension.identifier.value}] INVOKE provider '${(ctor as any).name}'`);
}
let p = callback(data.adapter);
if (data.extension) {
const extension = data.extension;
if (extension) {
Promise.resolve(p).then(
() => this._logService.trace(`[${data.extension.identifier.value}] provider DONE after ${Date.now() - t1}ms`),
() => this._logService.trace(`[${extension.identifier.value}] provider DONE after ${Date.now() - t1}ms`),
err => {
this._logService.error(`[${data.extension.identifier.value}] provider FAILED`);
this._logService.error(`[${extension.identifier.value}] provider FAILED`);
this._logService.error(err);
}
);
@@ -1034,7 +1054,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideDocumentSymbols(handle: number, resource: UriComponents, token: CancellationToken): Promise<modes.DocumentSymbol[]> {
$provideDocumentSymbols(handle: number, resource: UriComponents, token: CancellationToken): Promise<modes.DocumentSymbol[] | undefined> {
return this._withAdapter(handle, DocumentSymbolAdapter, adapter => adapter.provideDocumentSymbols(URI.revive(resource), token));
}
@@ -1049,7 +1069,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
let result = this._createDisposable(handle);
if (eventHandle !== undefined) {
const subscription = provider.onDidChangeCodeLenses(_ => this._proxy.$emitCodeLensEvent(eventHandle));
const subscription = provider.onDidChangeCodeLenses!(_ => this._proxy.$emitCodeLensEvent(eventHandle));
result = Disposable.from(result, subscription);
}
@@ -1114,7 +1134,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideHover(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.Hover> {
$provideHover(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.Hover | undefined> {
return this._withAdapter(handle, HoverAdapter, adapter => adapter.provideHover(URI.revive(resource), position, token));
}
@@ -1126,7 +1146,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideDocumentHighlights(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.DocumentHighlight[]> {
$provideDocumentHighlights(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.DocumentHighlight[] | undefined> {
return this._withAdapter(handle, DocumentHighlightAdapter, adapter => adapter.provideDocumentHighlights(URI.revive(resource), position, token));
}
@@ -1138,7 +1158,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideReferences(handle: number, resource: UriComponents, position: IPosition, context: modes.ReferenceContext, token: CancellationToken): Promise<modes.Location[]> {
$provideReferences(handle: number, resource: UriComponents, position: IPosition, context: modes.ReferenceContext, token: CancellationToken): Promise<modes.Location[] | undefined> {
return this._withAdapter(handle, ReferenceAdapter, adapter => adapter.provideReferences(URI.revive(resource), position, context, token));
}
@@ -1146,12 +1166,12 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerCodeActionProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider, metadata?: vscode.CodeActionProviderMetadata): vscode.Disposable {
const handle = this._addNewAdapter(new CodeActionAdapter(this._documents, this._commands.converter, this._diagnostics, provider, this._logService, extension.identifier), extension);
this._proxy.$registerQuickFixSupport(handle, this._transformDocumentSelector(selector), metadata && metadata.providedCodeActionKinds ? metadata.providedCodeActionKinds.map(kind => kind.value) : undefined);
this._proxy.$registerQuickFixSupport(handle, this._transformDocumentSelector(selector), (metadata && metadata.providedCodeActionKinds) ? metadata.providedCodeActionKinds.map(kind => kind.value) : undefined);
return this._createDisposable(handle);
}
$provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise<CodeActionDto[]> {
$provideCodeActions(handle: number, resource: UriComponents, rangeOrSelection: IRange | ISelection, context: modes.CodeActionContext, token: CancellationToken): Promise<CodeActionDto[] | undefined> {
return this._withAdapter(handle, CodeActionAdapter, adapter => adapter.provideCodeActions(URI.revive(resource), rangeOrSelection, context, token));
}
@@ -1163,7 +1183,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideDocumentFormattingEdits(handle: number, resource: UriComponents, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]> {
$provideDocumentFormattingEdits(handle: number, resource: UriComponents, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined> {
return this._withAdapter(handle, DocumentFormattingAdapter, adapter => adapter.provideDocumentFormattingEdits(URI.revive(resource), options, token));
}
@@ -1173,7 +1193,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideDocumentRangeFormattingEdits(handle: number, resource: UriComponents, range: IRange, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]> {
$provideDocumentRangeFormattingEdits(handle: number, resource: UriComponents, range: IRange, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined> {
return this._withAdapter(handle, RangeFormattingAdapter, adapter => adapter.provideDocumentRangeFormattingEdits(URI.revive(resource), range, options, token));
}
@@ -1183,7 +1203,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideOnTypeFormattingEdits(handle: number, resource: UriComponents, position: IPosition, ch: string, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[]> {
$provideOnTypeFormattingEdits(handle: number, resource: UriComponents, position: IPosition, ch: string, options: modes.FormattingOptions, token: CancellationToken): Promise<ISingleEditOperation[] | undefined> {
return this._withAdapter(handle, OnTypeFormattingAdapter, adapter => adapter.provideOnTypeFormattingEdits(URI.revive(resource), position, ch, options, token));
}
@@ -1199,7 +1219,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.provideWorkspaceSymbols(search, token));
}
$resolveWorkspaceSymbol(handle: number, symbol: WorkspaceSymbolDto, token: CancellationToken): Promise<WorkspaceSymbolDto> {
$resolveWorkspaceSymbol(handle: number, symbol: WorkspaceSymbolDto, token: CancellationToken): Promise<WorkspaceSymbolDto | undefined> {
return this._withAdapter(handle, NavigateTypeAdapter, adapter => adapter.resolveWorkspaceSymbol(symbol, token));
}
@@ -1215,11 +1235,11 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string, token: CancellationToken): Promise<WorkspaceEditDto> {
$provideRenameEdits(handle: number, resource: UriComponents, position: IPosition, newName: string, token: CancellationToken): Promise<WorkspaceEditDto | undefined> {
return this._withAdapter(handle, RenameAdapter, adapter => adapter.provideRenameEdits(URI.revive(resource), position, newName, token));
}
$resolveRenameLocation(handle: number, resource: URI, position: IPosition, token: CancellationToken): Promise<modes.RenameLocation> {
$resolveRenameLocation(handle: number, resource: URI, position: IPosition, token: CancellationToken): Promise<modes.RenameLocation | undefined> {
return this._withAdapter(handle, RenameAdapter, adapter => adapter.resolveRenameLocation(URI.revive(resource), position, token));
}
@@ -1245,8 +1265,8 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
// --- parameter hints
registerSignatureHelpProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, metadataOrTriggerChars?: string[] | vscode.SignatureHelpProviderMetadata): vscode.Disposable {
const metadata: ISerializedSignatureHelpProviderMetadata = Array.isArray(metadataOrTriggerChars)
registerSignatureHelpProvider(extension: IExtensionDescription, selector: vscode.DocumentSelector, provider: vscode.SignatureHelpProvider, metadataOrTriggerChars: string[] | vscode.SignatureHelpProviderMetadata): vscode.Disposable {
const metadata: ISerializedSignatureHelpProviderMetadata | undefined = Array.isArray(metadataOrTriggerChars)
? { triggerCharacters: metadataOrTriggerChars, retriggerCharacters: [] }
: metadataOrTriggerChars;
@@ -1255,7 +1275,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise<modes.SignatureHelp> {
$provideSignatureHelp(handle: number, resource: UriComponents, position: IPosition, context: modes.SignatureHelpContext, token: CancellationToken): Promise<modes.SignatureHelp | undefined> {
return this._withAdapter(handle, SignatureHelpAdapter, adapter => adapter.provideSignatureHelp(URI.revive(resource), position, context, token));
}
@@ -1267,11 +1287,11 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideDocumentLinks(handle: number, resource: UriComponents, token: CancellationToken): Promise<modes.ILink[]> {
$provideDocumentLinks(handle: number, resource: UriComponents, token: CancellationToken): Promise<modes.ILink[] | undefined> {
return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.provideLinks(URI.revive(resource), token));
}
$resolveDocumentLink(handle: number, link: modes.ILink, token: CancellationToken): Promise<modes.ILink> {
$resolveDocumentLink(handle: number, link: modes.ILink, token: CancellationToken): Promise<modes.ILink | undefined> {
return this._withAdapter(handle, LinkProviderAdapter, adapter => adapter.resolveLink(link, token));
}
@@ -1307,8 +1327,8 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}
$provideSelectionRanges(handle: number, resource: UriComponents, position: IPosition, token: CancellationToken): Promise<modes.SelectionRange[]> {
return this._withAdapter(handle, SelectionRangeAdapter, adapter => adapter.provideSelectionRanges(URI.revive(resource), position, token));
$provideSelectionRanges(handle: number, resource: UriComponents, positions: IPosition[], token: CancellationToken): Promise<modes.SelectionRange[][]> {
return this._withAdapter(handle, SelectionRangeAdapter, adapter => adapter.provideSelectionRanges(URI.revive(resource), positions, token));
}
// --- configuration
@@ -1350,7 +1370,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
};
}
private static _serializeOnEnterRules(onEnterRules: vscode.OnEnterRule[]): ISerializedOnEnterRule[] {
private static _serializeOnEnterRules(onEnterRules: vscode.OnEnterRule[]): ISerializedOnEnterRule[] | undefined | null {
if (typeof onEnterRules === 'undefined') {
return undefined;
}
@@ -1372,7 +1392,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
if (wordPattern) {
this._documents.setWordDefinitionFor(languageId, wordPattern);
} else {
this._documents.setWordDefinitionFor(languageId, null);
this._documents.setWordDefinitionFor(languageId, undefined);
}
const handle = this._nextHandle();

View File

@@ -24,9 +24,10 @@ export class ExtHostLanguages {
return this._proxy.$getLanguages();
}
changeLanguage(uri: vscode.Uri, languageId: string): Promise<vscode.TextDocument> {
changeLanguage(uri: vscode.Uri, languageId: string): Promise<vscode.TextDocument | undefined> {
return this._proxy.$changeLanguage(uri, languageId).then(() => {
return this._documents.getDocumentData(uri).document;
const data = this._documents.getDocumentData(uri);
return data ? data.document : undefined;
});
}
}

View File

@@ -7,7 +7,7 @@ import { MainContext, MainThreadOutputServiceShape, IMainContext, ExtHostOutputS
import * as vscode from 'vscode';
import { URI } from 'vs/base/common/uri';
import { posix } from 'path';
import { OutputAppender } from 'vs/platform/output/node/outputAppender';
import { OutputAppender } from 'vs/workbench/contrib/output/node/outputAppender';
import { toLocalISOString } from 'vs/base/common/date';
import { Event, Emitter } from 'vs/base/common/event';
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';

View File

@@ -27,11 +27,11 @@ export class ExtHostProgress implements ExtHostProgressShape {
const { title, location, cancellable } = options;
const source = localize('extensionSource', "{0} (Extension)", extension.displayName || extension.name);
this._proxy.$startProgress(handle, { location: ProgressLocation.from(location), title, source, cancellable });
return this._withProgress(handle, task, cancellable);
return this._withProgress(handle, task, !!cancellable);
}
private _withProgress<R>(handle: number, task: (progress: Progress<IProgressStep>, token: CancellationToken) => Thenable<R>, cancellable: boolean): Thenable<R> {
let source: CancellationTokenSource;
let source: CancellationTokenSource | undefined;
if (cancellable) {
source = new CancellationTokenSource();
this._mapHandleToCancellationSource.set(handle, source);
@@ -48,7 +48,7 @@ export class ExtHostProgress implements ExtHostProgressShape {
let p: Thenable<R>;
try {
p = task(new ProgressCallback(this._proxy, handle), cancellable ? source.token : CancellationToken.None);
p = task(new ProgressCallback(this._proxy, handle), cancellable && source ? source.token : CancellationToken.None);
} catch (err) {
progressEnd(handle);
throw err;

View File

@@ -164,7 +164,7 @@ export class ExtHostQuickOpen implements ExtHostQuickOpenShape {
return undefined;
}
return this._workspace.getWorkspaceFolders().filter(folder => folder.uri.toString() === selectedFolder.uri.toString())[0];
return this._workspace.getWorkspaceProvider().then(workspaceProvider => workspaceProvider.getWorkspaceFolders().filter(folder => folder.uri.toString() === selectedFolder.uri.toString())[0]);
});
}

View File

@@ -14,7 +14,7 @@ import { StopWatch } from 'vs/base/common/stopwatch';
import * as strings from 'vs/base/common/strings';
import { URI } from 'vs/base/common/uri';
import { compareItemsByScore, IItemAccessor, prepareQuery, ScorerCache } from 'vs/base/parts/quickopen/common/quickOpenScorer';
import { ICachedSearchStats, IFileIndexProviderStats, IFileMatch, IFileQuery, IFileSearchStats, IFolderQuery, ISearchCompleteStats } from 'vs/platform/search/common/search';
import { ICachedSearchStats, IFileIndexProviderStats, IFileMatch, IFileQuery, IFileSearchStats, IFolderQuery, ISearchCompleteStats } from 'vs/workbench/services/search/common/search';
import { IDirectoryEntry, IDirectoryTree, IInternalFileMatch } from 'vs/workbench/services/search/node/fileSearchManager';
import { QueryGlobTester, resolvePatternsForProvider } from 'vs/workbench/services/search/node/search';
import * as vscode from 'vscode';

View File

@@ -8,7 +8,7 @@ import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { URI, UriComponents } from 'vs/base/common/uri';
import * as extfs from 'vs/base/node/extfs';
import { ILogService } from 'vs/platform/log/common/log';
import { IFileQuery, IFolderQuery, IRawFileQuery, IRawQuery, IRawTextQuery, ISearchCompleteStats, ITextQuery } from 'vs/platform/search/common/search';
import { IFileQuery, IFolderQuery, IRawFileQuery, IRawQuery, IRawTextQuery, ISearchCompleteStats, ITextQuery } from 'vs/workbench/services/search/common/search';
import { FileIndexSearchManager } from 'vs/workbench/api/node/extHostSearch.fileIndex';
import { FileSearchManager } from 'vs/workbench/services/search/node/fileSearchManager';
import { SearchService } from 'vs/workbench/services/search/node/rawSearchService';
@@ -35,12 +35,12 @@ export class ExtHostSearch implements ExtHostSearchShape {
private _handlePool: number = 0;
private _internalFileSearchHandle: number;
private _internalFileSearchProvider: SearchService;
private _internalFileSearchProvider: SearchService | null;
private _fileSearchManager: FileSearchManager;
private _fileIndexSearchManager: FileIndexSearchManager;
constructor(mainContext: IMainContext, private _schemeTransformer: ISchemeTransformer, private _logService: ILogService, private _extfs = extfs) {
constructor(mainContext: IMainContext, private _schemeTransformer: ISchemeTransformer | null, private _logService: ILogService, private _extfs = extfs) {
this._proxy = mainContext.getProxy(MainContext.MainThreadSearch);
this._fileSearchManager = new FileSearchManager();
this._fileIndexSearchManager = new FileIndexSearchManager();
@@ -124,6 +124,10 @@ export class ExtHostSearch implements ExtHostSearchShape {
}, token);
} else {
const indexProvider = this._fileIndexProvider.get(handle);
if (!indexProvider) {
throw new Error('unknown provider: ' + handle);
}
return this._fileIndexSearchManager.fileSearch(query, indexProvider, batch => {
this._proxy.$handleFileMatch(handle, session, batch.map(p => p.resource));
}, token);
@@ -147,7 +151,11 @@ export class ExtHostSearch implements ExtHostSearchShape {
}
};
return this._internalFileSearchProvider.doFileSearch(rawQuery, onResult, token);
if (!this._internalFileSearchProvider) {
throw new Error('No internal file search handler');
}
return <Promise<ISearchCompleteStats>>this._internalFileSearchProvider.doFileSearch(rawQuery, onResult, token);
}
$clearCache(cacheKey: string): Promise<void> {
@@ -163,8 +171,8 @@ export class ExtHostSearch implements ExtHostSearchShape {
$provideTextSearchResults(handle: number, session: number, rawQuery: IRawTextQuery, token: CancellationToken): Promise<ISearchCompleteStats> {
const provider = this._textSearchProvider.get(handle);
if (!provider.provideTextSearchResults) {
return Promise.resolve(undefined);
if (!provider || !provider.provideTextSearchResults) {
throw new Error(`Unknown provider ${handle}`);
}
const query = reviveQuery(rawQuery);

View File

@@ -16,13 +16,13 @@ import { IExtensionDescription } from 'vs/workbench/services/extensions/common/e
import { MainContext, MainThreadTaskShape, ExtHostTaskShape, IMainContext } from 'vs/workbench/api/node/extHost.protocol';
import * as types from 'vs/workbench/api/node/extHostTypes';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { ExtHostWorkspace, ExtHostWorkspaceProvider } from 'vs/workbench/api/node/extHostWorkspace';
import * as vscode from 'vscode';
import {
TaskDefinitionDTO, TaskExecutionDTO, TaskPresentationOptionsDTO,
ProcessExecutionOptionsDTO, ProcessExecutionDTO,
ShellExecutionOptionsDTO, ShellExecutionDTO,
ExtensionCallbackExecutionDTO,
CustomTaskExecutionDTO,
TaskDTO, TaskHandleDTO, TaskFilterDTO, TaskProcessStartedDTO, TaskProcessEndedDTO, TaskSystemInfoDTO, TaskSetDTO
} from '../shared/tasks';
import { ExtHostVariableResolverService } from 'vs/workbench/api/node/extHostDebugService';
@@ -79,7 +79,7 @@ namespace ProcessExecutionOptionsDTO {
}
namespace ProcessExecutionDTO {
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | ExtensionCallbackExecutionDTO): value is ProcessExecutionDTO {
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomTaskExecutionDTO): value is ProcessExecutionDTO {
let candidate = value as ProcessExecutionDTO;
return candidate && !!candidate.process;
}
@@ -120,7 +120,7 @@ namespace ShellExecutionOptionsDTO {
}
namespace ShellExecutionDTO {
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | ExtensionCallbackExecutionDTO): value is ShellExecutionDTO {
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomTaskExecutionDTO): value is ShellExecutionDTO {
let candidate = value as ShellExecutionDTO;
return candidate && (!!candidate.commandLine || !!candidate.command);
}
@@ -153,15 +153,15 @@ namespace ShellExecutionDTO {
}
}
namespace ExtensionCallbackExecutionDTO {
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | ExtensionCallbackExecutionDTO): value is ExtensionCallbackExecutionDTO {
let candidate = value as ExtensionCallbackExecutionDTO;
return candidate && candidate.extensionCallback === 'extensionCallback';
namespace CustomTaskExecutionDTO {
export function is(value: ShellExecutionDTO | ProcessExecutionDTO | CustomTaskExecutionDTO): value is CustomTaskExecutionDTO {
let candidate = value as CustomTaskExecutionDTO;
return candidate && candidate.customTaskExecution === 'customTaskExecution';
}
export function from(value: vscode.ExtensionCallbackExecution): ExtensionCallbackExecutionDTO {
export function from(value: vscode.CustomTaskExecution): CustomTaskExecutionDTO {
return {
extensionCallback: 'extensionCallback'
customTaskExecution: 'customTaskExecution'
};
}
}
@@ -199,13 +199,13 @@ namespace TaskDTO {
if (value === undefined || value === null) {
return undefined;
}
let execution: ShellExecutionDTO | ProcessExecutionDTO | ExtensionCallbackExecutionDTO;
let execution: ShellExecutionDTO | ProcessExecutionDTO | CustomTaskExecutionDTO;
if (value.execution instanceof types.ProcessExecution) {
execution = ProcessExecutionDTO.from(value.execution);
} else if (value.execution instanceof types.ShellExecution) {
execution = ShellExecutionDTO.from(value.execution);
} else if ((<vscode.TaskWithExtensionCallback>value).executionWithExtensionCallback && (<vscode.TaskWithExtensionCallback>value).executionWithExtensionCallback instanceof types.ExtensionCallbackExecution) {
execution = ExtensionCallbackExecutionDTO.from(<types.ExtensionCallbackExecution>(<vscode.TaskWithExtensionCallback>value).executionWithExtensionCallback);
} else if ((<vscode.TaskWithCustomTaskExecution>value).executionWithExtensionCallback && (<vscode.TaskWithCustomTaskExecution>value).executionWithExtensionCallback instanceof types.CustomTaskExecution) {
execution = CustomTaskExecutionDTO.from(<types.CustomTaskExecution>(<vscode.TaskWithCustomTaskExecution>value).executionWithExtensionCallback);
}
let definition: TaskDefinitionDTO = TaskDefinitionDTO.from(value.definition);
@@ -243,7 +243,7 @@ namespace TaskDTO {
};
return result;
}
export function to(value: TaskDTO, workspace: ExtHostWorkspace): types.Task {
export function to(value: TaskDTO, workspace: ExtHostWorkspaceProvider): types.Task {
if (value === undefined || value === null) {
return undefined;
}
@@ -320,8 +320,8 @@ class TaskExecutionImpl implements vscode.TaskExecution {
}
namespace TaskExecutionDTO {
export function to(value: TaskExecutionDTO, tasks: ExtHostTask): vscode.TaskExecution {
return new TaskExecutionImpl(tasks, value.id, TaskDTO.to(value.task, tasks.extHostWorkspace));
export function to(value: TaskExecutionDTO, tasks: ExtHostTask, workspaceProvider: ExtHostWorkspaceProvider): vscode.TaskExecution {
return new TaskExecutionImpl(tasks, value.id, TaskDTO.to(value.task, workspaceProvider));
}
export function from(value: vscode.TaskExecution): TaskExecutionDTO {
return {
@@ -344,7 +344,7 @@ class ExtensionCallbackExecutionData implements IDisposable {
private terminalId?: number;
constructor(
private readonly callbackData: vscode.ExtensionCallbackExecution,
private readonly callbackData: vscode.CustomTaskExecution,
private readonly terminalService: ExtHostTerminalService) {
}
@@ -449,10 +449,6 @@ export class ExtHostTask implements ExtHostTaskShape {
this._activeExtensionCallbacks = new Map<string, ExtensionCallbackExecutionData>();
}
public get extHostWorkspace(): ExtHostWorkspace {
return this._workspaceService;
}
public registerTaskProvider(extension: IExtensionDescription, provider: vscode.TaskProvider): vscode.Disposable {
if (!provider) {
return new types.Disposable(() => { });
@@ -471,10 +467,11 @@ export class ExtHostTask implements ExtHostTaskShape {
}
public fetchTasks(filter?: vscode.TaskFilter): Promise<vscode.Task[]> {
return this._proxy.$fetchTasks(TaskFilterDTO.from(filter)).then((values) => {
return this._proxy.$fetchTasks(TaskFilterDTO.from(filter)).then(async (values) => {
let result: vscode.Task[] = [];
const workspaceProvider = await this._workspaceService.getWorkspaceProvider();
for (let value of values) {
let task = TaskDTO.to(value, this._workspaceService);
let task = TaskDTO.to(value, workspaceProvider);
if (task) {
result.push(task);
}
@@ -483,17 +480,18 @@ export class ExtHostTask implements ExtHostTaskShape {
});
}
public executeTask(extension: IExtensionDescription, task: vscode.Task): Promise<vscode.TaskExecution> {
public async executeTask(extension: IExtensionDescription, task: vscode.Task): Promise<vscode.TaskExecution> {
const workspaceProvider = await this._workspaceService.getWorkspaceProvider();
let tTask = (task as types.Task);
// We have a preserved ID. So the task didn't change.
if (tTask._id !== undefined) {
return this._proxy.$executeTask(TaskHandleDTO.from(tTask)).then(value => this.getTaskExecution(value, task));
return this._proxy.$executeTask(TaskHandleDTO.from(tTask)).then(value => this.getTaskExecution(value, workspaceProvider, task));
} else {
let dto = TaskDTO.from(task, extension);
if (dto === undefined) {
return Promise.reject(new Error('Task is not valid'));
}
return this._proxy.$executeTask(dto).then(value => this.getTaskExecution(value, task));
return this._proxy.$executeTask(dto).then(value => this.getTaskExecution(value, workspaceProvider, task));
}
}
@@ -514,7 +512,7 @@ export class ExtHostTask implements ExtHostTaskShape {
return this._onDidExecuteTask.event;
}
public $onDidStartTask(execution: TaskExecutionDTO, terminalId: number): void {
public async $onDidStartTask(execution: TaskExecutionDTO, terminalId: number): Promise<void> {
// Once a terminal is spun up for the extension callback task execution
// this event will be fired.
// At that point, we need to actually start the callback, but
@@ -534,8 +532,9 @@ export class ExtHostTask implements ExtHostTaskShape {
extensionCallback.startCallback(terminalId);
}
const workspaceProvider = await this._workspaceService.getWorkspaceProvider();
this._onDidExecuteTask.fire({
execution: this.getTaskExecution(execution)
execution: this.getTaskExecution(execution, workspaceProvider)
});
}
@@ -543,8 +542,9 @@ export class ExtHostTask implements ExtHostTaskShape {
return this._onDidTerminateTask.event;
}
public $OnDidEndTask(execution: TaskExecutionDTO): void {
const _execution = this.getTaskExecution(execution);
public async $OnDidEndTask(execution: TaskExecutionDTO): Promise<void> {
const workspaceProvider = await this._workspaceService.getWorkspaceProvider();
const _execution = this.getTaskExecution(execution, workspaceProvider);
this._taskExecutions.delete(execution.id);
this.extensionCallbackTaskComplete(execution);
this._onDidTerminateTask.fire({
@@ -556,8 +556,9 @@ export class ExtHostTask implements ExtHostTaskShape {
return this._onDidTaskProcessStarted.event;
}
public $onDidStartTaskProcess(value: TaskProcessStartedDTO): void {
const execution = this.getTaskExecution(value.id);
public async $onDidStartTaskProcess(value: TaskProcessStartedDTO): Promise<void> {
const workspaceProvider = await this._workspaceService.getWorkspaceProvider();
const execution = this.getTaskExecution(value.id, workspaceProvider);
if (execution) {
this._onDidTaskProcessStarted.fire({
execution: execution,
@@ -570,8 +571,9 @@ export class ExtHostTask implements ExtHostTaskShape {
return this._onDidTaskProcessEnded.event;
}
public $onDidEndTaskProcess(value: TaskProcessEndedDTO): void {
const execution = this.getTaskExecution(value.id);
public async $onDidEndTaskProcess(value: TaskProcessEndedDTO): Promise<void> {
const workspaceProvider = await this._workspaceService.getWorkspaceProvider();
const execution = this.getTaskExecution(value.id, workspaceProvider);
if (execution) {
this._onDidTaskProcessEnded.fire({
execution: execution,
@@ -610,11 +612,11 @@ export class ExtHostTask implements ExtHostTaskShape {
const taskDTO: TaskDTO = TaskDTO.from(task, handler.extension);
taskDTOs.push(taskDTO);
if (ExtensionCallbackExecutionDTO.is(taskDTO.execution)) {
if (CustomTaskExecutionDTO.is(taskDTO.execution)) {
taskIdPromises.push(new Promise((resolve) => {
// The ID is calculated on the main thread task side, so, let's call into it here.
this._proxy.$createTaskId(taskDTO).then((taskId) => {
this._providedExtensionCallbacks.set(taskId, new ExtensionCallbackExecutionData(<vscode.ExtensionCallbackExecution>(<vscode.TaskWithExtensionCallback>task).executionWithExtensionCallback, this._terminalService));
this._providedExtensionCallbacks.set(taskId, new ExtensionCallbackExecutionData(<vscode.CustomTaskExecution>(<vscode.TaskWithCustomTaskExecution>task).executionWithExtensionCallback, this._terminalService));
resolve();
});
}));
@@ -638,13 +640,14 @@ export class ExtHostTask implements ExtHostTaskShape {
public async $resolveVariables(uriComponents: UriComponents, toResolve: { process?: { name: string; cwd?: string; path?: string }, variables: string[] }): Promise<{ process?: string, variables: { [key: string]: string; } }> {
const configProvider = await this._configurationService.getConfigProvider();
const workspaceProvider = await this._workspaceService.getWorkspaceProvider();
let uri: URI = URI.revive(uriComponents);
let result = {
process: undefined as string,
variables: Object.create(null)
};
let workspaceFolder = this._workspaceService.resolveWorkspaceFolder(uri);
let resolver = new ExtHostVariableResolverService(this._workspaceService, this._editorService, configProvider);
let workspaceFolder = workspaceProvider.resolveWorkspaceFolder(uri);
let resolver = new ExtHostVariableResolverService(workspaceProvider, this._editorService, configProvider);
let ws: IWorkspaceFolder = {
uri: workspaceFolder.uri,
name: workspaceFolder.name,
@@ -677,7 +680,7 @@ export class ExtHostTask implements ExtHostTaskShape {
return this._handleCounter++;
}
private getTaskExecution(execution: TaskExecutionDTO | string, task?: vscode.Task): TaskExecutionImpl {
private getTaskExecution(execution: TaskExecutionDTO | string, workspaceProvider: ExtHostWorkspaceProvider, task?: vscode.Task): TaskExecutionImpl {
if (typeof execution === 'string') {
return this._taskExecutions.get(execution);
}
@@ -686,7 +689,7 @@ export class ExtHostTask implements ExtHostTaskShape {
if (result) {
return result;
}
result = new TaskExecutionImpl(this, execution.id, task ? task : TaskDTO.to(execution.task, this._workspaceService));
result = new TaskExecutionImpl(this, execution.id, task ? task : TaskDTO.to(execution.task, workspaceProvider));
this._taskExecutions.set(execution.id, result);
return result;
}

View File

@@ -188,7 +188,7 @@ export class ExtHostTerminal extends BaseExtHostTerminal implements vscode.Termi
}
}
export class ExtHostTerminalRenderer extends BaseExtHostTerminal implements vscode.TerminalRenderer, vscode.AnsiRenderer {
export class ExtHostTerminalRenderer extends BaseExtHostTerminal implements vscode.TerminalRenderer {
public get name(): string { return this._name; }
public set name(newName: string) {
this._name = newName;

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { Emitter, Event } from 'vs/base/common/event';
import * as arrays from 'vs/base/common/arrays';
import { ExtHostEditorsShape, IEditorPropertiesChangeData, IMainContext, ITextDocumentShowOptions, ITextEditorPositionData, MainContext, MainThreadTextEditorsShape } from 'vs/workbench/api/node/extHost.protocol';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumentsAndEditors';
import { ExtHostTextEditor, TextEditorDecorationType } from 'vs/workbench/api/node/extHostTextEditor';
@@ -42,7 +43,7 @@ export class ExtHostEditors implements ExtHostEditorsShape {
this._extHostDocumentsAndEditors.onDidChangeActiveTextEditor(e => this._onDidChangeActiveTextEditor.fire(e));
}
getActiveTextEditor(): ExtHostTextEditor {
getActiveTextEditor(): ExtHostTextEditor | undefined {
return this._extHostDocumentsAndEditors.activeEditor();
}
@@ -106,7 +107,7 @@ export class ExtHostEditors implements ExtHostEditorsShape {
textEditor._acceptSelections(selections);
}
if (data.visibleRanges) {
const visibleRanges = data.visibleRanges.map(TypeConverters.Range.to);
const visibleRanges = arrays.coalesce(data.visibleRanges.map(TypeConverters.Range.to));
textEditor._acceptVisibleRanges(visibleRanges);
}
@@ -127,7 +128,7 @@ export class ExtHostEditors implements ExtHostEditorsShape {
});
}
if (data.visibleRanges) {
const visibleRanges = data.visibleRanges.map(TypeConverters.Range.to);
const visibleRanges = arrays.coalesce(data.visibleRanges.map(TypeConverters.Range.to));
this._onDidChangeTextEditorVisibleRanges.fire({
textEditor,
visibleRanges

View File

@@ -28,6 +28,7 @@ import * as marked from 'vs/base/common/marked/marked';
import { parse } from 'vs/base/common/marshalling';
import { cloneAndChange } from 'vs/base/common/objects';
import { LogLevel as _MainLogLevel } from 'vs/platform/log/common/log';
import { coalesce } from 'vs/base/common/arrays';
export interface PositionLike {
line: number;
@@ -64,7 +65,10 @@ export namespace Selection {
}
export namespace Range {
export function from(range: RangeLike): IRange {
export function from(range: undefined): undefined;
export function from(range: RangeLike): IRange;
export function from(range: RangeLike | undefined): IRange | undefined;
export function from(range: RangeLike | undefined): IRange | undefined {
if (!range) {
return undefined;
}
@@ -77,7 +81,10 @@ export namespace Range {
};
}
export function to(range: IRange): types.Range {
export function to(range: undefined): types.Range;
export function to(range: IRange): types.Range;
export function to(range: IRange | undefined): types.Range | undefined;
export function to(range: IRange | undefined): types.Range | undefined {
if (!range) {
return undefined;
}
@@ -96,7 +103,7 @@ export namespace Position {
}
export namespace DiagnosticTag {
export function from(value: vscode.DiagnosticTag): MarkerTag {
export function from(value: vscode.DiagnosticTag): MarkerTag | undefined {
switch (value) {
case types.DiagnosticTag.Unnecessary:
return MarkerTag.Unnecessary;
@@ -114,7 +121,7 @@ export namespace Diagnostic {
code: isString(value.code) || isNumber(value.code) ? String(value.code) : undefined,
severity: DiagnosticSeverity.from(value.severity),
relatedInformation: value.relatedInformation && value.relatedInformation.map(DiagnosticRelatedInformation.from),
tags: Array.isArray(value.tags) ? value.tags.map(DiagnosticTag.from) : undefined,
tags: Array.isArray(value.tags) ? coalesce(value.tags.map(DiagnosticTag.from)) : undefined,
};
}
}
@@ -175,12 +182,12 @@ export namespace ViewColumn {
return ACTIVE_GROUP; // default is always the active group
}
export function to(position?: EditorViewColumn): vscode.ViewColumn {
export function to(position: EditorViewColumn): vscode.ViewColumn {
if (typeof position === 'number' && position >= 0) {
return position + 1; // adjust to index (ViewColumn.ONE => 1)
}
return undefined;
throw new Error(`invalid 'EditorViewColumn'`);
}
}
@@ -226,13 +233,15 @@ export namespace MarkdownString {
}
// extract uris into a separate object
res.uris = Object.create(null);
const resUris: { [href: string]: UriComponents } = Object.create(null);
res.uris = resUris;
let renderer = new marked.Renderer();
renderer.image = renderer.link = (href: string): string => {
try {
let uri = URI.parse(href, true);
uri = uri.with({ query: _uriMassage(uri.query, res.uris) });
res.uris[href] = uri;
uri = uri.with({ query: _uriMassage(uri.query, resUris) });
resUris[href] = uri;
} catch (e) {
// ignore
}
@@ -284,10 +293,12 @@ export namespace MarkdownString {
export function fromRangeOrRangeWithMessage(ranges: vscode.Range[] | vscode.DecorationOptions[]): IDecorationOptions[] {
if (isDecorationOptionsArr(ranges)) {
return ranges.map(r => {
return ranges.map((r): IDecorationOptions => {
return {
range: Range.from(r.range),
hoverMessage: Array.isArray(r.hoverMessage) ? MarkdownString.fromMany(r.hoverMessage) : r.hoverMessage && MarkdownString.from(r.hoverMessage),
hoverMessage: Array.isArray(r.hoverMessage)
? MarkdownString.fromMany(r.hoverMessage)
: (r.hoverMessage ? MarkdownString.from(r.hoverMessage) : undefined),
renderOptions: <any> /* URI vs Uri */r.renderOptions
};
});
@@ -318,7 +329,7 @@ export namespace ThemableDecorationAttachmentRenderOptions {
}
return {
contentText: options.contentText,
contentIconPath: pathOrURIToURI(options.contentIconPath),
contentIconPath: options.contentIconPath ? pathOrURIToURI(options.contentIconPath) : undefined,
border: options.border,
borderColor: <string | types.ThemeColor>options.borderColor,
fontStyle: options.fontStyle,
@@ -357,11 +368,11 @@ export namespace ThemableDecorationRenderOptions {
color: <string | types.ThemeColor>options.color,
opacity: options.opacity,
letterSpacing: options.letterSpacing,
gutterIconPath: pathOrURIToURI(options.gutterIconPath),
gutterIconPath: options.gutterIconPath ? pathOrURIToURI(options.gutterIconPath) : undefined,
gutterIconSize: options.gutterIconSize,
overviewRulerColor: <string | types.ThemeColor>options.overviewRulerColor,
before: ThemableDecorationAttachmentRenderOptions.from(options.before),
after: ThemableDecorationAttachmentRenderOptions.from(options.after),
before: options.before ? ThemableDecorationAttachmentRenderOptions.from(options.before) : undefined,
after: options.after ? ThemableDecorationAttachmentRenderOptions.from(options.after) : undefined,
};
}
}
@@ -388,10 +399,10 @@ export namespace DecorationRenderOptions {
export function from(options: vscode.DecorationRenderOptions): IDecorationRenderOptions {
return {
isWholeLine: options.isWholeLine,
rangeBehavior: DecorationRangeBehavior.from(options.rangeBehavior),
rangeBehavior: options.rangeBehavior ? DecorationRangeBehavior.from(options.rangeBehavior) : undefined,
overviewRulerLane: options.overviewRulerLane,
light: ThemableDecorationRenderOptions.from(options.light),
dark: ThemableDecorationRenderOptions.from(options.dark),
light: options.light ? ThemableDecorationRenderOptions.from(options.light) : undefined,
dark: options.dark ? ThemableDecorationRenderOptions.from(options.dark) : undefined,
backgroundColor: <string | types.ThemeColor>options.backgroundColor,
outline: options.outline,
@@ -411,11 +422,11 @@ export namespace DecorationRenderOptions {
color: <string | types.ThemeColor>options.color,
opacity: options.opacity,
letterSpacing: options.letterSpacing,
gutterIconPath: pathOrURIToURI(options.gutterIconPath),
gutterIconPath: options.gutterIconPath ? pathOrURIToURI(options.gutterIconPath) : undefined,
gutterIconSize: options.gutterIconSize,
overviewRulerColor: <string | types.ThemeColor>options.overviewRulerColor,
before: ThemableDecorationAttachmentRenderOptions.from(options.before),
after: ThemableDecorationAttachmentRenderOptions.from(options.after),
before: options.before ? ThemableDecorationAttachmentRenderOptions.from(options.before) : undefined,
after: options.after ? ThemableDecorationAttachmentRenderOptions.from(options.after) : undefined,
};
}
}
@@ -432,7 +443,7 @@ export namespace TextEdit {
export function to(edit: modes.TextEdit): types.TextEdit {
const result = new types.TextEdit(Range.to(edit.range), edit.text);
result.newEol = EndOfLine.to(edit.eol);
result.newEol = (typeof edit.eol === 'undefined' ? undefined : EndOfLine.to(edit.eol))!;
return result;
}
}
@@ -446,7 +457,7 @@ export namespace WorkspaceEdit {
const [uri, uriOrEdits] = entry;
if (Array.isArray(uriOrEdits)) {
// text edits
const doc = documents ? documents.getDocument(uri.toString()) : undefined;
const doc = documents && uri ? documents.getDocument(uri.toString()) : undefined;
result.edits.push(<ResourceTextEditDto>{ resource: uri, modelVersionId: doc && doc.version, edits: uriOrEdits.map(TextEdit.from) });
} else {
// resource edits
@@ -648,7 +659,7 @@ export namespace CompletionContext {
export namespace CompletionItemKind {
export function from(kind: types.CompletionItemKind): modes.CompletionItemKind {
export function from(kind: types.CompletionItemKind | undefined): modes.CompletionItemKind {
switch (kind) {
case types.CompletionItemKind.Method: return modes.CompletionItemKind.Method;
case types.CompletionItemKind.Function: return modes.CompletionItemKind.Function;
@@ -724,9 +735,9 @@ export namespace CompletionItem {
result.preselect = suggestion.preselect;
result.commitCharacters = suggestion.commitCharacters;
result.range = Range.to(suggestion.range);
result.keepWhitespace = Boolean(suggestion.insertTextRules & modes.CompletionItemInsertTextRule.KeepWhitespace);
result.keepWhitespace = typeof suggestion.insertTextRules === 'undefined' ? false : Boolean(suggestion.insertTextRules & modes.CompletionItemInsertTextRule.KeepWhitespace);
// 'inserText'-logic
if (suggestion.insertTextRules & modes.CompletionItemInsertTextRule.InsertAsSnippet) {
if (typeof suggestion.insertTextRules !== 'undefined' && suggestion.insertTextRules & modes.CompletionItemInsertTextRule.InsertAsSnippet) {
result.insertText = new types.SnippetString(suggestion.insertText);
} else {
result.insertText = suggestion.insertText;
@@ -742,7 +753,7 @@ export namespace ParameterInformation {
export function from(info: types.ParameterInformation): modes.ParameterInformation {
return {
label: info.label,
documentation: MarkdownString.fromStrict(info.documentation)
documentation: info.documentation ? MarkdownString.fromStrict(info.documentation) : undefined
};
}
export function to(info: modes.ParameterInformation): types.ParameterInformation {
@@ -758,7 +769,7 @@ export namespace SignatureInformation {
export function from(info: types.SignatureInformation): modes.SignatureInformation {
return {
label: info.label,
documentation: MarkdownString.fromStrict(info.documentation),
documentation: info.documentation ? MarkdownString.fromStrict(info.documentation) : undefined,
parameters: info.parameters && info.parameters.map(ParameterInformation.from)
};
}
@@ -801,7 +812,7 @@ export namespace DocumentLink {
}
export function to(link: modes.ILink): vscode.DocumentLink {
return new types.DocumentLink(Range.to(link.range), link.url && URI.parse(link.url));
return new types.DocumentLink(Range.to(link.range), link.url ? URI.parse(link.url) : undefined);
}
}
@@ -877,7 +888,7 @@ export namespace TextDocumentSaveReason {
export namespace EndOfLine {
export function from(eol: vscode.EndOfLine): EndOfLineSequence {
export function from(eol: vscode.EndOfLine): EndOfLineSequence | undefined {
if (eol === types.EndOfLine.CRLF) {
return EndOfLineSequence.CRLF;
} else if (eol === types.EndOfLine.LF) {
@@ -886,7 +897,7 @@ export namespace EndOfLine {
return undefined;
}
export function to(eol: EndOfLineSequence): vscode.EndOfLine {
export function to(eol: EndOfLineSequence): vscode.EndOfLine | undefined {
if (eol === EndOfLineSequence.CRLF) {
return types.EndOfLine.CRLF;
} else if (eol === EndOfLineSequence.LF) {
@@ -903,7 +914,7 @@ export namespace ProgressLocation {
case types.ProgressLocation.Window: return MainProgressLocation.Window;
case types.ProgressLocation.Notification: return MainProgressLocation.Notification;
}
return undefined;
throw new Error(`Unknown 'ProgressLocation'`);
}
}
@@ -935,7 +946,7 @@ export namespace FoldingRangeKind {
export namespace TextEditorOptions {
export function from(options?: vscode.TextDocumentShowOptions): ITextEditorOptions {
export function from(options?: vscode.TextDocumentShowOptions): ITextEditorOptions | undefined {
if (options) {
return {
pinned: typeof options.preview === 'boolean' ? !options.preview : undefined,
@@ -975,7 +986,10 @@ export namespace GlobPattern {
export namespace LanguageSelector {
export function from(selector: vscode.DocumentSelector): languageSelector.LanguageSelector {
export function from(selector: undefined): undefined;
export function from(selector: vscode.DocumentSelector): languageSelector.LanguageSelector;
export function from(selector: vscode.DocumentSelector | undefined): languageSelector.LanguageSelector | undefined;
export function from(selector: vscode.DocumentSelector | undefined): languageSelector.LanguageSelector | undefined {
if (!selector) {
return undefined;
} else if (Array.isArray(selector)) {
@@ -986,7 +1000,7 @@ export namespace LanguageSelector {
return <languageSelector.LanguageFilter>{
language: selector.language,
scheme: selector.scheme,
pattern: GlobPattern.from(selector.pattern),
pattern: typeof selector.pattern === 'undefined' ? undefined : GlobPattern.from(selector.pattern),
exclusive: selector.exclusive
};
}

View File

@@ -16,6 +16,18 @@ import { generateUuid } from 'vs/base/common/uuid';
import * as vscode from 'vscode';
function es5ClassCompat(target: Function): any {
///@ts-ignore
function _() { return Reflect.construct(target, arguments, this.constructor); }
Object.defineProperty(_, 'name', Object.getOwnPropertyDescriptor(target, 'name')!);
///@ts-ignore
Object.setPrototypeOf(_, target);
///@ts-ignore
Object.setPrototypeOf(_.prototype, target.prototype);
return _;
}
@es5ClassCompat
export class Disposable {
static from(...inDisposables: { dispose(): any }[]): Disposable {
@@ -46,6 +58,7 @@ export class Disposable {
}
}
@es5ClassCompat
export class Position {
static Min(...positions: Position[]): Position {
@@ -217,6 +230,7 @@ export class Position {
}
}
@es5ClassCompat
export class Range {
static isRange(thing: any): thing is vscode.Range {
@@ -351,6 +365,7 @@ export class Range {
}
}
@es5ClassCompat
export class Selection extends Range {
static isSelection(thing: any): thing is Selection {
@@ -421,6 +436,7 @@ export enum EndOfLine {
CRLF = 2
}
@es5ClassCompat
export class TextEdit {
static isTextEdit(thing: any): thing is TextEdit {
@@ -524,6 +540,7 @@ export interface IFileTextEdit {
edit: TextEdit;
}
@es5ClassCompat
export class WorkspaceEdit implements vscode.WorkspaceEdit {
private _edits = new Array<IFileOperation | IFileTextEdit>();
@@ -627,6 +644,7 @@ export class WorkspaceEdit implements vscode.WorkspaceEdit {
}
}
@es5ClassCompat
export class SnippetString {
static isSnippetString(thing: any): thing is SnippetString {
@@ -720,6 +738,7 @@ export enum DiagnosticSeverity {
Error = 0
}
@es5ClassCompat
export class Location {
static isLocation(thing: any): thing is Location {
@@ -758,6 +777,7 @@ export class Location {
}
}
@es5ClassCompat
export class DiagnosticRelatedInformation {
static is(thing: any): thing is DiagnosticRelatedInformation {
@@ -791,6 +811,7 @@ export class DiagnosticRelatedInformation {
}
}
@es5ClassCompat
export class Diagnostic {
range: Range;
@@ -835,6 +856,7 @@ export class Diagnostic {
}
}
@es5ClassCompat
export class Hover {
public contents: vscode.MarkdownString[] | vscode.MarkedString[];
@@ -864,6 +886,7 @@ export enum DocumentHighlightKind {
Write = 2
}
@es5ClassCompat
export class DocumentHighlight {
range: Range;
@@ -911,6 +934,7 @@ export enum SymbolKind {
TypeParameter = 25
}
@es5ClassCompat
export class SymbolInformation {
static validate(candidate: SymbolInformation): void {
@@ -924,9 +948,9 @@ export class SymbolInformation {
kind: SymbolKind;
containerName: string | undefined;
constructor(name: string, kind: SymbolKind, containerName: string, location: Location);
constructor(name: string, kind: SymbolKind, containerName: string | undefined, location: Location);
constructor(name: string, kind: SymbolKind, range: Range, uri?: URI, containerName?: string);
constructor(name: string, kind: SymbolKind, rangeOrContainer: string | Range, locationOrUri?: Location | URI, containerName?: string) {
constructor(name: string, kind: SymbolKind, rangeOrContainer: string | undefined | Range, locationOrUri?: Location | URI, containerName?: string) {
this.name = name;
this.kind = kind;
this.containerName = containerName;
@@ -954,6 +978,7 @@ export class SymbolInformation {
}
}
@es5ClassCompat
export class DocumentSymbol {
static validate(candidate: DocumentSymbol): void {
@@ -993,6 +1018,7 @@ export enum CodeActionTrigger {
Manual = 2,
}
@es5ClassCompat
export class CodeAction {
title: string;
@@ -1011,6 +1037,7 @@ export class CodeAction {
}
@es5ClassCompat
export class CodeActionKind {
private static readonly sep = '.';
@@ -1041,6 +1068,7 @@ export class CodeActionKind {
}
}
@es5ClassCompat
export class SelectionRangeKind {
private static readonly _sep = '.';
@@ -1060,6 +1088,7 @@ export class SelectionRangeKind {
}
}
@es5ClassCompat
export class SelectionRange {
kind: SelectionRangeKind;
@@ -1072,6 +1101,7 @@ export class SelectionRange {
}
@es5ClassCompat
export class CodeLens {
range: Range;
@@ -1088,6 +1118,7 @@ export class CodeLens {
}
}
@es5ClassCompat
export class MarkdownString {
value: string;
@@ -1118,6 +1149,7 @@ export class MarkdownString {
}
}
@es5ClassCompat
export class ParameterInformation {
label: string | [number, number];
@@ -1129,6 +1161,7 @@ export class ParameterInformation {
}
}
@es5ClassCompat
export class SignatureInformation {
label: string;
@@ -1142,6 +1175,7 @@ export class SignatureInformation {
}
}
@es5ClassCompat
export class SignatureHelp {
signatures: SignatureInformation[];
@@ -1166,8 +1200,8 @@ export enum CompletionTriggerKind {
}
export interface CompletionContext {
triggerKind: CompletionTriggerKind;
triggerCharacter: string;
readonly triggerKind: CompletionTriggerKind;
readonly triggerCharacter?: string;
}
export enum CompletionItemKind {
@@ -1198,19 +1232,20 @@ export enum CompletionItemKind {
TypeParameter = 24
}
@es5ClassCompat
export class CompletionItem implements vscode.CompletionItem {
label: string;
kind: CompletionItemKind | undefined;
detail: string;
documentation: string | MarkdownString;
sortText: string;
filterText: string;
preselect: boolean;
detail?: string;
documentation?: string | MarkdownString;
sortText?: string;
filterText?: string;
preselect?: boolean;
insertText: string | SnippetString;
keepWhitespace?: boolean;
range: Range;
commitCharacters: string[];
commitCharacters?: string[];
textEdit: TextEdit;
additionalTextEdits: TextEdit[];
command: vscode.Command;
@@ -1235,6 +1270,7 @@ export class CompletionItem implements vscode.CompletionItem {
}
}
@es5ClassCompat
export class CompletionList {
isIncomplete?: boolean;
@@ -1314,7 +1350,7 @@ export enum DecorationRangeBehavior {
}
export namespace TextEditorSelectionChangeKind {
export function fromValue(s: string) {
export function fromValue(s: string | undefined) {
switch (s) {
case 'keyboard': return TextEditorSelectionChangeKind.Keyboard;
case 'mouse': return TextEditorSelectionChangeKind.Mouse;
@@ -1324,13 +1360,14 @@ export namespace TextEditorSelectionChangeKind {
}
}
@es5ClassCompat
export class DocumentLink {
range: Range;
target: URI;
target?: URI;
constructor(range: Range, target: URI) {
constructor(range: Range, target: URI | undefined) {
if (target && !(target instanceof URI)) {
throw illegalArgument('target');
}
@@ -1342,6 +1379,7 @@ export class DocumentLink {
}
}
@es5ClassCompat
export class Color {
readonly red: number;
readonly green: number;
@@ -1358,6 +1396,7 @@ export class Color {
export type IColorFormat = string | { opaque: string, transparent: string };
@es5ClassCompat
export class ColorInformation {
range: Range;
@@ -1375,6 +1414,7 @@ export class ColorInformation {
}
}
@es5ClassCompat
export class ColorPresentation {
label: string;
textEdit?: TextEdit;
@@ -1416,6 +1456,7 @@ export enum TaskPanelKind {
New = 3
}
@es5ClassCompat
export class TaskGroup implements vscode.TaskGroup {
private _id: string;
@@ -1458,6 +1499,7 @@ export class TaskGroup implements vscode.TaskGroup {
}
}
@es5ClassCompat
export class ProcessExecution implements vscode.ProcessExecution {
private _process: string;
@@ -1530,6 +1572,7 @@ export class ProcessExecution implements vscode.ProcessExecution {
}
}
@es5ClassCompat
export class ShellExecution implements vscode.ShellExecution {
private _commandLine: string;
@@ -1626,32 +1669,33 @@ export enum TaskScope {
Workspace = 2
}
export class ExtensionCallbackExecution implements vscode.ExtensionCallbackExecution {
private _callback: (args: vscode.TerminalRenderer, cancellationToken: vscode.CancellationToken) => Thenable<void>;
export class CustomTaskExecution implements vscode.CustomTaskExecution {
private _callback: (args: vscode.TerminalRenderer, cancellationToken: vscode.CancellationToken) => Thenable<number | undefined>;
constructor(callback: (args: vscode.TerminalRenderer, cancellationToken: vscode.CancellationToken) => Thenable<void>) {
constructor(callback: (args: vscode.TerminalRenderer, cancellationToken: vscode.CancellationToken) => Thenable<number | undefined>) {
this._callback = callback;
}
public computeId(): string {
const hash = crypto.createHash('md5');
hash.update('extensionCallback');
hash.update('customTaskExecution');
hash.update(generateUuid());
return hash.digest('hex');
}
public set callback(value: (args: vscode.TerminalRenderer, cancellationToken: vscode.CancellationToken) => Thenable<void>) {
public set callback(value: (args: vscode.TerminalRenderer, cancellationToken: vscode.CancellationToken) => Thenable<number | undefined>) {
this._callback = value;
}
public get callback(): (args: vscode.TerminalRenderer, cancellationToken: vscode.CancellationToken) => Thenable<void> {
public get callback(): (args: vscode.TerminalRenderer, cancellationToken: vscode.CancellationToken) => Thenable<number | undefined> {
return this._callback;
}
}
export class Task implements vscode.TaskWithExtensionCallback {
@es5ClassCompat
export class Task implements vscode.TaskWithCustomTaskExecution {
private static ExtensionCallbackType: string = 'extensionCallback';
private static ExtensionCallbackType: string = 'customTaskExecution';
private static ProcessType: string = 'process';
private static ShellType: string = 'shell';
private static EmptyType: string = '$empty';
@@ -1661,7 +1705,7 @@ export class Task implements vscode.TaskWithExtensionCallback {
private _definition: vscode.TaskDefinition;
private _scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder | undefined;
private _name: string;
private _execution: ProcessExecution | ShellExecution | ExtensionCallbackExecution | undefined;
private _execution: ProcessExecution | ShellExecution | CustomTaskExecution | undefined;
private _problemMatchers: string[];
private _hasDefinedMatchers: boolean;
private _isBackground: boolean;
@@ -1670,8 +1714,8 @@ export class Task implements vscode.TaskWithExtensionCallback {
private _presentationOptions: vscode.TaskPresentationOptions;
private _runOptions: vscode.RunOptions;
constructor(definition: vscode.TaskDefinition, name: string, source: string, execution?: ProcessExecution | ShellExecution | ExtensionCallbackExecution, problemMatchers?: string | string[]);
constructor(definition: vscode.TaskDefinition, scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder, name: string, source: string, execution?: ProcessExecution | ShellExecution | ExtensionCallbackExecution, problemMatchers?: string | string[]);
constructor(definition: vscode.TaskDefinition, name: string, source: string, execution?: ProcessExecution | ShellExecution | CustomTaskExecution, problemMatchers?: string | string[]);
constructor(definition: vscode.TaskDefinition, scope: vscode.TaskScope.Global | vscode.TaskScope.Workspace | vscode.WorkspaceFolder, name: string, source: string, execution?: ProcessExecution | ShellExecution | CustomTaskExecution, problemMatchers?: string | string[]);
constructor(definition: vscode.TaskDefinition, arg2: string | (vscode.TaskScope.Global | vscode.TaskScope.Workspace) | vscode.WorkspaceFolder, arg3: any, arg4?: any, arg5?: any, arg6?: any) {
this.definition = definition;
let problemMatchers: string | string[];
@@ -1736,7 +1780,7 @@ export class Task implements vscode.TaskWithExtensionCallback {
type: Task.ShellType,
id: this._execution.computeId()
};
} else if (this._execution instanceof ExtensionCallbackExecution) {
} else if (this._execution instanceof CustomTaskExecution) {
this._definition = {
type: Task.ExtensionCallbackType,
id: this._execution.computeId()
@@ -1783,18 +1827,18 @@ export class Task implements vscode.TaskWithExtensionCallback {
}
get execution(): ProcessExecution | ShellExecution | undefined {
return (this._execution instanceof ExtensionCallbackExecution) ? undefined : this._execution;
return (this._execution instanceof CustomTaskExecution) ? undefined : this._execution;
}
set execution(value: ProcessExecution | ShellExecution | undefined) {
this.executionWithExtensionCallback = value;
}
get executionWithExtensionCallback(): ProcessExecution | ShellExecution | ExtensionCallbackExecution | undefined {
get executionWithExtensionCallback(): ProcessExecution | ShellExecution | CustomTaskExecution | undefined {
return this._execution;
}
set executionWithExtensionCallback(value: ProcessExecution | ShellExecution | ExtensionCallbackExecution | undefined) {
set executionWithExtensionCallback(value: ProcessExecution | ShellExecution | CustomTaskExecution | undefined) {
if (value === null) {
value = undefined;
}
@@ -1895,6 +1939,7 @@ export enum ProgressLocation {
Notification = 15
}
@es5ClassCompat
export class TreeItem {
label?: string | vscode.TreeItemLabel;
@@ -1934,6 +1979,7 @@ export class ThemeIcon {
}
}
@es5ClassCompat
export class ThemeColor {
id: string;
constructor(id: string) {
@@ -1949,6 +1995,7 @@ export enum ConfigurationTarget {
WorkspaceFolder = 3
}
@es5ClassCompat
export class RelativePattern implements IRelativePattern {
base: string;
baseFolder?: URI;
@@ -1981,6 +2028,7 @@ export class RelativePattern implements IRelativePattern {
}
}
@es5ClassCompat
export class Breakpoint {
private _id: string | undefined;
@@ -2011,6 +2059,7 @@ export class Breakpoint {
}
}
@es5ClassCompat
export class SourceBreakpoint extends Breakpoint {
readonly location: Location;
@@ -2023,6 +2072,7 @@ export class SourceBreakpoint extends Breakpoint {
}
}
@es5ClassCompat
export class FunctionBreakpoint extends Breakpoint {
readonly functionName: string;
@@ -2035,6 +2085,7 @@ export class FunctionBreakpoint extends Breakpoint {
}
}
@es5ClassCompat
export class DebugAdapterExecutable implements vscode.DebugAdapterExecutable {
readonly command: string;
readonly args: string[];
@@ -2047,6 +2098,7 @@ export class DebugAdapterExecutable implements vscode.DebugAdapterExecutable {
}
}
@es5ClassCompat
export class DebugAdapterServer implements vscode.DebugAdapterServer {
readonly port: number;
readonly host?: string;
@@ -2058,6 +2110,7 @@ export class DebugAdapterServer implements vscode.DebugAdapterServer {
}
/*
@es5ClassCompat
export class DebugAdapterImplementation implements vscode.DebugAdapterImplementation {
readonly implementation: any;
@@ -2085,6 +2138,7 @@ export enum FileChangeType {
Deleted = 3,
}
@es5ClassCompat
export class FileSystemError extends Error {
static FileExists(messageOrUri?: string | URI): FileSystemError {
@@ -2127,6 +2181,7 @@ export class FileSystemError extends Error {
//#region folding api
@es5ClassCompat
export class FoldingRange {
start: number;
@@ -2162,6 +2217,7 @@ export enum CommentThreadCollapsibleState {
Expanded = 1
}
@es5ClassCompat
export class QuickInputButtons {
static readonly Back: vscode.QuickInputButton = { iconPath: 'back.svg' };

View File

@@ -333,7 +333,7 @@ export class ExtHostWebviews implements ExtHostWebviewsShape {
}
const webview = new ExtHostWebview(webviewHandle, this._proxy, options);
const revivedPanel = new ExtHostWebviewPanel(webviewHandle, this._proxy, viewType, title, typeConverters.ViewColumn.to(position), options, webview);
const revivedPanel = new ExtHostWebviewPanel(webviewHandle, this._proxy, viewType, title, typeof position === 'number' ? typeConverters.ViewColumn.to(position) : undefined, options, webview);
this._webviewPanels.set(webviewHandle, revivedPanel);
return Promise.resolve(serializer.deserializeWebviewPanel(revivedPanel, state));
}

View File

@@ -17,14 +17,15 @@ import { URI } from 'vs/base/common/uri';
import { localize } from 'vs/nls';
import { ILogService } from 'vs/platform/log/common/log';
import { Severity } from 'vs/platform/notification/common/notification';
import { IRawFileMatch2, resultIsMatch } from 'vs/platform/search/common/search';
import { IRawFileMatch2, resultIsMatch } from 'vs/workbench/services/search/common/search';
import { Workspace, WorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { Range, RelativePattern } from 'vs/workbench/api/node/extHostTypes';
import { ITextQueryBuilderOptions } from 'vs/workbench/contrib/search/common/queryBuilder';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import * as vscode from 'vscode';
import { ExtHostWorkspaceShape, IMainContext, IWorkspaceData, MainContext, MainThreadMessageServiceShape, MainThreadWorkspaceShape } from './extHost.protocol';
import { ExtHostWorkspaceShape, IWorkspaceData, MainThreadMessageServiceShape, MainThreadWorkspaceShape, IMainContext, MainContext } from './extHost.protocol';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { Barrier } from 'vs/base/common/async';
function isFolderEqual(folderA: URI, folderB: URI): boolean {
return isEqual(folderA, folderB, !isLinux);
@@ -56,7 +57,7 @@ interface MutableWorkspaceFolder extends vscode.WorkspaceFolder {
class ExtHostWorkspaceImpl extends Workspace {
static toExtHostWorkspace(data: IWorkspaceData, previousConfirmedWorkspace?: ExtHostWorkspaceImpl, previousUnconfirmedWorkspace?: ExtHostWorkspaceImpl): { workspace: ExtHostWorkspaceImpl, added: vscode.WorkspaceFolder[], removed: vscode.WorkspaceFolder[] } {
static toExtHostWorkspace(data: IWorkspaceData, previousConfirmedWorkspace?: ExtHostWorkspaceImpl, previousUnconfirmedWorkspace?: ExtHostWorkspaceImpl): { workspace: ExtHostWorkspaceImpl | null, added: vscode.WorkspaceFolder[], removed: vscode.WorkspaceFolder[] } {
if (!data) {
return { workspace: null, added: [], removed: [] };
}
@@ -68,7 +69,7 @@ class ExtHostWorkspaceImpl extends Workspace {
// 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) {
if (previousConfirmedWorkspace) {
folders.forEach((folderData, index) => {
const folderUri = URI.revive(folderData.uri);
const existingFolder = ExtHostWorkspaceImpl._findFolder(previousUnconfirmedWorkspace || previousConfirmedWorkspace, folderUri);
@@ -95,7 +96,7 @@ class ExtHostWorkspaceImpl extends Workspace {
return { workspace, added, removed };
}
private static _findFolder(workspace: ExtHostWorkspaceImpl, folderUriToFind: URI): MutableWorkspaceFolder {
private static _findFolder(workspace: ExtHostWorkspaceImpl, folderUriToFind: URI): MutableWorkspaceFolder | undefined {
for (let i = 0; i < workspace.folders.length; i++) {
const folder = workspace.workspaceFolders[i];
if (isFolderEqual(folder.uri, folderUriToFind)) {
@@ -127,28 +128,70 @@ class ExtHostWorkspaceImpl extends Workspace {
return this._workspaceFolders.slice(0);
}
getWorkspaceFolder(uri: URI, resolveParent?: boolean): vscode.WorkspaceFolder {
getWorkspaceFolder(uri: URI, resolveParent?: boolean): vscode.WorkspaceFolder | undefined {
if (resolveParent && this._structure.get(uri.toString())) {
// `uri` is a workspace folder so we check for its parent
uri = dirname(uri);
uri = dirname(uri)!;
}
return this._structure.findSubstr(uri.toString());
}
resolveWorkspaceFolder(uri: URI): vscode.WorkspaceFolder {
resolveWorkspaceFolder(uri: URI): vscode.WorkspaceFolder | undefined {
return this._structure.get(uri.toString());
}
}
export class ExtHostWorkspace implements ExtHostWorkspaceShape {
private readonly _mainContext: IMainContext;
private readonly _logService: ILogService;
private readonly _requestIdProvider: Counter;
private readonly _barrier: Barrier;
private _actual: ExtHostWorkspaceProvider | null;
constructor(
mainContext: IMainContext,
logService: ILogService,
requestIdProvider: Counter
) {
this._mainContext = mainContext;
this._logService = logService;
this._requestIdProvider = requestIdProvider;
this._barrier = new Barrier();
this._actual = null;
}
public getWorkspaceProvider(): Promise<ExtHostWorkspaceProvider> {
return this._barrier.wait().then(_ => this._actual!);
}
$initializeWorkspace(data: IWorkspaceData): void {
this._actual = new ExtHostWorkspaceProvider(this._mainContext, data, this._logService, this._requestIdProvider);
this._barrier.open();
}
$acceptWorkspaceData(workspace: IWorkspaceData): void {
if (this._actual) {
this._actual.$acceptWorkspaceData(workspace);
}
}
$handleTextSearchResult(result: IRawFileMatch2, requestId: number): void {
if (this._actual) {
this._actual.$handleTextSearchResult(result, requestId);
}
}
}
export class ExtHostWorkspaceProvider {
private readonly _onDidChangeWorkspace = new Emitter<vscode.WorkspaceFoldersChangeEvent>();
private _confirmedWorkspace?: ExtHostWorkspaceImpl;
private _unconfirmedWorkspace?: ExtHostWorkspaceImpl;
private readonly _proxy: MainThreadWorkspaceShape;
private _confirmedWorkspace: ExtHostWorkspaceImpl;
private _unconfirmedWorkspace: ExtHostWorkspaceImpl;
private _messageService: MainThreadMessageServiceShape;
private readonly _messageService: MainThreadMessageServiceShape;
readonly onDidChangeWorkspace: Event<vscode.WorkspaceFoldersChangeEvent> = this._onDidChangeWorkspace.event;
@@ -162,24 +205,24 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
) {
this._proxy = mainContext.getProxy(MainContext.MainThreadWorkspace);
this._messageService = mainContext.getProxy(MainContext.MainThreadMessageService);
this._confirmedWorkspace = ExtHostWorkspaceImpl.toExtHostWorkspace(data).workspace;
this._confirmedWorkspace = ExtHostWorkspaceImpl.toExtHostWorkspace(data).workspace || undefined;
}
// --- workspace ---
get workspace(): Workspace {
get workspace(): Workspace | undefined {
return this._actualWorkspace;
}
get name(): string {
get name(): string | undefined {
return this._actualWorkspace ? this._actualWorkspace.name : undefined;
}
private get _actualWorkspace(): ExtHostWorkspaceImpl {
private get _actualWorkspace(): ExtHostWorkspaceImpl | undefined {
return this._unconfirmedWorkspace || this._confirmedWorkspace;
}
getWorkspaceFolders(): vscode.WorkspaceFolder[] {
getWorkspaceFolders(): vscode.WorkspaceFolder[] | undefined {
if (!this._actualWorkspace) {
return undefined;
}
@@ -215,7 +258,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
// 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 })));
newWorkspaceFolders.splice(index, deleteCount, ...validatedDistinctWorkspaceFoldersToAdd.map(f => ({ uri: f.uri, name: f.name || basenameOrAuthority(f.uri), index: undefined! /* fixed later */ })));
for (let i = 0; i < newWorkspaceFolders.length; i++) {
const folder = newWorkspaceFolders[i];
@@ -250,21 +293,21 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
return true;
}
getWorkspaceFolder(uri: vscode.Uri, resolveParent?: boolean): vscode.WorkspaceFolder {
getWorkspaceFolder(uri: vscode.Uri, resolveParent?: boolean): vscode.WorkspaceFolder | undefined {
if (!this._actualWorkspace) {
return undefined;
}
return this._actualWorkspace.getWorkspaceFolder(uri, resolveParent);
}
resolveWorkspaceFolder(uri: vscode.Uri): vscode.WorkspaceFolder {
resolveWorkspaceFolder(uri: vscode.Uri): vscode.WorkspaceFolder | undefined {
if (!this._actualWorkspace) {
return undefined;
}
return this._actualWorkspace.resolveWorkspaceFolder(uri);
}
getPath(): string {
getPath(): string | undefined {
// this is legacy from the days before having
// multi-root and we keep it only alive if there
@@ -281,9 +324,9 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
return folders[0].uri.fsPath;
}
getRelativePath(pathOrUri: string | vscode.Uri, includeWorkspace?: boolean): string {
getRelativePath(pathOrUri: string | vscode.Uri, includeWorkspace?: boolean): string | undefined {
let path: string;
let path: string | undefined;
if (typeof pathOrUri === 'string') {
path = pathOrUri;
} else if (typeof pathOrUri !== 'undefined') {
@@ -303,7 +346,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
return path;
}
if (typeof includeWorkspace === 'undefined') {
if (typeof includeWorkspace === 'undefined' && this._actualWorkspace) {
includeWorkspace = this._actualWorkspace.folders.length > 1;
}
@@ -324,7 +367,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
name: this._actualWorkspace.name,
configuration: this._actualWorkspace.configuration,
folders
} as IWorkspaceData, this._actualWorkspace).workspace;
} as IWorkspaceData, this._actualWorkspace).workspace || undefined;
}
}
@@ -334,7 +377,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
// Update our workspace object. We have a confirmed workspace, so we drop our
// unconfirmed workspace.
this._confirmedWorkspace = workspace;
this._confirmedWorkspace = workspace || undefined;
this._unconfirmedWorkspace = undefined;
// Events
@@ -349,8 +392,8 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
findFiles(include: string | RelativePattern, exclude: vscode.GlobPattern, maxResults: number, extensionId: ExtensionIdentifier, token: vscode.CancellationToken = CancellationToken.None): Promise<vscode.Uri[]> {
this._logService.trace(`extHostWorkspace#findFiles: fileSearch, extension: ${extensionId.value}, entryPoint: findFiles`);
let includePattern: string;
let includeFolder: URI;
let includePattern: string | undefined;
let includeFolder: URI | undefined;
if (include) {
if (typeof include === 'string') {
includePattern = include;
@@ -362,7 +405,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
}
}
let excludePatternOrDisregardExcludes: string | false;
let excludePatternOrDisregardExcludes: string | false = false;
if (exclude === null) {
excludePatternOrDisregardExcludes = false;
} else if (exclude) {
@@ -381,7 +424,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
.then(data => Array.isArray(data) ? data.map(URI.revive) : []);
}
findTextInFiles(query: vscode.TextSearchQuery, options: vscode.FindTextInFilesOptions, callback: (result: vscode.TextSearchResult) => void, extensionId: ExtensionIdentifier, token: vscode.CancellationToken = CancellationToken.None): Promise<vscode.TextSearchComplete> {
findTextInFiles(query: vscode.TextSearchQuery, options: vscode.FindTextInFilesOptions, callback: (result: vscode.TextSearchResult) => void, extensionId: ExtensionIdentifier, token: vscode.CancellationToken = CancellationToken.None): Promise<vscode.TextSearchComplete | undefined> {
this._logService.trace(`extHostWorkspace#findTextInFiles: textSearch, extension: ${extensionId.value}, entryPoint: findTextInFiles`);
const requestId = this._requestIdProvider.getNext();
@@ -413,7 +456,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
beforeContext: options.beforeContext,
includePattern: options.include && globPatternToString(options.include),
excludePattern: options.exclude && globPatternToString(options.exclude)
excludePattern: options.exclude ? globPatternToString(options.exclude) : undefined
};
let isCanceled = false;
@@ -424,7 +467,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
}
const uri = URI.revive(p.resource);
p.results.forEach(result => {
p.results!.forEach(result => {
if (resultIsMatch(result)) {
callback(<vscode.TextSearchMatch>{
uri,
@@ -471,7 +514,7 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
return this._proxy.$saveAll(includeUntitled);
}
resolveProxy(url: string): Promise<string> {
resolveProxy(url: string): Promise<string | undefined> {
return this._proxy.$resolveProxy(url);
}
}