diff --git a/src/vs/base/common/marshalling.ts b/src/vs/base/common/marshalling.ts index 30dc89ca52d..fb03d036071 100644 --- a/src/vs/base/common/marshalling.ts +++ b/src/vs/base/common/marshalling.ts @@ -29,7 +29,7 @@ var currentDynamicContrib:IMarshallingContribution = null; export function canSerialize(obj: any): boolean { for (let contrib of marshallingContributions) { - if (contrib.canDeserialize(obj)) { + if (contrib.canSerialize(obj)) { return true; } } diff --git a/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts b/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts index 2af92d98124..2bccc0b3a44 100644 --- a/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts +++ b/src/vs/editor/contrib/goToDeclaration/common/goToDeclaration.ts @@ -7,11 +7,13 @@ import URI from 'vs/base/common/uri'; import {TPromise} from 'vs/base/common/winjs.base'; -import {onUnexpectedError} from 'vs/base/common/errors'; +import {onUnexpectedError, illegalArgument} from 'vs/base/common/errors'; import {IModel, IPosition} from 'vs/editor/common/editorCommon'; import {IDeclarationSupport} from 'vs/editor/common/modes'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; import {IReference} from 'vs/editor/common/modes'; +import {IModelService} from 'vs/editor/common/services/modelService'; +import {registerCommand} from 'vs/platform/keybinding/common/commandsUtils'; export const DeclarationRegistry = new LanguageFeatureRegistry('declarationSupport'); @@ -40,4 +42,19 @@ export function getDeclarationsAtPosition(model: IModel, position: IPosition): T } return result; }); -} \ No newline at end of file +} + +registerCommand('_executeDefinitionProvider', function(accessor, args) { + + let {resource, position} = args; + if (!URI.isURI(resource)) { + throw illegalArgument(); + } + + let model = accessor.get(IModelService).getModel(resource); + if (!model) { + throw illegalArgument(resource + ' not found'); + } + + return getDeclarationsAtPosition(model, position); +}); \ No newline at end of file diff --git a/src/vs/editor/contrib/hover/common/hover.ts b/src/vs/editor/contrib/hover/common/hover.ts index 0ffc441ae9c..687cdd4def4 100644 --- a/src/vs/editor/contrib/hover/common/hover.ts +++ b/src/vs/editor/contrib/hover/common/hover.ts @@ -10,8 +10,10 @@ import {IExtraInfoSupport, IComputeExtraInfoResult} from 'vs/editor/common/modes import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; import {TPromise} from 'vs/base/common/winjs.base'; import {coalesce} from 'vs/base/common/arrays'; -import {onUnexpectedError} from 'vs/base/common/errors'; +import {onUnexpectedError, illegalArgument} from 'vs/base/common/errors'; import {IPosition, IModel} from 'vs/editor/common/editorCommon'; +import {IModelService} from 'vs/editor/common/services/modelService'; +import {registerCommand} from 'vs/platform/keybinding/common/commandsUtils'; export const ExtraInfoRegistry = new LanguageFeatureRegistry('extraInfoSupport'); @@ -37,4 +39,18 @@ export function getExtraInfoAtPosition(model: IModel, position: IPosition): TPro }); return TPromise.join(promises).then(() => coalesce(values)); -} \ No newline at end of file +} + +registerCommand('_executeHoverProvider', function(accessor, args) { + + let {resource, position} = args; + if (!URI.isURI(resource)) { + throw illegalArgument(); + } + let model = accessor.get(IModelService).getModel(resource); + if (!model) { + throw illegalArgument(resource + ' not found'); + } + + return getExtraInfoAtPosition(model, position); +}); \ No newline at end of file diff --git a/src/vs/platform/keybinding/common/commandsUtils.ts b/src/vs/platform/keybinding/common/commandsUtils.ts new file mode 100644 index 00000000000..dec5138e8fd --- /dev/null +++ b/src/vs/platform/keybinding/common/commandsUtils.ts @@ -0,0 +1,26 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import {illegalArgument} from 'vs/base/common/errors'; +import {ServicesAccessor} from 'vs/platform/instantiation/common/instantiation'; +import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry'; + +export function registerCommand(id: string, handler: (accessor: ServicesAccessor, args: { [n: string]: any }) => any) { + + KeybindingsRegistry.registerCommandDesc({ + id, + handler(accessor, args: any[]) { + if (args && args.length > 1 || typeof args[0] !== 'object') { + throw illegalArgument(); + } + + return handler(accessor, args && args[0]); + }, + weight: KeybindingsRegistry.WEIGHT.editorContrib(), + primary: undefined, + context: undefined, + }); +} \ No newline at end of file diff --git a/src/vs/workbench/api/browser/pluginHost.api.impl.ts b/src/vs/workbench/api/browser/pluginHost.api.impl.ts index bdc5061e270..85c58b2b349 100644 --- a/src/vs/workbench/api/browser/pluginHost.api.impl.ts +++ b/src/vs/workbench/api/browser/pluginHost.api.impl.ts @@ -22,6 +22,7 @@ import {PluginHostTelemetryService} from 'vs/workbench/api/common/pluginHostTele import {PluginHostEditors} from 'vs/workbench/api/common/pluginHostEditors'; import {ExtHostLanguages} from 'vs/workbench/api/common/extHostLanguages'; import {ExtHostLanguageFeatures} from 'vs/workbench/api/common/extHostLanguageFeatures'; +import {ExtHostLanguageFeatureCommands} from 'vs/workbench/api/common/extHostLanguageFeatureCommands'; import * as extHostTypes from 'vs/workbench/api/common/pluginHostTypes'; import 'vs/workbench/api/common/pluginHostTypes.marshalling'; import {wrapAsWinJSPromise} from 'vs/base/common/async'; @@ -251,6 +252,7 @@ export class PluginHostAPIImplementation { const languages = new ExtHostLanguages(this._threadService); const pluginHostDiagnostics = new PluginHostDiagnostics(this._threadService); const languageFeatures = threadService.getRemotable(ExtHostLanguageFeatures); + const languageFeatureCommand = new ExtHostLanguageFeatureCommands(threadService.getRemotable(PluginHostCommands)); this.languages = { createDiagnosticCollection(name?: string): vscode.DiagnosticCollection { diff --git a/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts b/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts new file mode 100644 index 00000000000..ccdd2b7f4dd --- /dev/null +++ b/src/vs/workbench/api/common/extHostLanguageFeatureCommands.ts @@ -0,0 +1,107 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import URI from 'vs/base/common/uri'; +import Event, {Emitter} from 'vs/base/common/event'; +import Severity from 'vs/base/common/severity'; +import {DefaultFilter} from 'vs/editor/common/modes/modesFilters'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {onUnexpectedError} from 'vs/base/common/errors'; +import {sequence} from 'vs/base/common/async'; +import {Range as EditorRange} from 'vs/editor/common/core/range'; +import {IDisposable} from 'vs/base/common/lifecycle'; +import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; +import {Remotable, IThreadService} from 'vs/platform/thread/common/thread'; +import * as vscode from 'vscode'; +import * as typeConverters from 'vs/workbench/api/common/pluginHostTypeConverters'; +import * as types from 'vs/workbench/api/common/pluginHostTypes'; +import {IPosition, IRange, ISingleEditOperation} from 'vs/editor/common/editorCommon'; +import * as modes from 'vs/editor/common/modes'; +import {CancellationTokenSource} from 'vs/base/common/cancellation'; +import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments'; +import {IMarkerService, IMarker} from 'vs/platform/markers/common/markers'; +import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; +import {DeclarationRegistry} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; +import {ExtraInfoRegistry} from 'vs/editor/contrib/hover/common/hover'; +import {OccurrencesRegistry} from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; +import {ReferenceRegistry} from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; +import {QuickFixRegistry} from 'vs/editor/contrib/quickFix/common/quickFix'; +import {OutlineRegistry, IOutlineEntry, IOutlineSupport} from 'vs/editor/contrib/quickOpen/common/quickOpen'; +import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; +import {NavigateTypesSupportRegistry, INavigateTypesSupport, ITypeBearing} from 'vs/workbench/parts/search/common/search' +import {RenameRegistry} from 'vs/editor/contrib/rename/common/rename'; +import {FormatRegistry, FormatOnTypeRegistry} from 'vs/editor/contrib/format/common/format'; +import {CodeLensRegistry} from 'vs/editor/contrib/codelens/common/codelens'; +import {ParameterHintsRegistry} from 'vs/editor/contrib/parameterHints/common/parameterHints'; +import {SuggestRegistry} from 'vs/editor/contrib/suggest/common/suggest'; + +// vscode.executeWorkspaceSymbolProvider +// vscode.executeDefinitionProvider +// vscode.executeHoverProvider + +// vscode.executeDocumentHighlights +// vscode.executeReferenceProvider +// vscode.executeCodeActionProvider +// vscode.executeCodeLensProvider +// vscode.executeDocumentSymbolProvider +// vscode.executeDocumentRenameProvider +// vscode.executeFormatDocumentProvider +// vscode.executeFormatRangeProvider +// vscode.executeFormatOnTypeProvider +// vscode.executeSignatureHelpProvider +// vscode.executeCompletionItemProvider + +export class ExtHostLanguageFeatureCommands { + + private _commands: PluginHostCommands; + private _disposables: IDisposable[] = []; + + constructor(commands: PluginHostCommands) { + this._commands = commands; + + this._register('vscode.executeWorkspaceSymbolProvider', this._executeWorkspaceSymbolProvider); + this._register('vscode.executeDefinitionProvider', this._executeDefinitionProvider); + this._register('vscode.executeHoverProvider', this._executeHoverProvider); + } + + private _register(id: string, callback: (...args: any[]) => any): void { + this._disposables.push(this._commands.registerCommand(id, callback, this)); + } + + // --- command impl + + private _executeWorkspaceSymbolProvider(query: string): Thenable { + return this._commands.executeCommand('_executeWorkspaceSymbolProvider', { query }).then(value => { + if (Array.isArray(value)) { + return value.map(typeConverters.toSymbolInformation); + } + }); + } + + private _executeDefinitionProvider(resource: URI, position: types.Position): Thenable { + const args = { + resource, + position: position && typeConverters.fromPosition(position) + }; + return this._commands.executeCommand('_executeDefinitionProvider', args).then(value => { + if (Array.isArray(value)) { + return value.map(typeConverters.toLocation) + } + }); + } + + private _executeHoverProvider(resource: URI, position: types.Position): Thenable { + const args = { + resource, + position: position && typeConverters.fromPosition(position) + }; + return this._commands.executeCommand('_executeHoverProvider', args).then(value => { + if (Array.isArray(value)) { + return value.map(typeConverters.toHover) + } + }); + } +} \ No newline at end of file diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index e638636c307..fe0552a08b4 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -215,20 +215,14 @@ class ExtraInfoAdapter implements modes.IExtraInfoSupport { if (!value) { return; } - - let {range, contents} = value; - - if (!range) { - range = doc.getWordRangeAtPosition(pos); + if (!value.range) { + value.range = doc.getWordRangeAtPosition(pos); } - if (!range) { - range = new Range(pos, pos); + if (!value.range) { + value.range = new Range(pos, pos); } - return { - range: TypeConverters.fromRange(range), - htmlContent: contents && contents.map(TypeConverters.fromFormattedString) - } + return TypeConverters.fromHover(value); }); } } @@ -438,21 +432,10 @@ class NavigateTypeAdapter implements INavigateTypesSupport { getNavigateToItems(search: string): TPromise { return asWinJsPromise(token => this._provider.provideWorkspaceSymbols(search, token)).then(value => { if (Array.isArray(value)) { - return value.map(NavigateTypeAdapter._fromSymbolInformation); + return value.map(TypeConverters.fromSymbolInformation); } }); } - - private static _fromSymbolInformation(info: vscode.SymbolInformation): ITypeBearing { - return { - name: info.name, - type: SymbolKind[info.kind || SymbolKind.Property].toLowerCase(), - range: TypeConverters.fromRange(info.location.range), - resourceUri: info.location.uri, - containerName: info.containerName, - parameters: '', - }; - } } class RenameAdapter implements modes.IRenameSupport { diff --git a/src/vs/workbench/api/common/pluginHostCommands.ts b/src/vs/workbench/api/common/pluginHostCommands.ts index 43e01007d31..bc57ffe3992 100644 --- a/src/vs/workbench/api/common/pluginHostCommands.ts +++ b/src/vs/workbench/api/common/pluginHostCommands.ts @@ -78,13 +78,13 @@ export class PluginHostCommands { return this._executeContributedCommand(id, ...args); } else { - // check that we can get all parameters over to - // the other side - for (let i = 0; i < args.length; i++) { - if (typeof args[i] === 'object' && !canSerialize(args[i])) { - throw new Error('illegal argument - can not serialize argument number: ' + i) - } - } + // // check that we can get all parameters over to + // // the other side + // for (let i = 0; i < args.length; i++) { + // if (args[i] !== null && typeof args[i] === 'object' && !canSerialize(args[i])) { + // throw new Error('illegal argument - can not serialize argument number: ' + i) + // } + // } return this._proxy._executeCommand(id, args); } diff --git a/src/vs/workbench/api/common/pluginHostTypeConverters.ts b/src/vs/workbench/api/common/pluginHostTypeConverters.ts index f87fa4d2617..80448162cd4 100644 --- a/src/vs/workbench/api/common/pluginHostTypeConverters.ts +++ b/src/vs/workbench/api/common/pluginHostTypeConverters.ts @@ -6,10 +6,12 @@ import Severity from 'vs/base/common/severity'; import * as objects from 'vs/base/common/objects'; +import * as modes from 'vs/editor/common/modes'; +import * as types from './pluginHostTypes'; import {Position as EditorPosition} from 'vs/platform/editor/common/editor'; -import {Selection, Range, Position, SymbolKind, DiagnosticSeverity, ViewColumn} from './pluginHostTypes'; import {IPosition, ISelection, IRange, IRangeWithMessage, ISingleEditOperation} from 'vs/editor/common/editorCommon'; import {IHTMLContentElement} from 'vs/base/common/htmlContent'; +import {ITypeBearing} from 'vs/workbench/parts/search/common/search' export interface PositionLike { line: number; @@ -26,11 +28,11 @@ export interface SelectionLike extends RangeLike { active: PositionLike; } -export function toSelection(selection: ISelection): Selection { +export function toSelection(selection: ISelection): types.Selection { let {selectionStartLineNumber, selectionStartColumn, positionLineNumber, positionColumn} = selection; - let start = new Position(selectionStartLineNumber - 1, selectionStartColumn - 1); - let end = new Position(positionLineNumber - 1, positionColumn - 1); - return new Selection(start, end); + let start = new types.Position(selectionStartLineNumber - 1, selectionStartColumn - 1); + let end = new types.Position(positionLineNumber - 1, positionColumn - 1); + return new types.Selection(start, end); } export function fromSelection(selection: SelectionLike): ISelection { @@ -53,46 +55,50 @@ export function fromRange(range: RangeLike): IRange { }; } -export function toRange(range: IRange): Range { +export function toRange(range: IRange): types.Range { let {startLineNumber, startColumn, endLineNumber, endColumn} = range; - return new Range(startLineNumber - 1, startColumn - 1, endLineNumber - 1, endColumn - 1); + return new types.Range(startLineNumber - 1, startColumn - 1, endLineNumber - 1, endColumn - 1); } -export function toPosition(position: IPosition): Position { - return new Position(position.lineNumber - 1, position.column - 1); +export function toPosition(position: IPosition): types.Position { + return new types.Position(position.lineNumber - 1, position.column - 1); } -export function fromSymbolKind(kind: number | SymbolKind): string { +export function fromPosition(position: types.Position):IPosition { + return { lineNumber: position.line + 1, column: position.character + 1}; +} + +export function fromSymbolKind(kind: number | types.SymbolKind): string { switch (kind) { - case SymbolKind.Method: + case types.SymbolKind.Method: return 'method'; - case SymbolKind.Function: + case types.SymbolKind.Function: return 'function'; - case SymbolKind.Constructor: + case types.SymbolKind.Constructor: return 'constructor'; - case SymbolKind.Variable: + case types.SymbolKind.Variable: return 'variable'; - case SymbolKind.Class: + case types.SymbolKind.Class: return 'class'; - case SymbolKind.Interface: + case types.SymbolKind.Interface: return 'interface'; - case SymbolKind.Module: - case SymbolKind.Namespace: - case SymbolKind.Package: + case types.SymbolKind.Module: + case types.SymbolKind.Namespace: + case types.SymbolKind.Package: return 'module'; - case SymbolKind.Property: + case types.SymbolKind.Property: return 'property'; - case SymbolKind.Enum: + case types.SymbolKind.Enum: return 'enum'; - case SymbolKind.String: + case types.SymbolKind.String: return 'string'; - case SymbolKind.File: + case types.SymbolKind.File: return 'file'; - case SymbolKind.Array: + case types.SymbolKind.Array: return 'array'; - case SymbolKind.Number: + case types.SymbolKind.Number: return 'number'; - case SymbolKind.Boolean: + case types.SymbolKind.Boolean: return 'boolean'; } @@ -101,39 +107,39 @@ export function fromSymbolKind(kind: number | SymbolKind): string { export function fromDiagnosticSeverity(value: number): Severity { switch (value) { - case DiagnosticSeverity.Error: + case types.DiagnosticSeverity.Error: return Severity.Error; - case DiagnosticSeverity.Warning: + case types.DiagnosticSeverity.Warning: return Severity.Warning; - case DiagnosticSeverity.Information: + case types.DiagnosticSeverity.Information: return Severity.Info; - case DiagnosticSeverity.Hint: + case types.DiagnosticSeverity.Hint: return Severity.Ignore; } return Severity.Error; } -export function toDiagnosticSeverty(value: Severity): DiagnosticSeverity { +export function toDiagnosticSeverty(value: Severity): types.DiagnosticSeverity { switch (value) { case Severity.Info: - return DiagnosticSeverity.Information; + return types.DiagnosticSeverity.Information; case Severity.Warning: - return DiagnosticSeverity.Warning; + return types.DiagnosticSeverity.Warning; case Severity.Error: - return DiagnosticSeverity.Error; + return types.DiagnosticSeverity.Error; case Severity.Ignore: - return DiagnosticSeverity.Hint; + return types.DiagnosticSeverity.Hint; } - return DiagnosticSeverity.Error; + return types.DiagnosticSeverity.Error; } export function fromViewColumn(column?: vscode.ViewColumn): EditorPosition { let editorColumn = EditorPosition.LEFT; if (typeof column !== 'number') { // stick with LEFT - } else if (column === ViewColumn.Two) { + } else if (column === types.ViewColumn.Two) { editorColumn = EditorPosition.CENTER; - } else if (column === ViewColumn.Three) { + } else if (column === types.ViewColumn.Three) { editorColumn = EditorPosition.RIGHT; } return editorColumn; @@ -148,6 +154,14 @@ export function fromFormattedString(value: vscode.MarkedString): IHTMLContentEle } } +export function toFormattedString(value: IHTMLContentElement): vscode.MarkedString { + if (typeof value.code === 'string') { + return value.code; + } + let {formattedText, text} = value; + return formattedText || text || ''; +} + function isMarkedStringArr(something: vscode.MarkedString | vscode.MarkedString[]): something is vscode.MarkedString[] { return Array.isArray(something); } @@ -195,4 +209,40 @@ export function fromTextEdit(edit: vscode.TextEdit) { text: edit.newText, range: fromRange(edit.range) } +} + +export function fromSymbolInformation(info: vscode.SymbolInformation): ITypeBearing { + return { + name: info.name, + type: types.SymbolKind[info.kind || types.SymbolKind.Property].toLowerCase(), + range: fromRange(info.location.range), + resourceUri: info.location.uri, + containerName: info.containerName, + parameters: '', + }; +} + +export function toSymbolInformation(bearing: ITypeBearing): types.SymbolInformation { + return new types.SymbolInformation(bearing.name, + types.SymbolKind[bearing.type.charAt(0).toUpperCase() + bearing.type.substr(1)], + toRange(bearing.range), + bearing.resourceUri, + bearing.containerName); +} + + +export function toLocation(reference: modes.IReference): types.Location { + return new types.Location(reference.resource, toRange(reference.range)); +} + + +export function fromHover(hover: vscode.Hover): modes.IComputeExtraInfoResult { + return { + range: fromRange(hover.range), + htmlContent: hover.contents.map(fromFormattedString) + } +} + +export function toHover(info: modes.IComputeExtraInfoResult): types.Hover { + return new types.Hover(info.htmlContent.map(toFormattedString), toRange(info.range)); } \ No newline at end of file diff --git a/src/vs/workbench/parts/search/common/search.ts b/src/vs/workbench/parts/search/common/search.ts index b62874ccf73..b8e13192400 100644 --- a/src/vs/workbench/parts/search/common/search.ts +++ b/src/vs/workbench/parts/search/common/search.ts @@ -6,11 +6,12 @@ 'use strict'; import {TPromise} from 'vs/base/common/winjs.base'; -import {onUnexpectedError} from 'vs/base/common/errors'; +import {onUnexpectedError, illegalArgument} from 'vs/base/common/errors'; import {IDisposable} from 'vs/base/common/lifecycle'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; import {IRange} from 'vs/editor/common/editorCommon'; import URI from 'vs/base/common/uri'; +import {registerCommand} from 'vs/platform/keybinding/common/commandsUtils'; /** * Interface used to navigate to types by value. @@ -72,4 +73,12 @@ export function getNavigateToItems(query: string): TPromise { } return result; }); -} \ No newline at end of file +} + +registerCommand('_executeWorkspaceSymbolProvider', function(accessor, args: { query: string;}) { + let {query} = args; + if (typeof query !== 'string') { + throw illegalArgument(); + } + return getNavigateToItems(query); +}); diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts new file mode 100644 index 00000000000..c5eeb9052ea --- /dev/null +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatureCommands.test.ts @@ -0,0 +1,212 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +import * as assert from 'assert'; +import {setUnexpectedErrorHandler, errorHandler} from 'vs/base/common/errors'; +import {create} from 'vs/base/common/types'; +import URI from 'vs/base/common/uri'; +import {URL} from 'vs/base/common/network'; +import {TPromise} from 'vs/base/common/winjs.base'; +import {PluginHostDocument} from 'vs/workbench/api/common/pluginHostDocuments'; +import * as types from 'vs/workbench/api/common/pluginHostTypes'; +import {Range as CodeEditorRange} from 'vs/editor/common/core/range'; +import * as EditorCommon from 'vs/editor/common/editorCommon'; +import {Model as EditorModel} from 'vs/editor/common/model/model'; +import threadService from './testThreadService' +import {create as createInstantiationService} from 'vs/platform/instantiation/common/instantiationService'; +import {MarkerService} from 'vs/platform/markers/common/markerService'; +import {IMarkerService} from 'vs/platform/markers/common/markers'; +import {IThreadService} from 'vs/platform/thread/common/thread'; +import {IKeybindingService} from 'vs/platform/keybinding/common/keybindingService'; +import {KeybindingsRegistry} from 'vs/platform/keybinding/common/keybindingsRegistry'; +import {IModelService} from 'vs/editor/common/services/modelService'; +import {ExtHostLanguageFeatures, MainThreadLanguageFeatures} from 'vs/workbench/api/common/extHostLanguageFeatures'; +import {ExtHostLanguageFeatureCommands} from 'vs/workbench/api/common/extHostLanguageFeatureCommands'; +import {PluginHostCommands, MainThreadCommands} from 'vs/workbench/api/common/pluginHostCommands'; +import {PluginHostModelService} from 'vs/workbench/api/common/pluginHostDocuments'; +import {SyncDescriptor0} from 'vs/platform/instantiation/common/descriptors'; +import {LanguageSelector, ModelLike} from 'vs/editor/common/modes/languageSelector'; +import {OutlineRegistry, getOutlineEntries} from 'vs/editor/contrib/quickOpen/common/quickOpen'; +import {CodeLensRegistry, getCodeLensData} from 'vs/editor/contrib/codelens/common/codelens'; +import {DeclarationRegistry, getDeclarationsAtPosition} from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration'; +import {ExtraInfoRegistry, getExtraInfoAtPosition} from 'vs/editor/contrib/hover/common/hover'; +import {OccurrencesRegistry, getOccurrencesAtPosition} from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter'; +import {ReferenceRegistry, findReferences} from 'vs/editor/contrib/referenceSearch/common/referenceSearch'; +import {getQuickFixes} from 'vs/editor/contrib/quickFix/common/quickFix'; +import {getNavigateToItems} from 'vs/workbench/parts/search/common/search'; +import {rename} from 'vs/editor/contrib/rename/common/rename'; +import {getParameterHints} from 'vs/editor/contrib/parameterHints/common/parameterHints'; + +const defaultSelector = { scheme: 'far' }; +const model: EditorCommon.IModel = new EditorModel( + [ + 'This is the first line', + 'This is the second line', + 'This is the third line', + ].join('\n'), + undefined, + URL.fromUri(URI.parse('far://testing/file.b'))); + +let extHost: ExtHostLanguageFeatures; +let mainThread: MainThreadLanguageFeatures; +let commands: PluginHostCommands; +let disposables: vscode.Disposable[] = []; + +suite('ExtHostLanguageFeatureCommands', function() { + + suiteSetup(() => { + + let instantiationService = createInstantiationService(); + threadService.setInstantiationService(instantiationService); + instantiationService.addSingleton(IMarkerService, new MarkerService(threadService)); + instantiationService.addSingleton(IThreadService, threadService); + instantiationService.addSingleton(IModelService, { + serviceId: IModelService, + getModel():any { return model; }, + createModel():any { throw new Error(); }, + destroyModel():any { throw new Error(); }, + getModels():any { throw new Error(); }, + onModelAdded: undefined, + onModelModeChanged: undefined, + onModelRemoved: undefined + }); + instantiationService.addSingleton(IKeybindingService, { + executeCommand(id, args):any { + let handler = KeybindingsRegistry.getCommands()[id]; + return TPromise.as(instantiationService.invokeFunction(handler, args)); + } + }) + + threadService.getRemotable(PluginHostModelService)._acceptModelAdd({ + isDirty: false, + versionId: model.getVersionId(), + modeId: model.getModeId(), + url: model.getAssociatedResource(), + value: { + EOL: model.getEOL(), + lines: model.getValue().split(model.getEOL()), + BOM: '', + length: -1 + }, + }); + + threadService.getRemotable(MainThreadCommands); + commands = threadService.getRemotable(PluginHostCommands); + new ExtHostLanguageFeatureCommands(commands); + mainThread = threadService.getRemotable(MainThreadLanguageFeatures); + extHost = threadService.getRemotable(ExtHostLanguageFeatures); + }); + + suiteTeardown(() => { + model.dispose(); + }); + + teardown(function(done) { + while (disposables.length) { + disposables.pop().dispose(); + } + threadService.sync() + .then(() => done(), err => done(err)); + }); + + // --- workspace symbols + + test('WorkspaceSymbols, invalid arguments', function(done) { + let promises = [ + commands.executeCommand('vscode.executeWorkspaceSymbolProvider'), + commands.executeCommand('vscode.executeWorkspaceSymbolProvider', null), + commands.executeCommand('vscode.executeWorkspaceSymbolProvider', undefined), + commands.executeCommand('vscode.executeWorkspaceSymbolProvider', true) + ]; + + threadService.sync().then(() => { + TPromise.join(promises).then(undefined, (err: any[]) => { + assert.equal(err.length, 4); + done(); + return []; + }); + }); + }); + + test('WorkspaceSymbols, ⇔ back and forth', function(done) { + + disposables.push(extHost.registerWorkspaceSymbolProvider({ + provideWorkspaceSymbols(query): any { + return [ + new types.SymbolInformation(query, types.SymbolKind.Array, new types.Range(0, 0, 1, 1), URI.parse('far://testing/first')), + new types.SymbolInformation(query, types.SymbolKind.Array, new types.Range(0, 0, 1, 1), URI.parse('far://testing/second')) + ] + } + })); + + disposables.push(extHost.registerWorkspaceSymbolProvider({ + provideWorkspaceSymbols(query): any { + return [ + new types.SymbolInformation(query, types.SymbolKind.Array, new types.Range(0, 0, 1, 1), URI.parse('far://testing/first')) + ] + } + })); + + threadService.sync().then(() => { + commands.executeCommand('vscode.executeWorkspaceSymbolProvider', 'testing').then(value => { + + for (let info of value) { + assert.ok(info instanceof types.SymbolInformation); + assert.equal(info.name, 'testing'); + assert.equal(info.kind, types.SymbolKind.Array); + } + assert.equal(value.length, 3); + done(); + }); + }); + }); + + + // --- definition + + test('Definition, invalid arguments', function(done) { + let promises = [ + commands.executeCommand('vscode.executeDefinitionProvider'), + commands.executeCommand('vscode.executeDefinitionProvider', null), + commands.executeCommand('vscode.executeDefinitionProvider', undefined), + commands.executeCommand('vscode.executeDefinitionProvider', true, false) + ]; + + threadService.sync().then(() => { + TPromise.join(promises).then(undefined, (err: any[]) => { + assert.equal(err.length, 4); + done(); + return []; + }); + }); + }); + + test('Definition, ⇔ back and forth', function(done) { + + disposables.push(extHost.registerDefinitionProvider(defaultSelector, { + provideDefinition(doc:any): any { + return new types.Location(doc.uri, new types.Range(0, 0, 0, 0)); + } + })); + disposables.push(extHost.registerDefinitionProvider(defaultSelector, { + provideDefinition(doc: any): any { + return [ + new types.Location(doc.uri, new types.Range(0, 0, 0, 0)), + new types.Location(doc.uri, new types.Range(0, 0, 0, 0)), + new types.Location(doc.uri, new types.Range(0, 0, 0, 0)), + ] + } + })); + + threadService.sync().then(() => { + commands.executeCommand('vscode.executeDefinitionProvider', model.getAssociatedResource(), new types.Position(0, 0)).then(values => { + assert.equal(values.length, 4); + done(); + }); + }); + }) +}); \ No newline at end of file diff --git a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts index 6c5073e6325..875d3fd2a20 100644 --- a/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/common/api/extHostLanguageFeatures.test.ts @@ -85,6 +85,7 @@ suite('ExtHostLanguageFeatures', function() { suiteTeardown(() => { setUnexpectedErrorHandler(originalErrorHandler); + model.dispose(); }); teardown(function(done) {