Initial VS Code 1.19 source merge (#571)

* Initial 1.19 xcopy

* Fix yarn build

* Fix numerous build breaks

* Next batch of build break fixes

* More build break fixes

* Runtime breaks

* Additional post merge fixes

* Fix windows setup file

* Fix test failures.

* Update license header blocks to refer to source eula
This commit is contained in:
Karl Burtram
2018-01-28 23:37:17 -08:00
committed by GitHub
parent 9a1ac20710
commit 251ae01c3e
8009 changed files with 93378 additions and 35634 deletions

View File

@@ -36,7 +36,6 @@ import { ExtHostApiCommands } from 'vs/workbench/api/node/extHostApiCommands';
import { ExtHostTask } from 'vs/workbench/api/node/extHostTask';
// {{SQL CARBON EDIT}}
//import { ExtHostDebugService } from 'vs/workbench/api/node/extHostDebugService';
import { ExtHostCredentials } from 'vs/workbench/api/node/extHostCredentials';
import { ExtHostWindow } from 'vs/workbench/api/node/extHostWindow';
import * as extHostTypes from 'vs/workbench/api/node/extHostTypes';
import URI from 'vs/base/common/uri';
@@ -57,6 +56,10 @@ import { ExtHostDialogs } from 'vs/workbench/api/node/extHostDialogs';
import { ExtHostFileSystem } from 'vs/workbench/api/node/extHostFileSystem';
import { FileChangeType, FileType } from 'vs/platform/files/common/files';
import { ExtHostDecorations } from 'vs/workbench/api/node/extHostDecorations';
import { toGlobPattern, toLanguageSelector } from 'vs/workbench/api/node/extHostTypeConverters';
import { ExtensionActivatedByAPI } from 'vs/workbench/api/node/extHostExtensionActivator';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import { ILogService } from 'vs/platform/log/common/log';
export interface IExtensionApiFactory {
(extension: IExtensionDescription): typeof vscode;
@@ -80,7 +83,8 @@ export function createApiFactory(
threadService: ExtHostThreadService,
extHostWorkspace: ExtHostWorkspace,
extHostConfiguration: ExtHostConfiguration,
extensionService: ExtHostExtensionService
extensionService: ExtHostExtensionService,
logService: ILogService
): IExtensionApiFactory {
// Addressable instances
@@ -91,11 +95,11 @@ export function createApiFactory(
const extHostDocumentContentProviders = threadService.set(ExtHostContext.ExtHostDocumentContentProviders, new ExtHostDocumentContentProvider(threadService, extHostDocumentsAndEditors));
const extHostDocumentSaveParticipant = threadService.set(ExtHostContext.ExtHostDocumentSaveParticipant, new ExtHostDocumentSaveParticipant(extHostDocuments, threadService.get(MainContext.MainThreadEditors)));
const extHostEditors = threadService.set(ExtHostContext.ExtHostEditors, new ExtHostEditors(threadService, extHostDocumentsAndEditors));
const extHostCommands = threadService.set(ExtHostContext.ExtHostCommands, new ExtHostCommands(threadService, extHostHeapService));
const extHostCommands = threadService.set(ExtHostContext.ExtHostCommands, new ExtHostCommands(threadService, extHostHeapService, logService));
const extHostTreeViews = threadService.set(ExtHostContext.ExtHostTreeViews, new ExtHostTreeViews(threadService.get(MainContext.MainThreadTreeViews), extHostCommands));
threadService.set(ExtHostContext.ExtHostWorkspace, extHostWorkspace);
// {{SQL CARBON EDIT}}
// const extHostDebugService = threadService.set(ExtHostContext.ExtHostDebugService, new ExtHostDebugService(threadService, extHostWorkspace));
//const extHostDebugService = threadService.set(ExtHostContext.ExtHostDebugService, new ExtHostDebugService(threadService, extHostWorkspace));
threadService.set(ExtHostContext.ExtHostConfiguration, extHostConfiguration);
const extHostDiagnostics = threadService.set(ExtHostContext.ExtHostDiagnostics, new ExtHostDiagnostics(threadService));
const languageFeatures = threadService.set(ExtHostContext.ExtHostLanguageFeatures, new ExtHostLanguageFeatures(threadService, extHostDocuments, extHostCommands, extHostHeapService, extHostDiagnostics));
@@ -103,9 +107,8 @@ export function createApiFactory(
const extHostFileSystemEvent = threadService.set(ExtHostContext.ExtHostFileSystemEventService, new ExtHostFileSystemEventService());
const extHostQuickOpen = threadService.set(ExtHostContext.ExtHostQuickOpen, new ExtHostQuickOpen(threadService, extHostWorkspace, extHostCommands));
const extHostTerminalService = threadService.set(ExtHostContext.ExtHostTerminalService, new ExtHostTerminalService(threadService));
const extHostSCM = threadService.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(threadService, extHostCommands));
const extHostSCM = threadService.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(threadService, extHostCommands, logService));
const extHostTask = threadService.set(ExtHostContext.ExtHostTask, new ExtHostTask(threadService, extHostWorkspace));
const extHostCredentials = threadService.set(ExtHostContext.ExtHostCredentials, new ExtHostCredentials(threadService));
const extHostWindow = threadService.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(threadService));
threadService.set(ExtHostContext.ExtHostExtensionService, extensionService);
@@ -126,8 +129,14 @@ export function createApiFactory(
return function (extension: IExtensionDescription): typeof vscode {
if (extension.enableProposedApi && !extension.isBuiltin) {
if (!isFalsyOrEmpty(product.extensionAllowedProposedApi)
&& product.extensionAllowedProposedApi.indexOf(extension.id) >= 0
) {
// fast lane -> proposed api is available to all extensions
// that are listed in product.json-files
extension.enableProposedApi = true;
} else if (extension.enableProposedApi && !extension.isBuiltin) {
if (
!initData.environment.enableProposedApiForAll &&
initData.environment.enableProposedApiFor.indexOf(extension.id) < 0
@@ -144,7 +153,7 @@ export function createApiFactory(
// namespace: commands
const commands: typeof vscode.commands = {
registerCommand<T>(id: string, command: <T>(...args: any[]) => T | Thenable<T>, thisArgs?: any): vscode.Disposable {
registerCommand(id: string, command: <T>(...args: any[]) => T | Thenable<T>, thisArgs?: any): vscode.Disposable {
return extHostCommands.registerCommand(id, command, thisArgs);
},
registerTextEditorCommand(id: string, callback: (textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit, ...args: any[]) => void, thisArg?: any): vscode.Disposable {
@@ -220,7 +229,7 @@ export function createApiFactory(
return extHostLanguages.getLanguages();
},
match(selector: vscode.DocumentSelector, document: vscode.TextDocument): number {
return score(selector, <any>document.uri, document.languageId);
return score(toLanguageSelector(selector), document.uri, document.languageId);
},
registerCodeActionsProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable {
return languageFeatures.registerCodeActionProvider(selector, provider);
@@ -412,7 +421,7 @@ export function createApiFactory(
return extHostWorkspace.getRelativePath(pathOrUri, includeWorkspace);
},
findFiles: (include, exclude, maxResults?, token?) => {
return extHostWorkspace.findFiles(include, exclude, maxResults, token);
return extHostWorkspace.findFiles(toGlobPattern(include), toGlobPattern(exclude), maxResults, token);
},
saveAll: (includeUntitled?) => {
return extHostWorkspace.saveAll(includeUntitled);
@@ -421,7 +430,7 @@ export function createApiFactory(
return extHostEditors.applyWorkspaceEdit(edit);
},
createFileSystemWatcher: (pattern, ignoreCreate, ignoreChange, ignoreDelete): vscode.FileSystemWatcher => {
return extHostFileSystemEvent.createFileSystemWatcher(pattern, ignoreCreate, ignoreChange, ignoreDelete);
return extHostFileSystemEvent.createFileSystemWatcher(toGlobPattern(pattern), ignoreCreate, ignoreChange, ignoreDelete);
},
get textDocuments() {
return extHostDocuments.getAllDocumentData().map(data => data.document);
@@ -496,22 +505,7 @@ export function createApiFactory(
// {{SQL CARBON EDIT}}
// delete namespace: debug
// namespace: credentials
const credentials = {
readSecret(service: string, account: string): Thenable<string | undefined> {
return extHostCredentials.readSecret(service, account);
},
writeSecret(service: string, account: string, secret: string): Thenable<void> {
return extHostCredentials.writeSecret(service, account, secret);
},
deleteSecret(service: string, account: string): Thenable<boolean> {
return extHostCredentials.deleteSecret(service, account);
}
};
const api: typeof vscode = {
return <typeof vscode>{
version: pkg.version,
// namespaces
commands,
@@ -524,7 +518,9 @@ export function createApiFactory(
// {{SQL CARBON EDIT}}
// debug,
// types
Breakpoint: extHostTypes.Breakpoint,
CancellationTokenSource: CancellationTokenSource,
CodeAction: extHostTypes.CodeAction,
CodeLens: extHostTypes.CodeLens,
Color: extHostTypes.Color,
ColorPresentation: extHostTypes.ColorPresentation,
@@ -541,6 +537,7 @@ export function createApiFactory(
DocumentHighlightKind: extHostTypes.DocumentHighlightKind,
DocumentLink: extHostTypes.DocumentLink,
EventEmitter: Emitter,
FunctionBreakpoint: extHostTypes.FunctionBreakpoint,
Hover: extHostTypes.Hover,
IndentAction: languageConfiguration.IndentAction,
Location: extHostTypes.Location,
@@ -553,6 +550,7 @@ export function createApiFactory(
SignatureHelp: extHostTypes.SignatureHelp,
SignatureInformation: extHostTypes.SignatureInformation,
SnippetString: extHostTypes.SnippetString,
SourceBreakpoint: extHostTypes.SourceBreakpoint,
StatusBarAlignment: extHostTypes.StatusBarAlignment,
SymbolInformation: extHostTypes.SymbolInformation,
SymbolKind: extHostTypes.SymbolKind,
@@ -585,10 +583,6 @@ export function createApiFactory(
FileChangeType: <any>FileChangeType,
FileType: <any>FileType
};
if (extension.enableProposedApi && extension.isBuiltin) {
api['credentials'] = credentials;
}
return api;
};
}
@@ -616,7 +610,7 @@ class Extension<T> implements vscode.Extension<T> {
}
activate(): Thenable<T> {
return this._extensionService.activateById(this.id, false).then(() => this.exports);
return this._extensionService.activateById(this.id, new ExtensionActivatedByAPI(false)).then(() => this.exports);
}
}

View File

@@ -46,10 +46,10 @@ import { ITreeItem } from 'vs/workbench/common/views';
import { ThemeColor } from 'vs/platform/theme/common/themeService';
import { IDisposable } from 'vs/base/common/lifecycle';
import { SerializedError } from 'vs/base/common/errors';
import { IRelativePattern } from 'vs/base/common/glob';
import { IWorkspaceFolderData } from 'vs/platform/workspace/common/workspace';
import { IStat, IFileChange } from 'vs/platform/files/common/files';
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
import { ParsedArgs } from 'vs/platform/environment/common/environment';
export interface IEnvironment {
isExtensionDevelopmentDebug: boolean;
@@ -76,6 +76,9 @@ export interface IInitData {
extensions: IExtensionDescription[];
configuration: IConfigurationInitData;
telemetryInfo: ITelemetryInfo;
windowId: number;
args: ParsedArgs;
execPath: string;
}
export interface IConfigurationInitData extends IConfigurationData {
@@ -236,11 +239,11 @@ export interface MainThreadEditorsShape extends IDisposable {
export interface MainThreadTreeViewsShape extends IDisposable {
$registerView(treeViewId: string): void;
$refresh(treeViewId: string, treeItemHandles: number[]): void;
$refresh(treeViewId: string, itemsToRefresh?: { [treeItemHandle: string]: ITreeItem }): void;
}
export interface MainThreadErrorsShape extends IDisposable {
$onUnexpectedError(err: any | SerializedError, extensionId: string | undefined): void;
$onUnexpectedError(err: any | SerializedError): void;
}
export interface MainThreadLanguageFeaturesShape extends IDisposable {
@@ -328,7 +331,7 @@ export interface MainThreadTelemetryShape extends IDisposable {
}
export interface MainThreadWorkspaceShape extends IDisposable {
$startSearch(include: string | IRelativePattern, exclude: string | IRelativePattern, maxResults: number, requestId: number): Thenable<URI[]>;
$startSearch(includePattern: string, includeFolder: string, excludePattern: string, maxResults: number, requestId: number): Thenable<URI[]>;
$cancelSearch(requestId: number): Thenable<boolean>;
$saveAll(includeUntitled?: boolean): Thenable<boolean>;
}
@@ -351,8 +354,10 @@ export interface MainThreadTaskShape extends IDisposable {
export interface MainThreadExtensionServiceShape extends IDisposable {
$localShowMessage(severity: Severity, msg: string): void;
$onExtensionActivated(extensionId: string, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number): void;
$onExtensionActivated(extensionId: string, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationEvent: string): void;
$onExtensionActivationFailed(extensionId: string): void;
$onExtensionRuntimeError(extensionId: string, error: SerializedError): void;
$addMessage(extensionId: string, severity: Severity, message: string): void;
}
export interface SCMProviderFeatures {
@@ -404,6 +409,7 @@ export interface MainThreadSCMShape extends IDisposable {
$spliceResourceStates(sourceControlHandle: number, splices: SCMRawResourceSplices[]): void;
$setInputBoxValue(sourceControlHandle: number, value: string): void;
$setInputBoxPlaceholder(sourceControlHandle: number, placeholder: string): void;
}
@@ -417,13 +423,10 @@ export interface MainThreadDebugServiceShape extends IDisposable {
$startDebugging(folder: URI | undefined, nameOrConfig: string | vscode.DebugConfiguration): TPromise<boolean>;
$customDebugAdapterRequest(id: DebugSessionUUID, command: string, args: any): TPromise<any>;
$appendDebugConsole(value: string): TPromise<any>;
$startBreakpointEvents(): TPromise<any>;
}
// {{SQL CARBON EDIT}}
*/
export interface MainThreadCredentialsShape extends IDisposable {
$readSecret(service: string, account: string): Thenable<string | undefined>;
$writeSecret(service: string, account: string, secret: string): Thenable<void>;
$deleteSecret(service: string, account: string): Thenable<boolean>;
}
export interface MainThreadWindowShape extends IDisposable {
$getWindowVisibility(): TPromise<boolean>;
@@ -497,7 +500,7 @@ export interface ExtHostDocumentsAndEditorsShape {
export interface ExtHostTreeViewsShape {
$getElements(treeViewId: string): TPromise<ITreeItem[]>;
$getChildren(treeViewId: string, treeItemHandle: number): TPromise<ITreeItem[]>;
$getChildren(treeViewId: string, treeItemHandle: string): TPromise<ITreeItem[]>;
}
export interface ExtHostWorkspaceShape {
@@ -577,7 +580,7 @@ export namespace IdObject {
}
export type IWorkspaceSymbol = IdObject & modes.SymbolInformation;
export interface IWorkspaceSymbols extends IdObject { symbols: IWorkspaceSymbol[]; };
export interface IWorkspaceSymbols extends IdObject { symbols: IWorkspaceSymbol[]; }
export interface ExtHostLanguageFeaturesShape {
$provideDocumentSymbols(handle: number, resource: URI): TPromise<modes.SymbolInformation[]>;
@@ -589,7 +592,7 @@ export interface ExtHostLanguageFeaturesShape {
$provideHover(handle: number, resource: URI, position: IPosition): TPromise<modes.Hover>;
$provideDocumentHighlights(handle: number, resource: URI, position: IPosition): TPromise<modes.DocumentHighlight[]>;
$provideReferences(handle: number, resource: URI, position: IPosition, context: modes.ReferenceContext): TPromise<modes.Location[]>;
$provideCodeActions(handle: number, resource: URI, range: IRange): TPromise<modes.Command[]>;
$provideCodeActions(handle: number, resource: URI, range: IRange): TPromise<modes.CodeAction[]>;
$provideDocumentFormattingEdits(handle: number, resource: URI, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]>;
$provideDocumentRangeFormattingEdits(handle: number, resource: URI, range: IRange, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]>;
$provideOnTypeFormattingEdits(handle: number, resource: URI, position: IPosition, ch: string, options: modes.FormattingOptions): TPromise<editorCommon.ISingleEditOperation[]>;
@@ -627,6 +630,32 @@ export interface ExtHostTaskShape {
$provideTasks(handle: number): TPromise<TaskSet>;
}
export interface IBreakpointData {
type: 'source' | 'function';
id: string;
enabled: boolean;
condition?: string;
hitCondition?: string;
}
export interface ISourceBreakpointData extends IBreakpointData {
type: 'source';
uri: URI;
line: number;
character: number;
}
export interface IFunctionBreakpointData extends IBreakpointData {
type: 'function';
functionName: string;
}
export interface IBreakpointsDelta {
added?: (ISourceBreakpointData | IFunctionBreakpointData)[];
removed?: string[];
changed?: (ISourceBreakpointData | IFunctionBreakpointData)[];
}
// {{SQL CARBON EDIT}}
/*
export interface ExtHostDebugServiceShape {
@@ -636,7 +665,9 @@ export interface ExtHostDebugServiceShape {
$acceptDebugSessionTerminated(id: DebugSessionUUID, type: string, name: string): void;
$acceptDebugSessionActiveChanged(id: DebugSessionUUID | undefined, type?: string, name?: string): void;
$acceptDebugSessionCustomEvent(id: DebugSessionUUID, type: string, name: string, event: any): void;
$acceptBreakpointsDelta(delat: IBreakpointsDelta): void;
}
// {{SQL CARBON EDIT}}
*/
export type DecorationData = [number, boolean, string, string, ThemeColor, string];
@@ -645,9 +676,6 @@ export interface ExtHostDecorationsShape {
$providerDecorations(handle: number, uri: URI): TPromise<DecorationData>;
}
export interface ExtHostCredentialsShape {
}
export interface ExtHostWindowShape {
$onDidChangeWindowFocus(value: boolean): void;
}
@@ -682,7 +710,6 @@ export const MainContext = {
MainThreadExtensionService: createMainId<MainThreadExtensionServiceShape>('MainThreadExtensionService'),
MainThreadSCM: createMainId<MainThreadSCMShape>('MainThreadSCM'),
MainThreadTask: createMainId<MainThreadTaskShape>('MainThreadTask'),
MainThreadCredentials: createMainId<MainThreadCredentialsShape>('MainThreadCredentials'),
MainThreadWindow: createMainId<MainThreadWindowShape>('MainThreadWindow'),
};
@@ -709,6 +736,5 @@ export const ExtHostContext = {
ExtHostSCM: createExtId<ExtHostSCMShape>('ExtHostSCM'),
ExtHostTask: createExtId<ExtHostTaskShape>('ExtHostTask'),
ExtHostWorkspace: createExtId<ExtHostWorkspaceShape>('ExtHostWorkspace'),
ExtHostCredentials: createExtId<ExtHostCredentialsShape>('ExtHostCredentials'),
ExtHostWindow: createExtId<ExtHostWindowShape>('ExtHostWindow'),
};

View File

@@ -15,7 +15,8 @@ import * as modes from 'vs/editor/common/modes';
import { ICommandHandlerDescription } from 'vs/platform/commands/common/commands';
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
import { IWorkspaceSymbolProvider } from 'vs/workbench/parts/search/common/search';
import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { Position as EditorPosition, ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { CustomCodeAction } from 'vs/workbench/api/node/extHostLanguageFeatures';
export class ExtHostApiCommands {
@@ -196,20 +197,11 @@ export class ExtHostApiCommands {
});
this._register('vscode.diff', (left: URI, right: URI, label: string, options?: vscode.TextDocumentShowOptions) => {
let editorOptions: ITextEditorOptions;
if (options) {
editorOptions = {
pinned: typeof options.preview === 'boolean' ? !options.preview : undefined,
preserveFocus: options.preserveFocus,
selection: typeof options.selection === 'object' ? typeConverters.fromRange(options.selection) : undefined
};
}
return this._commands.executeCommand('_workbench.diff', [
left, right,
label,
undefined,
editorOptions,
typeConverters.toTextEditorOptions(options),
options ? typeConverters.fromViewColumn(options.viewColumn) : undefined
]);
}, {
@@ -222,13 +214,29 @@ export class ExtHostApiCommands {
]
});
this._register('vscode.open', (resource: URI, column: vscode.ViewColumn) => {
return this._commands.executeCommand('_workbench.open', [resource, typeConverters.fromViewColumn(column)]);
this._register('vscode.open', (resource: URI, columnOrOptions?: vscode.ViewColumn | vscode.TextDocumentShowOptions) => {
let options: ITextEditorOptions;
let column: EditorPosition;
if (columnOrOptions) {
if (typeof columnOrOptions === 'number') {
column = typeConverters.fromViewColumn(columnOrOptions);
} else {
options = typeConverters.toTextEditorOptions(columnOrOptions);
column = typeConverters.fromViewColumn(columnOrOptions.viewColumn);
}
}
return this._commands.executeCommand('_workbench.open', [
resource,
options,
column
]);
}, {
description: 'Opens the provided resource in the editor. Can be a text or binary file, or a http(s) url. If you need more control over the options for opening a text file, use vscode.window.showTextDocument instead.',
args: [
{ name: 'resource', description: 'Resource to open', constraint: URI },
{ name: 'column', description: '(optional) Column in which to open', constraint: v => v === void 0 || typeof v === 'number' }
{ name: 'columnOrOptions', description: '(optional) Either the column in which to open or editor options, see vscode.TextDocumentShowOptions', constraint: v => v === void 0 || typeof v === 'number' || typeof v === 'object' }
]
});
}
@@ -386,16 +394,26 @@ export class ExtHostApiCommands {
});
}
private _executeCodeActionProvider(resource: URI, range: types.Range): Thenable<vscode.Command[]> {
private _executeCodeActionProvider(resource: URI, range: types.Range): Thenable<(vscode.CodeAction | vscode.Command)[]> {
const args = {
resource,
range: typeConverters.fromRange(range)
};
return this._commands.executeCommand<modes.Command[]>('_executeCodeActionProvider', args).then(value => {
return this._commands.executeCommand<CustomCodeAction[]>('_executeCodeActionProvider', args).then(value => {
if (!Array.isArray(value)) {
return undefined;
}
return value.map(quickFix => this._commands.converter.fromInternal(quickFix));
return value.map(codeAction => {
if (codeAction._isSynthetic) {
return this._commands.converter.fromInternal(codeAction.command);
} else {
const ret = new types.CodeAction(
codeAction.title,
typeConverters.WorkspaceEdit.to(codeAction.edits)
);
return ret;
}
});
});
}

View File

@@ -15,6 +15,7 @@ import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService';
import { isFalsyOrEmpty } from 'vs/base/common/arrays';
import * as modes from 'vs/editor/common/modes';
import * as vscode from 'vscode';
import { ILogService } from 'vs/platform/log/common/log';
interface CommandHandler {
callback: Function;
@@ -35,7 +36,8 @@ export class ExtHostCommands implements ExtHostCommandsShape {
constructor(
mainContext: IMainContext,
heapService: ExtHostHeapService
heapService: ExtHostHeapService,
private logService: ILogService
) {
this._proxy = mainContext.get(MainContext.MainThreadCommands);
this._converter = new CommandsConverter(this, heapService);
@@ -50,6 +52,7 @@ export class ExtHostCommands implements ExtHostCommandsShape {
}
registerCommand(id: string, callback: <T>(...args: any[]) => T | Thenable<T>, thisArg?: any, description?: ICommandHandlerDescription): extHostTypes.Disposable {
this.logService.trace('ExtHostCommands#registerCommand', id);
if (!id.trim().length) {
throw new Error('invalid id');
@@ -70,6 +73,7 @@ export class ExtHostCommands implements ExtHostCommandsShape {
}
executeCommand<T>(id: string, ...args: any[]): Thenable<T> {
this.logService.trace('ExtHostCommands#executeCommand', id);
if (this._commands.has(id)) {
// we stay inside the extension host and support
@@ -134,6 +138,8 @@ export class ExtHostCommands implements ExtHostCommandsShape {
}
getCommands(filterUnderscoreCommands: boolean = false): Thenable<string[]> {
this.logService.trace('ExtHostCommands#getCommands', filterUnderscoreCommands);
return this._proxy.$getCommands().then(result => {
if (filterUnderscoreCommands) {
result = result.filter(command => command[0] !== '_');

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import { mixin } from 'vs/base/common/objects';
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';
@@ -12,7 +12,7 @@ import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { ExtHostConfigurationShape, MainThreadConfigurationShape, IWorkspaceConfigurationChangeEventData, IConfigurationInitData } from './extHost.protocol';
import { ConfigurationTarget as ExtHostConfigurationTarget } from './extHostTypes';
import { IConfigurationData, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { Configuration, ConfigurationModel, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels';
import { Configuration, ConfigurationChangeEvent, ConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
import { WorkspaceConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels';
import { StrictResourceMap } from 'vs/base/common/map';
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
@@ -61,9 +61,9 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
}
getConfiguration(section?: string, resource?: URI, extensionId?: string): vscode.WorkspaceConfiguration {
const config = section
? lookUp(this._configuration.getSection(null, { resource }, this._extHostWorkspace.workspace), section)
: this._configuration.getSection(null, { resource }, this._extHostWorkspace.workspace);
const config = deepClone(section
? lookUp(this._configuration.getValue(null, { resource }, this._extHostWorkspace.workspace), section)
: this._configuration.getValue(null, { resource }, this._extHostWorkspace.workspace));
if (section) {
this._validateConfigurationAccess(section, resource, extensionId);
@@ -107,7 +107,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
},
inspect: <T>(key: string): ConfigurationInspect<T> => {
key = section ? `${section}.${key}` : key;
const config = this._configuration.lookup<T>(key, { resource }, this._extHostWorkspace.workspace);
const config = deepClone(this._configuration.inspect<T>(key, { resource }, this._extHostWorkspace.workspace));
if (config) {
return {
key,

View File

@@ -1,29 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { MainContext, MainThreadCredentialsShape, ExtHostCredentialsShape, IMainContext } from 'vs/workbench/api/node/extHost.protocol';
export class ExtHostCredentials implements ExtHostCredentialsShape {
private _proxy: MainThreadCredentialsShape;
constructor(mainContext: IMainContext) {
this._proxy = mainContext.get(MainContext.MainThreadCredentials);
};
readSecret(service: string, account: string): Thenable<string | undefined> {
return this._proxy.$readSecret(service, account);
}
writeSecret(service: string, account: string, secret: string): Thenable<void> {
return this._proxy.$writeSecret(service, account, secret);
}
deleteSecret(service: string, account: string): Thenable<boolean> {
return this._proxy.$deleteSecret(service, account);
}
}

View File

@@ -9,12 +9,12 @@
import { TPromise } from 'vs/base/common/winjs.base';
import Event, { Emitter } from 'vs/base/common/event';
import { asWinJsPromise } from 'vs/base/common/async';
import { MainContext, MainThreadDebugServiceShape, ExtHostDebugServiceShape, DebugSessionUUID, IMainContext } from 'vs/workbench/api/node/extHost.protocol';
import { MainContext, MainThreadDebugServiceShape, ExtHostDebugServiceShape, DebugSessionUUID, IMainContext, IBreakpointsDelta, ISourceBreakpointData, IFunctionBreakpointData } from 'vs/workbench/api/node/extHost.protocol';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import * as vscode from 'vscode';
import URI from 'vs/base/common/uri';
import * as types from 'vs/workbench/api/node/extHostTypes';
import { Disposable, Position, Location, SourceBreakpoint, FunctionBreakpoint } from 'vs/workbench/api/node/extHostTypes';
export class ExtHostDebugService implements ExtHostDebugServiceShape {
@@ -42,8 +42,13 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
private _onDidReceiveDebugSessionCustomEvent: Emitter<vscode.DebugSessionCustomEvent>;
get onDidReceiveDebugSessionCustomEvent(): Event<vscode.DebugSessionCustomEvent> { return this._onDidReceiveDebugSessionCustomEvent.event; }
private _debugConsole: ExtHostDebugConsole;
get debugConsole(): ExtHostDebugConsole { return this._debugConsole; }
private _activeDebugConsole: ExtHostDebugConsole;
get activeDebugConsole(): ExtHostDebugConsole { return this._activeDebugConsole; }
private _breakpoints: Map<string, vscode.Breakpoint>;
private _breakpointEventsActive: boolean;
private _onDidChangeBreakpoints: Emitter<vscode.BreakpointsChangeEvent>;
constructor(mainContext: IMainContext, workspace: ExtHostWorkspace) {
@@ -60,19 +65,94 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
this._debugServiceProxy = mainContext.get(MainContext.MainThreadDebugService);
this._debugConsole = new ExtHostDebugConsole(this._debugServiceProxy);
this._onDidChangeBreakpoints = new Emitter<vscode.BreakpointsChangeEvent>({
onFirstListenerAdd: () => {
this.startBreakpoints();
}
});
this._activeDebugConsole = new ExtHostDebugConsole(this._debugServiceProxy);
this._breakpoints = new Map<string, vscode.Breakpoint>();
this._breakpointEventsActive = false;
}
private startBreakpoints() {
if (!this._breakpointEventsActive) {
this._breakpointEventsActive = true;
this._debugServiceProxy.$startBreakpointEvents();
}
}
get onDidChangeBreakpoints(): Event<vscode.BreakpointsChangeEvent> {
return this._onDidChangeBreakpoints.event;
}
get breakpoints(): vscode.Breakpoint[] {
this.startBreakpoints();
const result: vscode.Breakpoint[] = [];
this._breakpoints.forEach(bp => result.push(bp));
return result;
}
public $acceptBreakpointsDelta(delta: IBreakpointsDelta): void {
let a: vscode.Breakpoint[] = [];
let r: vscode.Breakpoint[] = [];
let c: vscode.Breakpoint[] = [];
if (delta.added) {
a = delta.added.map(bpd => {
const bp = this.fromWire(bpd);
this._breakpoints.set(bpd.id, bp);
return bp;
});
}
if (delta.removed) {
r = delta.removed.map(id => {
const bp = this._breakpoints.get(id);
if (bp) {
this._breakpoints.delete(id);
}
return bp;
});
}
if (delta.changed) {
c = delta.changed.map(bpd => {
const bp = this.fromWire(bpd);
this._breakpoints.set(bpd.id, bp);
return bp;
});
}
this._onDidChangeBreakpoints.fire(Object.freeze({
added: Object.freeze<vscode.Breakpoint[]>(a || []),
removed: Object.freeze<vscode.Breakpoint[]>(r || []),
changed: Object.freeze<vscode.Breakpoint[]>(c || [])
}));
}
private fromWire(bp: ISourceBreakpointData | IFunctionBreakpointData): vscode.Breakpoint {
if (bp.type === 'function') {
return new FunctionBreakpoint(bp.enabled, bp.condition, bp.hitCondition, bp.functionName);
}
return new SourceBreakpoint(bp.enabled, bp.condition, bp.hitCondition, new Location(bp.uri, new Position(bp.line, bp.character)));
}
public registerDebugConfigurationProvider(type: string, provider: vscode.DebugConfigurationProvider): vscode.Disposable {
if (!provider) {
return new types.Disposable(() => { });
return new Disposable(() => { });
}
let handle = this.nextHandle();
this._handlers.set(handle, provider);
this._debugServiceProxy.$registerDebugConfigurationProvider(type, !!provider.provideDebugConfigurations, !!provider.resolveDebugConfiguration, handle);
return new types.Disposable(() => {
return new Disposable(() => {
this._handlers.delete(handle);
this._debugServiceProxy.$unregisterDebugConfigurationProvider(handle);
});
@@ -89,7 +169,6 @@ export class ExtHostDebugService implements ExtHostDebugServiceShape {
return asWinJsPromise(token => handler.provideDebugConfigurations(this.getFolder(folderUri), token));
}
public $resolveDebugConfiguration(handle: number, folderUri: URI | undefined, debugConfiguration: vscode.DebugConfiguration): TPromise<vscode.DebugConfiguration> {
let handler = this._handlers.get(handle);
if (!handler) {

View File

@@ -111,7 +111,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
orderLoop: for (let i = 0; i < 4; i++) {
for (let diagnostic of diagnostics) {
if (diagnostic.severity === order[i]) {
const len = marker.push(DiagnosticCollection._toMarkerData(diagnostic));
const len = marker.push(DiagnosticCollection.toMarkerData(diagnostic));
if (len === DiagnosticCollection._maxDiagnosticsPerFile) {
break orderLoop;
}
@@ -129,7 +129,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
endColumn: marker[marker.length - 1].endColumn
});
} else {
marker = diagnostics.map(DiagnosticCollection._toMarkerData);
marker = diagnostics.map(DiagnosticCollection.toMarkerData);
}
}
@@ -179,7 +179,7 @@ export class DiagnosticCollection implements vscode.DiagnosticCollection {
}
}
private static _toMarkerData(diagnostic: vscode.Diagnostic): IMarkerData {
public static toMarkerData(diagnostic: vscode.Diagnostic): IMarkerData {
let range = diagnostic.range;

View File

@@ -5,7 +5,6 @@
'use strict';
import Event from 'vs/base/common/event';
import CallbackList from 'vs/base/common/callbackList';
import URI from 'vs/base/common/uri';
import { sequence, always } from 'vs/base/common/async';
import { illegalState } from 'vs/base/common/errors';
@@ -16,12 +15,13 @@ import { fromRange, TextDocumentSaveReason, EndOfLine } from 'vs/workbench/api/n
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
import * as vscode from 'vscode';
import { LinkedList } from 'vs/base/common/linkedList';
export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSaveParticipantShape {
private _documents: ExtHostDocuments;
private _mainThreadEditors: MainThreadEditorsShape;
private _callbacks = new CallbackList();
private _callbacks = new LinkedList<[Function, any]>();
private _badListeners = new WeakMap<Function, number>();
private _thresholds: { timeout: number; errors: number; };
@@ -32,12 +32,12 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
}
dispose(): void {
this._callbacks.dispose();
this._callbacks.clear();
}
get onWillSaveTextDocumentEvent(): Event<vscode.TextDocumentWillSaveEvent> {
return (listener, thisArg, disposables) => {
const remove = this._callbacks.add(listener, thisArg);
const remove = this._callbacks.push([listener, thisArg]);
const result = { dispose: remove };
if (Array.isArray(disposables)) {
disposables.push(result);
@@ -47,7 +47,7 @@ export class ExtHostDocumentSaveParticipant implements ExtHostDocumentSavePartic
}
$participateInSave(resource: URI, reason: SaveReason): TPromise<boolean[]> {
const entries = this._callbacks.entries();
const entries = this._callbacks.toArray();
let didTimeout = false;
let didTimeoutHandle = setTimeout(() => didTimeout = true, this._thresholds.timeout);

View File

@@ -12,7 +12,7 @@ import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/n
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
const hasOwnProperty = Object.hasOwnProperty;
const NO_OP_VOID_PROMISE = TPromise.as<void>(void 0);
const NO_OP_VOID_PROMISE = TPromise.wrap<void>(void 0);
export interface IExtensionMemento {
get<T>(key: string, defaultValue: T): T;
@@ -45,7 +45,7 @@ export interface IExtensionAPI {
export class ExtensionActivationTimes {
public static NONE = new ExtensionActivationTimes(false, -1, -1, -1);
public static readonly NONE = new ExtensionActivationTimes(false, -1, -1, -1);
public readonly startup: boolean;
public readonly codeLoadingTime: number;
@@ -159,9 +159,24 @@ export class FailedExtension extends ActivatedExtension {
export interface IExtensionsActivatorHost {
showMessage(severity: Severity, message: string): void;
actualActivateExtension(extensionDescription: IExtensionDescription, startup: boolean): TPromise<ActivatedExtension>;
actualActivateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): TPromise<ActivatedExtension>;
}
export class ExtensionActivatedByEvent {
constructor(
public readonly startup: boolean,
public readonly activationEvent: string
) { }
}
export class ExtensionActivatedByAPI {
constructor(
public readonly startup: boolean
) { }
}
export type ExtensionActivationReason = ExtensionActivatedByEvent | ExtensionActivatedByAPI;
export class ExtensionsActivator {
private readonly _registry: ExtensionDescriptionRegistry;
@@ -192,23 +207,23 @@ export class ExtensionsActivator {
return this._activatedExtensions[extensionId];
}
public activateByEvent(activationEvent: string, startup: boolean): TPromise<void> {
public activateByEvent(activationEvent: string, reason: ExtensionActivationReason): TPromise<void> {
if (this._alreadyActivatedEvents[activationEvent]) {
return NO_OP_VOID_PROMISE;
}
let activateExtensions = this._registry.getExtensionDescriptionsForActivationEvent(activationEvent);
return this._activateExtensions(activateExtensions, startup, 0).then(() => {
return this._activateExtensions(activateExtensions, reason, 0).then(() => {
this._alreadyActivatedEvents[activationEvent] = true;
});
}
public activateById(extensionId: string, startup: boolean): TPromise<void> {
public activateById(extensionId: string, reason: ExtensionActivationReason): TPromise<void> {
let desc = this._registry.getExtensionDescription(extensionId);
if (!desc) {
throw new Error('Extension `' + extensionId + '` is not known');
}
return this._activateExtensions([desc], startup, 0);
return this._activateExtensions([desc], reason, 0);
}
/**
@@ -252,7 +267,7 @@ export class ExtensionsActivator {
}
}
private _activateExtensions(extensionDescriptions: IExtensionDescription[], startup: boolean, recursionLevel: number): TPromise<void> {
private _activateExtensions(extensionDescriptions: IExtensionDescription[], reason: ExtensionActivationReason, recursionLevel: number): TPromise<void> {
// console.log(recursionLevel, '_activateExtensions: ', extensionDescriptions.map(p => p.id));
if (extensionDescriptions.length === 0) {
return TPromise.as(void 0);
@@ -294,15 +309,15 @@ export class ExtensionsActivator {
if (red.length === 0) {
// Finally reached only leafs!
return TPromise.join(green.map((p) => this._activateExtension(p, startup))).then(_ => void 0);
return TPromise.join(green.map((p) => this._activateExtension(p, reason))).then(_ => void 0);
}
return this._activateExtensions(green, startup, recursionLevel + 1).then(_ => {
return this._activateExtensions(red, startup, recursionLevel + 1);
return this._activateExtensions(green, reason, recursionLevel + 1).then(_ => {
return this._activateExtensions(red, reason, recursionLevel + 1);
});
}
private _activateExtension(extensionDescription: IExtensionDescription, startup: boolean): TPromise<void> {
private _activateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): TPromise<void> {
if (hasOwnProperty.call(this._activatedExtensions, extensionDescription.id)) {
return TPromise.as(void 0);
}
@@ -311,7 +326,7 @@ export class ExtensionsActivator {
return this._activatingExtensions[extensionDescription.id];
}
this._activatingExtensions[extensionDescription.id] = this._host.actualActivateExtension(extensionDescription, startup).then(null, (err) => {
this._activatingExtensions[extensionDescription.id] = this._host.actualActivateExtension(extensionDescription, reason).then(null, (err) => {
this._host.showMessage(Severity.Error, nls.localize('activationError', "Activating extension `{0}` failed: {1}.", extensionDescription.id, err.message));
console.error('Activating extension `' + extensionDescription.id + '` failed: ', err.message);
console.log('Here is the error stack: ', err.stack);

View File

@@ -15,13 +15,14 @@ import { ExtHostStorage } from 'vs/workbench/api/node/extHostStorage';
// {{SQL CARBON EDIT}}
import { createApiFactory, initializeExtensionApi } from 'sql/workbench/api/node/sqlExtHost.api.impl';
import { MainContext, MainThreadExtensionServiceShape, IWorkspaceData, IEnvironment, IInitData, ExtHostExtensionServiceShape, MainThreadTelemetryShape } from './extHost.protocol';
import { IExtensionMemento, ExtensionsActivator, ActivatedExtension, IExtensionAPI, IExtensionContext, EmptyExtension, IExtensionModule, ExtensionActivationTimesBuilder, ExtensionActivationTimes } from 'vs/workbench/api/node/extHostExtensionActivator';
import { Barrier } from 'vs/workbench/services/extensions/node/barrier';
import { IExtensionMemento, ExtensionsActivator, ActivatedExtension, IExtensionAPI, IExtensionContext, EmptyExtension, IExtensionModule, ExtensionActivationTimesBuilder, ExtensionActivationTimes, ExtensionActivationReason, ExtensionActivatedByEvent } from 'vs/workbench/api/node/extHostExtensionActivator';
import { ExtHostThreadService } from 'vs/workbench/services/thread/node/extHostThreadService';
import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { realpath } from 'fs';
import { TernarySearchTree } from 'vs/base/common/map';
import { Barrier } from 'vs/base/common/async';
import { ILogService } from 'vs/platform/log/common/log';
class ExtensionMemento implements IExtensionMemento {
@@ -118,6 +119,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
private readonly _storage: ExtHostStorage;
private readonly _storagePath: ExtensionStoragePath;
private readonly _proxy: MainThreadExtensionServiceShape;
private readonly _logService: ILogService;
private _activator: ExtensionsActivator;
private _extensionPathIndex: TPromise<TernarySearchTree<IExtensionDescription>>;
/**
@@ -126,11 +128,13 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
constructor(initData: IInitData,
threadService: ExtHostThreadService,
extHostWorkspace: ExtHostWorkspace,
extHostConfiguration: ExtHostConfiguration
extHostConfiguration: ExtHostConfiguration,
logService: ILogService
) {
this._barrier = new Barrier();
this._registry = new ExtensionDescriptionRegistry(initData.extensions);
this._threadService = threadService;
this._logService = logService;
this._mainThreadTelemetry = threadService.get(MainContext.MainThreadTelemetry);
this._storage = new ExtHostStorage(threadService);
this._storagePath = new ExtensionStoragePath(initData.workspace, initData.environment);
@@ -138,7 +142,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
this._activator = null;
// initialize API first (i.e. do not release barrier until the API is initialized)
const apiFactory = createApiFactory(initData, threadService, extHostWorkspace, extHostConfiguration, this);
const apiFactory = createApiFactory(initData, threadService, extHostWorkspace, extHostConfiguration, this, logService);
initializeExtensionApi(this, apiFactory).then(() => {
@@ -158,8 +162,8 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
}
},
actualActivateExtension: (extensionDescription: IExtensionDescription, startup: boolean): TPromise<ActivatedExtension> => {
return this._activateExtension(extensionDescription, startup);
actualActivateExtension: (extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): TPromise<ActivatedExtension> => {
return this._activateExtension(extensionDescription, reason);
}
});
@@ -179,18 +183,19 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
}
public activateByEvent(activationEvent: string, startup: boolean): TPromise<void> {
const reason = new ExtensionActivatedByEvent(startup, activationEvent);
if (this._barrier.isOpen()) {
return this._activator.activateByEvent(activationEvent, startup);
return this._activator.activateByEvent(activationEvent, reason);
} else {
return this._barrier.wait().then(() => this._activator.activateByEvent(activationEvent, startup));
return this._barrier.wait().then(() => this._activator.activateByEvent(activationEvent, reason));
}
}
public activateById(extensionId: string, startup: boolean): TPromise<void> {
public activateById(extensionId: string, reason: ExtensionActivationReason): TPromise<void> {
if (this._barrier.isOpen()) {
return this._activator.activateById(extensionId, startup);
return this._activator.activateById(extensionId, reason);
} else {
return this._barrier.wait().then(() => this._activator.activateById(extensionId, startup));
return this._barrier.wait().then(() => this._activator.activateById(extensionId, reason));
}
}
@@ -273,12 +278,17 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
return result;
}
public addMessage(extensionId: string, severity: Severity, message: string): void {
this._proxy.$addMessage(extensionId, severity, message);
}
// --- impl
private _activateExtension(extensionDescription: IExtensionDescription, startup: boolean): TPromise<ActivatedExtension> {
return this._doActivateExtension(extensionDescription, startup).then((activatedExtension) => {
private _activateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): TPromise<ActivatedExtension> {
return this._doActivateExtension(extensionDescription, reason).then((activatedExtension) => {
const activationTimes = activatedExtension.activationTimes;
this._proxy.$onExtensionActivated(extensionDescription.id, activationTimes.startup, activationTimes.codeLoadingTime, activationTimes.activateCallTime, activationTimes.activateResolvedTime);
let activationEvent = (reason instanceof ExtensionActivatedByEvent ? reason.activationEvent : null);
this._proxy.$onExtensionActivated(extensionDescription.id, activationTimes.startup, activationTimes.codeLoadingTime, activationTimes.activateCallTime, activationTimes.activateResolvedTime, activationEvent);
return activatedExtension;
}, (err) => {
this._proxy.$onExtensionActivationFailed(extensionDescription.id);
@@ -286,7 +296,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
});
}
private _doActivateExtension(extensionDescription: IExtensionDescription, startup: boolean): TPromise<ActivatedExtension> {
private _doActivateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): TPromise<ActivatedExtension> {
let event = getTelemetryActivationEvent(extensionDescription);
/* __GDPR__
"activatePlugin" : {
@@ -301,12 +311,14 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
return TPromise.as(new EmptyExtension(ExtensionActivationTimes.NONE));
}
const activationTimesBuilder = new ExtensionActivationTimesBuilder(startup);
this._logService.info(`ExtensionService#_doActivateExtension ${extensionDescription.id} ${JSON.stringify(reason)}`);
const activationTimesBuilder = new ExtensionActivationTimesBuilder(reason.startup);
return TPromise.join<any>([
loadCommonJSModule(extensionDescription.main, activationTimesBuilder),
loadCommonJSModule(this._logService, extensionDescription.main, activationTimesBuilder),
this._loadExtensionContext(extensionDescription)
]).then(values => {
return ExtHostExtensionService._callActivate(<IExtensionModule>values[0], <IExtensionContext>values[1], activationTimesBuilder);
return ExtHostExtensionService._callActivate(this._logService, extensionDescription.id, <IExtensionModule>values[0], <IExtensionContext>values[1], activationTimesBuilder);
}, (errors: any[]) => {
// Avoid failing with an array of errors, fail with a single error
if (errors[0]) {
@@ -324,6 +336,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
let globalState = new ExtensionMemento(extensionDescription.id, true, this._storage);
let workspaceState = new ExtensionMemento(extensionDescription.id, false, this._storage);
this._logService.trace(`ExtensionService#loadExtensionContext ${extensionDescription.id}`);
return TPromise.join([
globalState.whenReady,
workspaceState.whenReady,
@@ -340,22 +353,23 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
});
}
private static _callActivate(extensionModule: IExtensionModule, context: IExtensionContext, activationTimesBuilder: ExtensionActivationTimesBuilder): TPromise<ActivatedExtension> {
private static _callActivate(logService: ILogService, extensionId: string, extensionModule: IExtensionModule, context: IExtensionContext, activationTimesBuilder: ExtensionActivationTimesBuilder): Thenable<ActivatedExtension> {
// Make sure the extension's surface is not undefined
extensionModule = extensionModule || {
activate: undefined,
deactivate: undefined
};
return this._callActivateOptional(extensionModule, context, activationTimesBuilder).then((extensionExports) => {
return this._callActivateOptional(logService, extensionId, extensionModule, context, activationTimesBuilder).then((extensionExports) => {
return new ActivatedExtension(false, activationTimesBuilder.build(), extensionModule, extensionExports, context.subscriptions);
});
}
private static _callActivateOptional(extensionModule: IExtensionModule, context: IExtensionContext, activationTimesBuilder: ExtensionActivationTimesBuilder): TPromise<IExtensionAPI> {
private static _callActivateOptional(logService: ILogService, extensionId: string, extensionModule: IExtensionModule, context: IExtensionContext, activationTimesBuilder: ExtensionActivationTimesBuilder): Thenable<IExtensionAPI> {
if (typeof extensionModule.activate === 'function') {
try {
activationTimesBuilder.activateCallStart();
logService.trace(`ExtensionService#_callActivateOptional ${extensionId}`);
const activateResult: TPromise<IExtensionAPI> = extensionModule.activate.apply(global, [context]);
activationTimesBuilder.activateCallStop();
@@ -380,9 +394,10 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
}
}
function loadCommonJSModule<T>(modulePath: string, activationTimesBuilder: ExtensionActivationTimesBuilder): TPromise<T> {
function loadCommonJSModule<T>(logService: ILogService, modulePath: string, activationTimesBuilder: ExtensionActivationTimesBuilder): TPromise<T> {
let r: T = null;
activationTimesBuilder.codeLoadingStart();
logService.info(`ExtensionService#loadCommonJSModule ${modulePath}`);
try {
r = require.__$__nodeRequire<T>(modulePath);
} catch (e) {
@@ -400,13 +415,7 @@ function getTelemetryActivationEvent(extensionDescription: IExtensionDescription
"name": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
"publisherDisplayName": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
"activationEvents": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"isBuiltin": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"${wildcard}": [
{
"${prefix}": "contribution.",
"${classification}": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
]
"isBuiltin": { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
}
*/
let event = {
@@ -417,34 +426,5 @@ function getTelemetryActivationEvent(extensionDescription: IExtensionDescription
isBuiltin: extensionDescription.isBuiltin
};
for (let contribution in extensionDescription.contributes) {
let contributionDetails = extensionDescription.contributes[contribution];
if (!contributionDetails) {
continue;
}
switch (contribution) {
case 'debuggers':
let types = contributionDetails.reduce((p, c) => p ? p + ',' + c['type'] : c['type'], '');
event['contribution.debuggers'] = types;
break;
case 'grammars':
let grammers = contributionDetails.reduce((p, c) => p ? p + ',' + c['language'] : c['language'], '');
event['contribution.grammars'] = grammers;
break;
case 'languages':
let languages = contributionDetails.reduce((p, c) => p ? p + ',' + c['id'] : c['id'], '');
event['contribution.languages'] = languages;
break;
case 'tmSnippets':
let tmSnippets = contributionDetails.reduce((p, c) => p ? p + ',' + c['languageId'] : c['languageId'], '');
event['contribution.tmSnippets'] = tmSnippets;
break;
default:
event[`contribution.${contribution}`] = true;
}
}
return event;
}

View File

@@ -15,7 +15,7 @@ import * as modes from 'vs/editor/common/modes';
import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService';
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands';
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
import { ExtHostDiagnostics, DiagnosticCollection } from 'vs/workbench/api/node/extHostDiagnostics';
import { asWinJsPromise } from 'vs/base/common/async';
import { MainContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, ObjectIdentifier, IRawColorInfo, IMainContext, IExtHostSuggestResult, IExtHostSuggestion, IWorkspaceSymbols, IWorkspaceSymbol, IdObject } from './extHost.protocol';
import { regExpLeadsToEndlessLoop } from 'vs/base/common/strings';
@@ -255,7 +255,11 @@ class ReferenceAdapter {
}
}
class QuickFixAdapter {
export interface CustomCodeAction extends modes.CodeAction {
_isSynthetic?: boolean;
}
class CodeActionAdapter {
private _documents: ExtHostDocuments;
private _commands: CommandsConverter;
@@ -269,7 +273,7 @@ class QuickFixAdapter {
this._provider = provider;
}
provideCodeActions(resource: URI, range: IRange): TPromise<modes.Command[]> {
provideCodeActions(resource: URI, range: IRange): TPromise<modes.CodeAction[]> {
const doc = this._documents.getDocumentData(resource).document;
const ran = <vscode.Range>TypeConverters.toRange(range);
@@ -285,13 +289,45 @@ class QuickFixAdapter {
}
});
return asWinJsPromise(token => this._provider.provideCodeActions(doc, ran, { diagnostics: allDiagnostics }, token)).then(commands => {
if (!Array.isArray(commands)) {
return asWinJsPromise(token => this._provider.provideCodeActions2
? this._provider.provideCodeActions2(doc, ran, { diagnostics: allDiagnostics }, token)
: this._provider.provideCodeActions(doc, ran, { diagnostics: allDiagnostics }, token)
).then(commandsOrActions => {
if (isFalsyOrEmpty(commandsOrActions)) {
return undefined;
}
return commands.map(command => this._commands.toInternal(command));
const result: CustomCodeAction[] = [];
for (const candidate of commandsOrActions) {
if (!candidate) {
continue;
}
if (CodeActionAdapter._isCommand(candidate)) {
// old school: synthetic code action
result.push({
_isSynthetic: true,
title: candidate.title,
command: this._commands.toInternal(candidate),
});
} else {
// new school: convert code action
result.push({
title: candidate.title,
command: candidate.command && this._commands.toInternal(candidate.command),
diagnostics: candidate.diagnostics && candidate.diagnostics.map(DiagnosticCollection.toMarkerData),
edits: Array.isArray(candidate.edits)
? TypeConverters.WorkspaceEdit.fromTextEdits(resource, candidate.edits)
: candidate.edits && TypeConverters.WorkspaceEdit.from(candidate.edits),
});
}
}
return result;
});
}
private static _isCommand(thing: any): thing is vscode.Command {
return typeof (<vscode.Command>thing).command === 'string' && typeof (<vscode.Command>thing).title === 'string';
}
}
class DocumentFormattingAdapter {
@@ -382,13 +418,23 @@ class NavigateTypeAdapter {
return asWinJsPromise(token => this._provider.provideWorkspaceSymbols(search, token)).then(value => {
if (!isFalsyOrEmpty(value)) {
for (const item of value) {
if (!item) {
// drop
continue;
}
if (!item.name) {
console.warn('INVALID SymbolInformation, lacks name', item);
continue;
}
const symbol = IdObject.mixin(TypeConverters.fromSymbolInformation(item));
this._symbolCache[symbol._id] = item;
result.symbols.push(symbol);
}
}
}).then(() => {
this._resultCache[result._id] = [result.symbols[0]._id, result.symbols[result.symbols.length - 1]._id];
if (result.symbols.length > 0) {
this._resultCache[result._id] = [result.symbols[0]._id, result.symbols[result.symbols.length - 1]._id];
}
return result;
});
}
@@ -438,30 +484,22 @@ class RenameAdapter {
if (!value) {
return undefined;
}
let result = <modes.WorkspaceEdit>{
edits: []
};
for (let entry of value.entries()) {
let [uri, textEdits] = entry;
for (let textEdit of textEdits) {
result.edits.push({
resource: uri,
newText: textEdit.newText,
range: TypeConverters.fromRange(textEdit.range)
});
}
}
return result;
return TypeConverters.WorkspaceEdit.from(value);
}, err => {
if (typeof err === 'string') {
return <modes.WorkspaceEdit>{
edits: undefined,
rejectReason: err
};
} else if (err instanceof Error && typeof err.message === 'string') {
return <modes.WorkspaceEdit>{
edits: undefined,
rejectReason: err.message
};
} else {
// generic error
return TPromise.wrapError<modes.WorkspaceEdit>(err);
}
return TPromise.wrapError<modes.WorkspaceEdit>(err);
});
}
}
@@ -707,9 +745,7 @@ class LinkProviderAdapter {
class ColorProviderAdapter {
constructor(
private _proxy: MainThreadLanguageFeaturesShape,
private _documents: ExtHostDocuments,
private _colorFormatCache: Map<string, number>,
private _provider: vscode.DocumentColorProvider
) { }
@@ -742,7 +778,7 @@ class ColorProviderAdapter {
}
type Adapter = OutlineAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter
| DocumentHighlightAdapter | ReferenceAdapter | QuickFixAdapter | DocumentFormattingAdapter
| DocumentHighlightAdapter | ReferenceAdapter | CodeActionAdapter | DocumentFormattingAdapter
| RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter
| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter | TypeDefinitionAdapter | ColorProviderAdapter;
@@ -756,7 +792,6 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
private _heapService: ExtHostHeapService;
private _diagnostics: ExtHostDiagnostics;
private _adapter = new Map<number, Adapter>();
private _colorFormatCache = new Map<string, number>();
constructor(
mainContext: IMainContext,
@@ -908,13 +943,13 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerCodeActionProvider(selector: vscode.DocumentSelector, provider: vscode.CodeActionProvider): vscode.Disposable {
const handle = this._nextHandle();
this._adapter.set(handle, new QuickFixAdapter(this._documents, this._commands.converter, this._diagnostics, provider));
this._adapter.set(handle, new CodeActionAdapter(this._documents, this._commands.converter, this._diagnostics, provider));
this._proxy.$registerQuickFixSupport(handle, selector);
return this._createDisposable(handle);
}
$provideCodeActions(handle: number, resource: URI, range: IRange): TPromise<modes.Command[]> {
return this._withAdapter(handle, QuickFixAdapter, adapter => adapter.provideCodeActions(resource, range));
$provideCodeActions(handle: number, resource: URI, range: IRange): TPromise<modes.CodeAction[]> {
return this._withAdapter(handle, CodeActionAdapter, adapter => adapter.provideCodeActions(resource, range));
}
// --- formatting
@@ -1039,7 +1074,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
registerColorProvider(selector: vscode.DocumentSelector, provider: vscode.DocumentColorProvider): vscode.Disposable {
const handle = this._nextHandle();
this._adapter.set(handle, new ColorProviderAdapter(this._proxy, this._documents, this._colorFormatCache, provider));
this._adapter.set(handle, new ColorProviderAdapter(this._documents, provider));
this._proxy.$registerDocumentColorProvider(handle, selector);
return this._createDisposable(handle);
}

View File

@@ -9,8 +9,7 @@ import vscode = require('vscode');
import { MainContext, MainThreadMessageServiceShape, MainThreadMessageOptions, IMainContext } from './extHost.protocol';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
function isMessageItem<T>(item: any): item is vscode.MessageItem {
function isMessageItem(item: any): item is vscode.MessageItem {
return item && item.title;
}

View File

@@ -16,6 +16,8 @@ import { MainContext, MainThreadSCMShape, SCMRawResource, SCMRawResourceSplice,
import { sortedDiff } from 'vs/base/common/arrays';
import { comparePaths } from 'vs/base/common/comparers';
import * as vscode from 'vscode';
import { ISplice } from 'vs/base/common/sequence';
import { ILogService } from 'vs/platform/log/common/log';
type ProviderHandle = number;
type GroupHandle = number;
@@ -127,6 +129,17 @@ export class ExtHostSCMInputBox {
return this._onDidChange.event;
}
private _placeholder: string = '';
get placeholder(): string {
return this._placeholder;
}
set placeholder(placeholder: string) {
this._proxy.$setInputBoxPlaceholder(this._sourceControlHandle, placeholder);
this._placeholder = placeholder;
}
constructor(private _proxy: MainThreadSCMShape, private _sourceControlHandle: number) {
// noop
}
@@ -147,7 +160,6 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG
private _resourceHandlePool: number = 0;
private _resourceStates: vscode.SourceControlResourceState[] = [];
private _resourceStatesRollingDisposables: { (): void }[] = [];
private _resourceStatesMap: Map<ResourceStateHandle, vscode.SourceControlResourceState> = new Map<ResourceStateHandle, vscode.SourceControlResourceState>();
private _resourceStatesCommandsMap: Map<ResourceStateHandle, vscode.Command> = new Map<ResourceStateHandle, vscode.Command>();
@@ -210,65 +222,63 @@ class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceG
_takeResourceStateSnapshot(): SCMRawResourceSplice[] {
const snapshot = [...this._resourceStates].sort(compareResourceStates);
const diffs = sortedDiff(this._resourceSnapshot, snapshot, compareResourceStates);
const handlesToDelete: number[] = [];
const splices = diffs.map(diff => {
const { start, deleteCount } = diff;
const handles: number[] = [];
const splices = diffs.map<ISplice<{ rawResource: SCMRawResource, handle: number }>>(diff => {
const toInsert = diff.toInsert.map(r => {
const handle = this._resourceHandlePool++;
this._resourceStatesMap.set(handle, r);
const rawResources = diff.inserted
.map(r => {
const handle = this._resourceHandlePool++;
this._resourceStatesMap.set(handle, r);
handles.push(handle);
const sourceUri = r.resourceUri.toString();
const iconPath = getIconPath(r.decorations);
const lightIconPath = r.decorations && getIconPath(r.decorations.light) || iconPath;
const darkIconPath = r.decorations && getIconPath(r.decorations.dark) || iconPath;
const icons: string[] = [];
const sourceUri = r.resourceUri.toString();
const iconPath = getIconPath(r.decorations);
const lightIconPath = r.decorations && getIconPath(r.decorations.light) || iconPath;
const darkIconPath = r.decorations && getIconPath(r.decorations.dark) || iconPath;
const icons: string[] = [];
if (r.command) {
this._resourceStatesCommandsMap.set(handle, r.command);
}
if (r.command) {
this._resourceStatesCommandsMap.set(handle, r.command);
}
if (lightIconPath || darkIconPath) {
icons.push(lightIconPath);
}
if (lightIconPath || darkIconPath) {
icons.push(lightIconPath);
}
if (darkIconPath !== lightIconPath) {
icons.push(darkIconPath);
}
if (darkIconPath !== lightIconPath) {
icons.push(darkIconPath);
}
const tooltip = (r.decorations && r.decorations.tooltip) || '';
const strikeThrough = r.decorations && !!r.decorations.strikeThrough;
const faded = r.decorations && !!r.decorations.faded;
const tooltip = (r.decorations && r.decorations.tooltip) || '';
const strikeThrough = r.decorations && !!r.decorations.strikeThrough;
const faded = r.decorations && !!r.decorations.faded;
const source = r.decorations && r.decorations.source || undefined;
const letter = r.decorations && r.decorations.letter || undefined;
const color = r.decorations && r.decorations.color || undefined;
const source = r.decorations && r.decorations.source || undefined;
const letter = r.decorations && r.decorations.letter || undefined;
const color = r.decorations && r.decorations.color || undefined;
const rawResource = [handle, sourceUri, icons, tooltip, strikeThrough, faded, source, letter, color] as SCMRawResource;
return [handle, sourceUri, icons, tooltip, strikeThrough, faded, source, letter, color] as SCMRawResource;
});
return { rawResource, handle };
});
handlesToDelete.push(...this._handlesSnapshot.splice(start, deleteCount, ...handles));
return [start, deleteCount, rawResources] as SCMRawResourceSplice;
return { start: diff.start, deleteCount: diff.deleteCount, toInsert };
});
const disposable = () => handlesToDelete.forEach(handle => {
this._resourceStatesMap.delete(handle);
this._resourceStatesCommandsMap.delete(handle);
});
const rawResourceSplices = splices
.map(({ start, deleteCount, toInsert }) => [start, deleteCount, toInsert.map(i => i.rawResource)] as SCMRawResourceSplice);
this._resourceStatesRollingDisposables.push(disposable);
const reverseSplices = splices.reverse();
while (this._resourceStatesRollingDisposables.length >= 10) {
this._resourceStatesRollingDisposables.shift()();
for (const { start, deleteCount, toInsert } of reverseSplices) {
const handles = toInsert.map(i => i.handle);
const handlesToDelete = this._handlesSnapshot.splice(start, deleteCount, ...handles);
for (const handle of handlesToDelete) {
this._resourceStatesMap.delete(handle);
this._resourceStatesCommandsMap.delete(handle);
}
}
this._resourceSnapshot = snapshot;
return splices;
return rawResourceSplices;
}
dispose(): void {
@@ -434,7 +444,8 @@ export class ExtHostSCM {
constructor(
mainContext: IMainContext,
private _commands: ExtHostCommands
private _commands: ExtHostCommands,
@ILogService private logService: ILogService
) {
this._proxy = mainContext.get(MainContext.MainThreadSCM);
@@ -478,6 +489,8 @@ export class ExtHostSCM {
}
createSourceControl(extension: IExtensionDescription, id: string, label: string, rootUri: vscode.Uri | undefined): vscode.SourceControl {
this.logService.trace('ExtHostSCM#createSourceControl', extension.id, id, label, rootUri);
const handle = ExtHostSCM._handlePool++;
const sourceControl = new ExtHostSourceControl(this._proxy, this._commands, id, label, rootUri);
this._sourceControls.set(handle, sourceControl);
@@ -491,6 +504,8 @@ export class ExtHostSCM {
// Deprecated
getLastInputBox(extension: IExtensionDescription): ExtHostSCMInputBox {
this.logService.trace('ExtHostSCM#getLastInputBox', extension.id);
const sourceControls = this._sourceControlsByExtension.get(extension.id);
const sourceControl = sourceControls && sourceControls[sourceControls.length - 1];
const inputBox = sourceControl && sourceControl.inputBox;
@@ -499,6 +514,8 @@ export class ExtHostSCM {
}
$provideOriginalResource(sourceControlHandle: number, uri: URI): TPromise<URI> {
this.logService.trace('ExtHostSCM#$provideOriginalResource', sourceControlHandle, uri);
const sourceControl = this._sourceControls.get(sourceControlHandle);
if (!sourceControl || !sourceControl.quickDiffProvider) {
@@ -512,6 +529,8 @@ export class ExtHostSCM {
}
$onInputBoxValueChange(sourceControlHandle: number, value: string): TPromise<void> {
this.logService.trace('ExtHostSCM#$onInputBoxValueChange', sourceControlHandle);
const sourceControl = this._sourceControls.get(sourceControlHandle);
if (!sourceControl) {
@@ -523,6 +542,8 @@ export class ExtHostSCM {
}
async $executeResourceCommand(sourceControlHandle: number, groupHandle: number, handle: number): TPromise<void> {
this.logService.trace('ExtHostSCM#$executeResourceCommand', sourceControlHandle, groupHandle, handle);
const sourceControl = this._sourceControls.get(sourceControlHandle);
if (!sourceControl) {

View File

@@ -19,9 +19,6 @@ import * as types from 'vs/workbench/api/node/extHostTypes';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import * as vscode from 'vscode';
interface StringMap<V> {
[key: string]: V;
}
/*
namespace ProblemPattern {
@@ -431,7 +428,7 @@ export class ExtHostTask implements ExtHostTaskShape {
this._extHostWorkspace = extHostWorkspace;
this._handleCounter = 0;
this._handlers = new Map<number, HandlerData>();
};
}
public registerTaskProvider(extension: IExtensionDescription, provider: vscode.TaskProvider): vscode.Disposable {
if (!provider) {
@@ -463,4 +460,4 @@ export class ExtHostTask implements ExtHostTaskShape {
private nextHandle(): number {
return this._handleCounter++;
}
}
}

View File

@@ -20,7 +20,7 @@ import { IRange } from 'vs/editor/common/core/range';
export class TextEditorDecorationType implements vscode.TextEditorDecorationType {
private static _Keys = new IdGenerator('TextEditorDecorationType');
private static readonly _Keys = new IdGenerator('TextEditorDecorationType');
private _proxy: MainThreadEditorsShape;
public key: string;

View File

@@ -20,13 +20,13 @@ export class ExtHostEditors implements ExtHostEditorsShape {
private readonly _onDidChangeTextEditorSelection = new Emitter<vscode.TextEditorSelectionChangeEvent>();
private readonly _onDidChangeTextEditorOptions = new Emitter<vscode.TextEditorOptionsChangeEvent>();
private readonly _onDidChangeTextEditorViewColumn = new Emitter<vscode.TextEditorViewColumnChangeEvent>();
private readonly _onDidChangeActiveTextEditor = new Emitter<vscode.TextEditor>();
private readonly _onDidChangeActiveTextEditor = new Emitter<vscode.TextEditor | undefined>();
private readonly _onDidChangeVisibleTextEditors = new Emitter<vscode.TextEditor[]>();
readonly onDidChangeTextEditorSelection: Event<vscode.TextEditorSelectionChangeEvent> = this._onDidChangeTextEditorSelection.event;
readonly onDidChangeTextEditorOptions: Event<vscode.TextEditorOptionsChangeEvent> = this._onDidChangeTextEditorOptions.event;
readonly onDidChangeTextEditorViewColumn: Event<vscode.TextEditorViewColumnChangeEvent> = this._onDidChangeTextEditorViewColumn.event;
readonly onDidChangeActiveTextEditor: Event<vscode.TextEditor> = this._onDidChangeActiveTextEditor.event;
readonly onDidChangeActiveTextEditor: Event<vscode.TextEditor | undefined> = this._onDidChangeActiveTextEditor.event;
readonly onDidChangeVisibleTextEditors: Event<vscode.TextEditor[]> = this._onDidChangeVisibleTextEditors.event;

View File

@@ -7,17 +7,15 @@
import { localize } from 'vs/nls';
import * as vscode from 'vscode';
import URI from 'vs/base/common/uri';
import { distinct } from 'vs/base/common/arrays';
import { debounceEvent } from 'vs/base/common/event';
import { TPromise } from 'vs/base/common/winjs.base';
import { Disposable } from 'vs/base/common/lifecycle';
import { ExtHostTreeViewsShape, MainThreadTreeViewsShape } from './extHost.protocol';
import { ITreeItem, TreeViewItemHandleArg } from 'vs/workbench/common/views';
import { TreeItemCollapsibleState } from './extHostTypes';
import { ExtHostCommands, CommandsConverter } from 'vs/workbench/api/node/extHostCommands';
import { asWinJsPromise } from 'vs/base/common/async';
type TreeItemHandle = number;
type TreeItemHandle = string;
export class ExtHostTreeViews implements ExtHostTreeViewsShape {
@@ -56,7 +54,7 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
return treeView.getTreeItems();
}
$getChildren(treeViewId: string, treeItemHandle?: number): TPromise<ITreeItem[]> {
$getChildren(treeViewId: string, treeItemHandle?: string): TPromise<ITreeItem[]> {
const treeView = this.treeViews.get(treeViewId);
if (!treeView) {
return TPromise.wrapError<ITreeItem[]>(new Error(localize('treeView.notRegistered', 'No tree view with id \'{0}\' registered.', treeViewId)));
@@ -70,13 +68,18 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
}
}
interface TreeNode {
index: number;
handle: TreeItemHandle;
parent: TreeItemHandle;
children: TreeItemHandle[];
}
class ExtHostTreeView<T> extends Disposable {
private _itemHandlePool = 0;
private extElementsMap: Map<TreeItemHandle, T> = new Map<TreeItemHandle, T>();
private itemHandlesMap: Map<T, TreeItemHandle> = new Map<T, TreeItemHandle>();
private extChildrenElementsMap: Map<T, T[]> = new Map<T, T[]>();
private static ROOT_HANDLE = '0';
private elements: Map<TreeItemHandle, T> = new Map<TreeItemHandle, T>();
private nodes: Map<T, TreeNode> = new Map<T, TreeNode>();
constructor(private viewId: string, private dataProvider: vscode.TreeDataProvider<T>, private proxy: MainThreadTreeViewsShape, private commands: CommandsConverter) {
super();
@@ -87,12 +90,9 @@ class ExtHostTreeView<T> extends Disposable {
}
getTreeItems(): TPromise<ITreeItem[]> {
this.extChildrenElementsMap.clear();
this.extElementsMap.clear();
this.itemHandlesMap.clear();
this.clearAll();
return asWinJsPromise(() => this.dataProvider.getChildren())
.then(elements => this.processAndMapElements(elements));
.then(elements => this.resolveElements(elements));
}
getChildren(treeItemHandle: TreeItemHandle): TPromise<ITreeItem[]> {
@@ -104,77 +104,86 @@ class ExtHostTreeView<T> extends Disposable {
}
return asWinJsPromise(() => this.dataProvider.getChildren(extElement))
.then(childrenElements => this.processAndMapElements(childrenElements));
.then(childrenElements => this.resolveElements(childrenElements, treeItemHandle))
.then(childrenItems => {
this.nodes.get(extElement).children = childrenItems.map(c => c.handle);
return childrenItems;
});
}
getExtensionElement(treeItemHandle: TreeItemHandle): T {
return this.extElementsMap.get(treeItemHandle);
return this.elements.get(treeItemHandle);
}
private _refresh(elements: T[]): void {
const hasRoot = elements.some(element => !element);
if (hasRoot) {
this.proxy.$refresh(this.viewId, []);
this.proxy.$refresh(this.viewId);
} else {
const itemHandles = distinct(elements.map(element => this.itemHandlesMap.get(element))
.filter(itemHandle => !!itemHandle));
if (itemHandles.length) {
this.proxy.$refresh(this.viewId, itemHandles);
const handlesToUpdate = this.getHandlesToUpdate(elements);
if (handlesToUpdate.length) {
this._refreshHandles(handlesToUpdate);
}
}
}
private processAndMapElements(elements: T[]): TPromise<ITreeItem[]> {
private resolveElements(elements: T[], parentHandle?: TreeItemHandle): TPromise<ITreeItem[]> {
if (elements && elements.length) {
return TPromise.join(
elements.filter(element => !!element)
.map(element => {
if (this.extChildrenElementsMap.has(element)) {
return TPromise.wrapError<ITreeItem>(new Error(localize('treeView.duplicateElement', 'Element {0} is already registered', element)));
}
return this.resolveElement(element);
.map((element, index) => {
return this.resolveElement(element, index, parentHandle)
.then(treeItem => {
if (treeItem) {
this.nodes.set(element, {
index,
handle: treeItem.handle,
parent: parentHandle,
children: void 0
});
if (this.elements.has(treeItem.handle)) {
return TPromise.wrapError<ITreeItem>(new Error(localize('treeView.duplicateElement', 'Element {0} is already registered', element)));
}
this.elements.set(treeItem.handle, element);
}
return treeItem;
});
}))
.then(treeItems => treeItems.filter(treeItem => !!treeItem));
}
return TPromise.as([]);
}
private resolveElement(element: T): TPromise<ITreeItem> {
private resolveElement(element: T, index: number, parentHandle?: TreeItemHandle): TPromise<ITreeItem> {
return asWinJsPromise(() => this.dataProvider.getTreeItem(element))
.then(extTreeItem => {
const treeItem = this.massageTreeItem(extTreeItem);
if (treeItem) {
this.itemHandlesMap.set(element, treeItem.handle);
this.extElementsMap.set(treeItem.handle, element);
if (treeItem.collapsibleState === TreeItemCollapsibleState.Expanded) {
return this.getChildren(treeItem.handle).then(children => {
treeItem.children = children;
return treeItem;
});
} else {
return treeItem;
}
}
return null;
});
.then(extTreeItem => this.massageTreeItem(element, extTreeItem, index, parentHandle));
}
private massageTreeItem(extensionTreeItem: vscode.TreeItem): ITreeItem {
private massageTreeItem(element: T, extensionTreeItem: vscode.TreeItem, index: number, parentHandle: TreeItemHandle): ITreeItem {
if (!extensionTreeItem) {
return null;
}
const icon = this.getLightIconPath(extensionTreeItem);
const label = extensionTreeItem.label;
const handle = typeof element === 'string' ? element : this.generateHandle(label, index, parentHandle);
return {
handle: ++this._itemHandlePool,
label: extensionTreeItem.label,
handle,
parentHandle,
label,
command: extensionTreeItem.command ? this.commands.toInternal(extensionTreeItem.command) : void 0,
contextValue: extensionTreeItem.contextValue,
icon,
iconDark: this.getDarkIconPath(extensionTreeItem) || icon,
collapsibleState: extensionTreeItem.collapsibleState,
collapsibleState: extensionTreeItem.collapsibleState
};
}
private generateHandle(label: string, index: number, parentHandle: TreeItemHandle): TreeItemHandle {
parentHandle = parentHandle ? parentHandle : ExtHostTreeView.ROOT_HANDLE;
label = label.indexOf('/') !== -1 ? label.replace('/', '//') : label;
return `${parentHandle}/${index}:${label}`;
}
private getLightIconPath(extensionTreeItem: vscode.TreeItem): string {
if (extensionTreeItem.iconPath) {
if (typeof extensionTreeItem.iconPath === 'string' || extensionTreeItem.iconPath instanceof URI) {
@@ -199,29 +208,107 @@ class ExtHostTreeView<T> extends Disposable {
return URI.file(iconPath).toString();
}
private clearChildren(extElement: T): void {
const children = this.extChildrenElementsMap.get(extElement);
if (children) {
for (const child of children) {
this.clearElement(child);
private getHandlesToUpdate(elements: T[]): TreeItemHandle[] {
const elementsToUpdate = new Set<TreeItemHandle>();
for (const element of elements) {
let elementNode = this.nodes.get(element);
if (elementNode && !elementsToUpdate.has(elementNode.handle)) {
// check if an ancestor of extElement is already in the elements to update list
let currentNode = elementNode;
while (currentNode && currentNode.parent && !elementsToUpdate.has(currentNode.parent)) {
const parentElement = this.elements.get(currentNode.parent);
currentNode = this.nodes.get(parentElement);
}
if (!currentNode.parent) {
elementsToUpdate.add(elementNode.handle);
}
}
this.extChildrenElementsMap.delete(extElement);
}
const handlesToUpdate: TreeItemHandle[] = [];
// Take only top level elements
elementsToUpdate.forEach((handle) => {
const element = this.elements.get(handle);
let node = this.nodes.get(element);
if (node && !elementsToUpdate.has(node.parent)) {
handlesToUpdate.push(handle);
}
});
return handlesToUpdate;
}
private clearElement(extElement: T): void {
this.clearChildren(extElement);
private _refreshHandles(itemHandles: TreeItemHandle[]): TPromise<void> {
const itemsToRefresh: { [handle: string]: ITreeItem } = {};
const promises: TPromise<void>[] = [];
itemHandles.forEach(treeItemHandle => {
const extElement = this.getExtensionElement(treeItemHandle);
const node = this.nodes.get(extElement);
const promise = this.resolveElement(extElement, node.index, node.parent)
.then(treeItem => {
if (treeItemHandle !== treeItem.handle) {
// Update caches if handle changes
this.updateCaches(node, treeItem, extElement);
}
itemsToRefresh[treeItemHandle] = treeItem;
});
promises.push(promise);
});
return TPromise.join(promises)
.then(treeItems => {
this.proxy.$refresh(this.viewId, itemsToRefresh);
});
}
const treeItemhandle = this.itemHandlesMap.get(extElement);
this.itemHandlesMap.delete(extElement);
if (treeItemhandle) {
this.extElementsMap.delete(treeItemhandle);
private updateCaches(node: TreeNode, treeItem: ITreeItem, element: T): void {
if (node.parent) {
// Update parent's children handles
const parentElement = this.getExtensionElement(node.parent);
const parentNode = this.nodes.get(parentElement);
parentNode.children[node.index] = treeItem.handle;
}
// Update elements map
this.elements.delete(node.handle);
this.elements.set(treeItem.handle, element);
// Update node
node.handle = treeItem.handle;
}
private clearChildren(element: T): void {
let node = this.nodes.get(element);
if (node.children) {
for (const childHandle of node.children) {
const childEleement = this.elements.get(childHandle);
if (childEleement) {
this.clear(childEleement);
}
}
}
node.children = void 0;
}
private clear(element: T): void {
let node = this.nodes.get(element);
if (node.children) {
for (const childHandle of node.children) {
const childEleement = this.elements.get(childHandle);
if (childEleement) {
this.clear(childEleement);
}
}
}
this.nodes.delete(element);
this.elements.delete(node.handle);
}
private clearAll(): void {
this.elements.clear();
this.nodes.clear();
}
dispose() {
this.extElementsMap.clear();
this.itemHandlesMap.clear();
this.extChildrenElementsMap.clear();
this.clearAll();
}
}

View File

@@ -7,7 +7,7 @@
import Severity from 'vs/base/common/severity';
import * as modes from 'vs/editor/common/modes';
import * as types from './extHostTypes';
import { Position as EditorPosition } from 'vs/platform/editor/common/editor';
import { Position as EditorPosition, ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { IDecorationOptions, EndOfLineSequence } from 'vs/editor/common/editorCommon';
import * as vscode from 'vscode';
import URI from 'vs/base/common/uri';
@@ -17,6 +17,8 @@ import { IPosition } from 'vs/editor/common/core/position';
import { IRange } from 'vs/editor/common/core/range';
import { ISelection } from 'vs/editor/common/core/selection';
import * as htmlContent from 'vs/base/common/htmlContent';
import { IRelativePattern } from 'vs/base/common/glob';
import { LanguageSelector, LanguageFilter } from 'vs/editor/common/modes/languageSelector';
export interface PositionLike {
line: number;
@@ -223,6 +225,43 @@ export const TextEdit = {
}
};
export namespace WorkspaceEdit {
export function from(value: vscode.WorkspaceEdit): modes.WorkspaceEdit {
const result: modes.WorkspaceEdit = { edits: [] };
for (let entry of value.entries()) {
let [uri, textEdits] = entry;
for (let textEdit of textEdits) {
result.edits.push({
resource: uri,
newText: textEdit.newText,
range: fromRange(textEdit.range)
});
}
}
return result;
}
export function fromTextEdits(uri: vscode.Uri, textEdits: vscode.TextEdit[]): modes.WorkspaceEdit {
const result: modes.WorkspaceEdit = { edits: [] };
for (let textEdit of textEdits) {
result.edits.push({
resource: uri,
newText: textEdit.newText,
range: fromRange(textEdit.range)
});
}
return result;
}
export function to(value: modes.WorkspaceEdit) {
const result = new types.WorkspaceEdit();
for (const edit of value.edits) {
result.replace(edit.resource, toRange(edit.range), edit.newText);
}
return result;
}
}
export namespace SymbolKind {
@@ -385,7 +424,8 @@ export namespace Suggest {
result.insertText = suggestion.insertText;
result.kind = CompletionItemKind.to(suggestion.type);
result.detail = suggestion.detail;
result.documentation = <string>suggestion.documentation; // htmlContent.isMarkdownString(suggestion.documentation) ? MarkdownString.to(suggestion.documentation) : suggestion.documentation;
// {{SQL CARBON EDIT}}
result.documentation = <string>suggestion.documentation;
result.sortText = suggestion.sortText;
result.filterText = suggestion.filterText;
@@ -410,7 +450,7 @@ export namespace Suggest {
return result;
}
};
}
export namespace ParameterInformation {
export function from(info: types.ParameterInformation): modes.ParameterInformation {
@@ -543,3 +583,53 @@ export namespace ProgressLocation {
return undefined;
}
}
export function toTextEditorOptions(options?: vscode.TextDocumentShowOptions): ITextEditorOptions {
if (options) {
return {
pinned: typeof options.preview === 'boolean' ? !options.preview : undefined,
preserveFocus: options.preserveFocus,
selection: typeof options.selection === 'object' ? fromRange(options.selection) : undefined
} as ITextEditorOptions;
}
return undefined;
}
export function toGlobPattern(pattern: vscode.GlobPattern): string | IRelativePattern {
if (typeof pattern === 'string') {
return pattern;
}
if (!isRelativePattern(pattern)) {
return undefined;
}
return new types.RelativePattern(pattern.base, pattern.pattern);
}
function isRelativePattern(obj: any): obj is vscode.RelativePattern {
const rp = obj as vscode.RelativePattern;
return rp && typeof rp.base === 'string' && typeof rp.pattern === 'string';
}
export function toLanguageSelector(selector: vscode.DocumentSelector): LanguageSelector {
if (Array.isArray(selector)) {
return selector.map(sel => doToLanguageSelector(sel));
}
return doToLanguageSelector(selector);
}
function doToLanguageSelector(selector: string | vscode.DocumentFilter): string | LanguageFilter {
if (typeof selector === 'string') {
return selector;
}
return {
language: selector.language,
scheme: selector.scheme,
pattern: toGlobPattern(selector.pattern)
};
}

View File

@@ -11,6 +11,7 @@ import { illegalArgument } from 'vs/base/common/errors';
import * as vscode from 'vscode';
import { isMarkdownString } from 'vs/base/common/htmlContent';
import { IRelativePattern } from 'vs/base/common/glob';
import { relative } from 'path';
export class Disposable {
@@ -808,6 +809,21 @@ export class SymbolInformation {
}
}
export class CodeAction {
title: string;
command?: vscode.Command;
edits?: TextEdit[] | WorkspaceEdit;
dianostics?: Diagnostic[];
constructor(title: string, edits?: TextEdit[] | WorkspaceEdit) {
this.title = title;
this.edits = edits;
}
}
export class CodeLens {
range: Range;
@@ -889,6 +905,11 @@ export class SignatureHelp {
}
}
export enum CodeActionType {
QuickFix = 1,
Refactoring = 2
}
export enum CompletionTriggerKind {
Invoke = 0,
TriggerCharacter = 1
@@ -1132,7 +1153,6 @@ export enum TaskPanelKind {
export class TaskGroup implements vscode.TaskGroup {
private _id: string;
private _label: string;
public static Clean: TaskGroup = new TaskGroup('clean', 'Clean');
@@ -1142,15 +1162,14 @@ export class TaskGroup implements vscode.TaskGroup {
public static Test: TaskGroup = new TaskGroup('test', 'Test');
constructor(id: string, label: string) {
constructor(id: string, _label: string) {
if (typeof id !== 'string') {
throw illegalArgument('name');
}
if (typeof label !== 'string') {
if (typeof _label !== 'string') {
throw illegalArgument('name');
}
this._id = id;
this._label = label;
}
get id(): string {
@@ -1475,4 +1494,41 @@ export class RelativePattern implements IRelativePattern {
this.base = typeof base === 'string' ? base : base.uri.fsPath;
this.pattern = pattern;
}
public pathToRelative(from: string, to: string): string {
return relative(from, to);
}
}
export class Breakpoint {
readonly enabled: boolean;
readonly condition?: string;
readonly hitCondition?: string;
protected constructor(enabled: boolean, condition: string, hitCondition: string) {
this.enabled = enabled;
this.condition = condition;
this.hitCondition = hitCondition;
this.condition = condition;
this.hitCondition = hitCondition;
}
}
export class SourceBreakpoint extends Breakpoint {
readonly location: Location;
constructor(enabled: boolean, condition: string, hitCondition: string, location: Location) {
super(enabled, condition, hitCondition);
this.location = location;
}
}
export class FunctionBreakpoint extends Breakpoint {
readonly functionName: string;
constructor(enabled: boolean, condition: string, hitCondition: string, functionName: string) {
super(enabled, condition, hitCondition);
this.functionName = functionName;
}
}

View File

@@ -14,7 +14,6 @@ import { IWorkspaceData, ExtHostWorkspaceShape, MainContext, MainThreadWorkspace
import * as vscode from 'vscode';
import { compare } from 'vs/base/common/strings';
import { TernarySearchTree } from 'vs/base/common/map';
import { IRelativePattern } from 'vs/base/common/glob';
class Workspace2 extends Workspace {
@@ -156,9 +155,30 @@ export class ExtHostWorkspace implements ExtHostWorkspaceShape {
// --- search ---
findFiles(include: string | IRelativePattern, exclude: string | IRelativePattern, maxResults?: number, token?: vscode.CancellationToken): Thenable<vscode.Uri[]> {
findFiles(include: vscode.GlobPattern, exclude: vscode.GlobPattern, maxResults?: number, token?: vscode.CancellationToken): Thenable<vscode.Uri[]> {
const requestId = ExtHostWorkspace._requestIdPool++;
const result = this._proxy.$startSearch(include, exclude, maxResults, requestId);
let includePattern: string;
let includeFolder: string;
if (include) {
if (typeof include === 'string') {
includePattern = include;
} else {
includePattern = include.pattern;
includeFolder = include.base;
}
}
let excludePattern: string;
if (exclude) {
if (typeof exclude === 'string') {
excludePattern = exclude;
} else {
excludePattern = exclude.pattern;
}
}
const result = this._proxy.$startSearch(includePattern, includeFolder, excludePattern, maxResults, requestId);
if (token) {
token.onCancellationRequested(() => this._proxy.$cancelSearch(requestId));
}