diff --git a/src/vs/editor/contrib/smartSelect/smartSelect.ts b/src/vs/editor/contrib/smartSelect/smartSelect.ts index 06ad8b73d77..c1fb4a04ffc 100644 --- a/src/vs/editor/contrib/smartSelect/smartSelect.ts +++ b/src/vs/editor/contrib/smartSelect/smartSelect.ts @@ -7,7 +7,7 @@ import * as arrays from 'vs/base/common/arrays'; import { CancellationToken } from 'vs/base/common/cancellation'; import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { ICodeEditor } from 'vs/editor/browser/editorBrowser'; -import { EditorAction, IActionOptions, registerEditorAction, registerEditorContribution, ServicesAccessor } from 'vs/editor/browser/editorExtensions'; +import { EditorAction, IActionOptions, registerEditorAction, registerEditorContribution, ServicesAccessor, registerDefaultLanguageCommand } from 'vs/editor/browser/editorExtensions'; import { Position } from 'vs/editor/common/core/position'; import { Range } from 'vs/editor/common/core/range'; import { IEditorContribution } from 'vs/editor/common/editorCommon'; @@ -258,3 +258,7 @@ export function provideSelectionRanges(model: ITextModel, position: Position, to return result; }); } + +registerDefaultLanguageCommand('_executeSelectionRangeProvider', function (model, position) { + return provideSelectionRanges(model, position, CancellationToken.None); +}); diff --git a/src/vs/workbench/api/node/extHostApiCommands.ts b/src/vs/workbench/api/node/extHostApiCommands.ts index 7eb6e84e197..bfee1376f3b 100644 --- a/src/vs/workbench/api/node/extHostApiCommands.ts +++ b/src/vs/workbench/api/node/extHostApiCommands.ts @@ -17,7 +17,8 @@ import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands'; import { CustomCodeAction } from 'vs/workbench/api/node/extHostLanguageFeatures'; import { ICommandsExecutor, PreviewHTMLAPICommand, OpenFolderAPICommand, DiffAPICommand, OpenAPICommand, RemoveFromRecentlyOpenedAPICommand, SetEditorLayoutAPICommand } from './apiCommands'; import { EditorGroupLayout } from 'vs/workbench/services/group/common/editorGroupsService'; -import { isFalsyOrEmpty } from 'vs/base/common/arrays'; +import { isFalsyOrEmpty, isNonEmptyArray } from 'vs/base/common/arrays'; +import { IRange } from 'vs/editor/common/core/range'; export class ExtHostApiCommands { @@ -195,7 +196,14 @@ export class ExtHostApiCommands { ], returns: 'A promise that resolves to an array of ColorPresentation objects.' }); - + this._register('vscode.executeSelectionRangeProvider', this._executeSelectionRangeProvider, { + description: 'Execute selection range provider.', + args: [ + { name: 'uri', description: 'Uri of a text document', constraint: URI }, + { name: 'position', description: 'Position in a text document', constraint: types.Position } + ], + returns: 'A promise that resolves to an array of ranges.' + }); // ----------------------------------------------------------------- // The following commands are registered on both sides separately. @@ -413,6 +421,19 @@ export class ExtHostApiCommands { }); } + private _executeSelectionRangeProvider(resource: URI, position: types.Position): Thenable { + const args = { + resource, + position: position && typeConverters.Position.from(position) + }; + return this._commands.executeCommand('_executeSelectionRangeProvider', args).then(result => { + if (isNonEmptyArray(result)) { + return result.map(typeConverters.Range.to); + } + return []; + }); + } + private _executeColorPresentationProvider(color: types.Color, context: { uri: URI, range: types.Range }): Thenable { const args = { resource: context.uri, diff --git a/src/vs/workbench/test/electron-browser/api/extHostApiCommands.test.ts b/src/vs/workbench/test/electron-browser/api/extHostApiCommands.test.ts index 863ca25a002..8733ce75192 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostApiCommands.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostApiCommands.test.ts @@ -765,4 +765,20 @@ suite('ExtHostLanguageFeatureCommands', function () { }); }); }); + + // --- selection ranges + + test('Links, back and forth', async function () { + + disposables.push(extHost.registerSelectionRangeProvider(nullExtensionDescription, defaultSelector, { + provideSelectionRanges() { + return [new types.Range(0, 10, 0, 18), new types.Range(0, 2, 0, 20)]; + } + })); + + await rpcProtocol.sync(); + let value = await commands.executeCommand('vscode.executeSelectionRangeProvider', model.uri, new types.Position(0, 0)); + assert.ok(value.length >= 2); + }); + }); diff --git a/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts b/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts index b26fc7427af..64b1ac47ed8 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts @@ -9,7 +9,7 @@ import { setUnexpectedErrorHandler, errorHandler } from 'vs/base/common/errors'; import { URI } from 'vs/base/common/uri'; import * as types from 'vs/workbench/api/node/extHostTypes'; import { TextModel as EditorModel } from 'vs/editor/common/model/textModel'; -import { Position as EditorPosition } from 'vs/editor/common/core/position'; +import { Position as EditorPosition, Position } from 'vs/editor/common/core/position'; import { Range as EditorRange } from 'vs/editor/common/core/range'; import { TestRPCProtocol } from './testRPCProtocol'; import { IMarkerService } from 'vs/platform/markers/common/markers'; @@ -45,6 +45,7 @@ import { ITextModel, EndOfLineSequence } from 'vs/editor/common/model'; import { getColors } from 'vs/editor/contrib/colorPicker/color'; import { CancellationToken } from 'vs/base/common/cancellation'; import { nullExtensionDescription as defaultExtension } from 'vs/workbench/services/extensions/common/extensions'; +import { provideSelectionRanges } from 'vs/editor/contrib/smartSelect/smartSelect'; const defaultSelector = { scheme: 'far' }; const model: ITextModel = EditorModel.createFromString( @@ -1222,4 +1223,20 @@ suite('ExtHostLanguageFeatures', function () { }); }); }); + + // -- selection ranges + + test('Selection Ranges, data conversion', async function () { + disposables.push(extHost.registerSelectionRangeProvider(defaultExtension, defaultSelector, { + provideSelectionRanges() { + return [new types.Range(0, 10, 0, 18), new types.Range(0, 2, 0, 20)]; + } + })); + + await rpcProtocol.sync(); + + provideSelectionRanges(model, new Position(1, 17), CancellationToken.None).then(ranges => { + assert.ok(ranges.length >= 2); + }); + }); });