diff --git a/extensions/typescript-language-features/src/features/definitionProvider.ts b/extensions/typescript-language-features/src/features/definitionProvider.ts index 25f9218c4e13c..e7d6eabcc9a4d 100644 --- a/extensions/typescript-language-features/src/features/definitionProvider.ts +++ b/extensions/typescript-language-features/src/features/definitionProvider.ts @@ -3,12 +3,56 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { DefinitionProvider, TextDocument, Position, CancellationToken, Definition } from 'vscode'; +import { DefinitionProvider, TextDocument, Position, CancellationToken, Location, SymbolDefinition } from 'vscode'; +import * as Proto from '../protocol'; import DefinitionProviderBase from './definitionProviderBase'; +import { ITypeScriptServiceClient } from '../typescriptService'; +import * as typeConverters from '../utils/typeConverters'; export default class TypeScriptDefinitionProvider extends DefinitionProviderBase implements DefinitionProvider { - public provideDefinition(document: TextDocument, position: Position, token: CancellationToken | boolean): Promise { + constructor( + client: ITypeScriptServiceClient + ) { + super(client); + } + + public async provideDefinition() { + // Implemented by provideDefinition2 + return undefined; + } + + public async provideDefinition2( + document: TextDocument, + position: Position, + token: CancellationToken | boolean + ): Promise { + if (this.client.apiVersion.has270Features()) { + const filepath = this.client.normalizePath(document.uri); + if (!filepath) { + return undefined; + } + + const args = typeConverters.Position.toFileLocationRequestArgs(filepath, position); + try { + const response = await this.client.execute('definitionAndBoundSpan', args, token); + const locations: Proto.FileSpan[] = (response && response.body && response.body.definitions) || []; + if (!locations) { + return []; + } + + const span = response.body.textSpan ? typeConverters.Location.fromTextSpan(document.uri, response.body.textSpan) : undefined; + return { + definingSpan: span, + definitions: locations + .map(location => typeConverters.Location.fromTextSpan(this.client.asUrl(location.file), location)) + .filter(x => x) as Location[] + }; + } catch { + return []; + } + } + return this.getSymbolLocations('definition', document, position, token); } } \ No newline at end of file diff --git a/extensions/typescript-language-features/src/features/definitionProviderBase.ts b/extensions/typescript-language-features/src/features/definitionProviderBase.ts index f8928579e07cd..93916e42436a7 100644 --- a/extensions/typescript-language-features/src/features/definitionProviderBase.ts +++ b/extensions/typescript-language-features/src/features/definitionProviderBase.ts @@ -11,7 +11,7 @@ import * as typeConverters from '../utils/typeConverters'; export default class TypeScriptDefinitionProviderBase { constructor( - private readonly client: ITypeScriptServiceClient + protected client: ITypeScriptServiceClient ) { } protected async getSymbolLocations( diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index 7d9701574ec86..0772a0285e312 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -520,6 +520,10 @@ export interface Location { */ range: IRange; } +export interface SymbolDefinition { + definingSpan?: Location; + definitions: Location[]; +} /** * The definition of a symbol represented as one or many [locations](#Location). * For most programming languages there is only one location at which a symbol is @@ -536,7 +540,7 @@ export interface DefinitionProvider { /** * Provide the definition of the symbol at the given position and document. */ - provideDefinition(model: model.ITextModel, position: Position, token: CancellationToken): Definition | Thenable; + provideDefinition(model: model.ITextModel, position: Position, token: CancellationToken): Definition | SymbolDefinition | Thenable; } /** diff --git a/src/vs/editor/contrib/goToDeclaration/goToDeclaration.ts b/src/vs/editor/contrib/goToDeclaration/goToDeclaration.ts index f79912d832315..b273d8bdf516e 100644 --- a/src/vs/editor/contrib/goToDeclaration/goToDeclaration.ts +++ b/src/vs/editor/contrib/goToDeclaration/goToDeclaration.ts @@ -10,7 +10,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { ITextModel } from 'vs/editor/common/model'; import { registerDefaultLanguageCommand } from 'vs/editor/browser/editorExtensions'; import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry'; -import { DefinitionProviderRegistry, ImplementationProviderRegistry, TypeDefinitionProviderRegistry, Location } from 'vs/editor/common/modes'; +import { DefinitionProviderRegistry, ImplementationProviderRegistry, TypeDefinitionProviderRegistry, Location, SymbolDefinition } from 'vs/editor/common/modes'; import { CancellationToken } from 'vs/base/common/cancellation'; import { asWinJsPromise } from 'vs/base/common/async'; import { Position } from 'vs/editor/common/core/position'; @@ -20,38 +20,49 @@ function getDefinitions( model: ITextModel, position: Position, registry: LanguageFeatureRegistry, - provide: (provider: T, model: ITextModel, position: Position, token: CancellationToken) => Location | Location[] | Thenable -): TPromise { + provide: (provider: T, model: ITextModel, position: Position, token: CancellationToken) => Location | Location[] | SymbolDefinition | Thenable +): TPromise { const provider = registry.ordered(model); + let definingSpan: Location | undefined = undefined; + // get results const promises = provider.map((provider, idx): TPromise => { return asWinJsPromise((token) => { return provide(provider, model, position, token); - }).then(undefined, err => { + }).then(result => { + if (result && (result as any).definitions) { + definingSpan = definingSpan || (result as any).definingSpan; + return (result as any).definitions; + } + return result; + }, err => { onUnexpectedExternalError(err); return null; }); }); + return TPromise.join(promises) .then(flatten) - .then(references => references.filter(x => !!x)); + .then(references => references.filter(x => !!x)) + .then((definitions): SymbolDefinition => { + return { definingSpan, definitions }; + }); } - -export function getDefinitionsAtPosition(model: ITextModel, position: Position): TPromise { +export function getDefinitionsAtPosition(model: ITextModel, position: Position): TPromise { return getDefinitions(model, position, DefinitionProviderRegistry, (provider, model, position, token) => { return provider.provideDefinition(model, position, token); }); } -export function getImplementationsAtPosition(model: ITextModel, position: Position): TPromise { +export function getImplementationsAtPosition(model: ITextModel, position: Position): TPromise { return getDefinitions(model, position, ImplementationProviderRegistry, (provider, model, position, token) => { return provider.provideImplementation(model, position, token); }); } -export function getTypeDefinitionsAtPosition(model: ITextModel, position: Position): TPromise { +export function getTypeDefinitionsAtPosition(model: ITextModel, position: Position): TPromise { return getDefinitions(model, position, TypeDefinitionProviderRegistry, (provider, model, position, token) => { return provider.provideTypeDefinition(model, position, token); }); diff --git a/src/vs/editor/contrib/goToDeclaration/goToDeclarationCommands.ts b/src/vs/editor/contrib/goToDeclaration/goToDeclarationCommands.ts index f96ba4400cb10..b6e5e87f77b37 100644 --- a/src/vs/editor/contrib/goToDeclaration/goToDeclarationCommands.ts +++ b/src/vs/editor/contrib/goToDeclaration/goToDeclarationCommands.ts @@ -13,7 +13,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IEditorService } from 'vs/platform/editor/common/editor'; import { Range } from 'vs/editor/common/core/range'; import { registerEditorAction, IActionOptions, ServicesAccessor, EditorAction } from 'vs/editor/browser/editorExtensions'; -import { Location } from 'vs/editor/common/modes'; +import { Location, SymbolDefinition } from 'vs/editor/common/modes'; import { getDefinitionsAtPosition, getImplementationsAtPosition, getTypeDefinitionsAtPosition } from './goToDeclaration'; import { ReferencesController } from 'vs/editor/contrib/referenceSearch/referencesController'; import { ReferencesModel } from 'vs/editor/contrib/referenceSearch/referencesModel'; @@ -56,7 +56,8 @@ export class DefinitionAction extends EditorAction { const model = editor.getModel(); const pos = editor.getPosition(); - const definitionPromise = this._getDeclarationsAtPosition(model, pos).then(references => { + const definitionPromise = this._getDeclarationsAtPosition(model, pos).then(symbolDefinition => { + const references = symbolDefinition.definitions; if (model.isDisposed() || editor.getModel() !== model) { // new model, no more model @@ -67,12 +68,11 @@ export class DefinitionAction extends EditorAction { // * find reference at the current pos let idxOfCurrent = -1; let result: Location[] = []; - for (let i = 0; i < references.length; i++) { - let reference = references[i]; - if (!reference || !reference.range) { + for (const location of references) { + if (!location || !location.range) { continue; } - let { uri, range } = reference; + let { uri, range } = location; let newLen = result.push({ uri, range @@ -111,7 +111,7 @@ export class DefinitionAction extends EditorAction { return definitionPromise; } - protected _getDeclarationsAtPosition(model: ITextModel, position: corePosition.Position): TPromise { + protected _getDeclarationsAtPosition(model: ITextModel, position: corePosition.Position): TPromise { return getDefinitionsAtPosition(model, position); } @@ -248,7 +248,7 @@ export class PeekDefinitionAction extends DefinitionAction { } export class ImplementationAction extends DefinitionAction { - protected _getDeclarationsAtPosition(model: ITextModel, position: corePosition.Position): TPromise { + protected _getDeclarationsAtPosition(model: ITextModel, position: corePosition.Position): TPromise { return getImplementationsAtPosition(model, position); } @@ -304,7 +304,7 @@ export class PeekImplementationAction extends ImplementationAction { } export class TypeDefinitionAction extends DefinitionAction { - protected _getDeclarationsAtPosition(model: ITextModel, position: corePosition.Position): TPromise { + protected _getDeclarationsAtPosition(model: ITextModel, position: corePosition.Position): TPromise { return getTypeDefinitionsAtPosition(model, position); } diff --git a/src/vs/editor/contrib/goToDeclaration/goToDeclarationMouse.ts b/src/vs/editor/contrib/goToDeclaration/goToDeclarationMouse.ts index 492acb4f3edf1..734e325a0cdbe 100644 --- a/src/vs/editor/contrib/goToDeclaration/goToDeclarationMouse.ts +++ b/src/vs/editor/contrib/goToDeclaration/goToDeclarationMouse.ts @@ -14,7 +14,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { IModeService } from 'vs/editor/common/services/modeService'; import { Range } from 'vs/editor/common/core/range'; import * as editorCommon from 'vs/editor/common/editorCommon'; -import { Location, DefinitionProviderRegistry } from 'vs/editor/common/modes'; +import { DefinitionProviderRegistry, SymbolDefinition } from 'vs/editor/common/modes'; import { ICodeEditor, IMouseTarget, MouseTargetType } from 'vs/editor/browser/editorBrowser'; import { registerEditorContribution } from 'vs/editor/browser/editorExtensions'; import { getDefinitionsAtPosition } from './goToDeclaration'; @@ -102,25 +102,25 @@ class GotoDefinitionWithMouseEditorContribution implements editorCommon.IEditorC this.throttler.queue(() => { return state.validate(this.editor) ? this.findDefinition(mouseEvent.target) - : TPromise.wrap(null); + : TPromise.wrap(null); - }).then(results => { - if (!results || !results.length || !state.validate(this.editor)) { + }).then(symbolDefinition => { + if (!symbolDefinition || !symbolDefinition.definitions.length || !state.validate(this.editor)) { this.removeDecorations(); return; } // Multiple results - if (results.length > 1) { + if (symbolDefinition.definitions.length > 1) { this.addDecoration( new Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn), - new MarkdownString().appendText(nls.localize('multipleResults', "Click to show {0} definitions.", results.length)) + new MarkdownString().appendText(nls.localize('multipleResults', "Click to show {0} definitions.", symbolDefinition.definitions.length)) ); } // Single result else { - let result = results[0]; + let result = symbolDefinition.definitions[0]; if (!result.uri) { return; @@ -157,8 +157,16 @@ class GotoDefinitionWithMouseEditorContribution implements editorCommon.IEditorC const previewRange = new Range(startLineNumber, 1, endLineNumber + 1, 1); const value = textEditorModel.getValueInRange(previewRange).replace(new RegExp(`^\\s{${minIndent - 1}}`, 'gm'), '').trim(); + let wordRange: Range; + if (symbolDefinition.definingSpan) { + const range = symbolDefinition.definingSpan.range; + wordRange = new Range(range.startLineNumber, range.startColumn, range.endLineNumber, range.endColumn); + } else { + wordRange = new Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn); + } + this.addDecoration( - new Range(position.lineNumber, word.startColumn, position.lineNumber, word.endColumn), + wordRange, new MarkdownString().appendCodeblock(this.modeService.getModeIdByFilenameOrFirstLine(textEditorModel.uri.fsPath), value) ); ref.dispose(); @@ -194,7 +202,7 @@ class GotoDefinitionWithMouseEditorContribution implements editorCommon.IEditorC DefinitionProviderRegistry.has(this.editor.getModel()); } - private findDefinition(target: IMouseTarget): TPromise { + private findDefinition(target: IMouseTarget): TPromise { let model = this.editor.getModel(); if (!model) { return TPromise.as(null); diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index c690f0d6e17fc..7edb9c775cb05 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -4743,6 +4743,11 @@ declare namespace monaco.languages { range: IRange; } + export interface SymbolDefinition { + definingSpan?: Location; + definitions: Location[]; + } + /** * The definition of a symbol represented as one or many [locations](#Location). * For most programming languages there is only one location at which a symbol is @@ -4759,7 +4764,7 @@ declare namespace monaco.languages { /** * Provide the definition of the symbol at the given position and document. */ - provideDefinition(model: editor.ITextModel, position: Position, token: CancellationToken): Definition | Thenable; + provideDefinition(model: editor.ITextModel, position: Position, token: CancellationToken): Definition | SymbolDefinition | Thenable; } /** diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index b28b3f0c0efbf..41d279ac32cf9 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -870,4 +870,19 @@ declare module 'vscode' { } //#endregion + + //#region Defintion symbol range: mjbvz + + export interface SymbolDefinition { + definingSpan?: Location; + + definitions: Location[]; + } + + export interface DefinitionProvider { + + provideDefinition2?(document: TextDocument, position: Position, token: CancellationToken): ProviderResult; + } + + //#endregion } diff --git a/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts b/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts index d9057794eab0d..15d5bd5e4a19c 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadLanguageFeatures.ts @@ -14,7 +14,7 @@ import { wireCancellationToken } from 'vs/base/common/async'; import { CancellationToken } from 'vs/base/common/cancellation'; import { Position as EditorPosition } from 'vs/editor/common/core/position'; import { Range as EditorRange, IRange } from 'vs/editor/common/core/range'; -import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ISerializedLanguageConfiguration, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, LocationDto, SymbolInformationDto, CodeActionDto, reviveWorkspaceEditDto, ISerializedDocumentFilter } from '../node/extHost.protocol'; +import { ExtHostContext, MainThreadLanguageFeaturesShape, ExtHostLanguageFeaturesShape, MainContext, IExtHostContext, ISerializedLanguageConfiguration, ISerializedRegExp, ISerializedIndentationRule, ISerializedOnEnterRule, LocationDto, SymbolInformationDto, CodeActionDto, reviveWorkspaceEditDto, ISerializedDocumentFilter, SymbolDefinitionDto } from '../node/extHost.protocol'; import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry'; import { LanguageConfiguration, IndentationRule, OnEnterRule } from 'vs/editor/common/modes/languageConfiguration'; import { IHeapService } from './mainThreadHeapService'; @@ -71,6 +71,19 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha } } + private static _reviveSymbolDefinitionDto(data: SymbolDefinitionDto): modes.SymbolDefinition { + if (!data) { + return data; + } + + if (data.definingSpan) { + data.definingSpan = this._reviveLocationDto(data.definingSpan); + } + + data.definitions = data.definitions.map(x => this._reviveLocationDto(x)); + return data; + } + private static _reviveSymbolInformationDto(data: SymbolInformationDto): modes.SymbolInformation; private static _reviveSymbolInformationDto(data: SymbolInformationDto[]): modes.SymbolInformation[]; private static _reviveSymbolInformationDto(data: SymbolInformationDto | SymbolInformationDto[]): modes.SymbolInformation | modes.SymbolInformation[] { @@ -137,8 +150,14 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha $registerDeclaractionSupport(handle: number, selector: ISerializedDocumentFilter[]): void { this._registrations[handle] = modes.DefinitionProviderRegistry.register(toLanguageSelector(selector), { - provideDefinition: (model, position, token): Thenable => { - return wireCancellationToken(token, this._proxy.$provideDefinition(handle, model.uri, position)).then(MainThreadLanguageFeatures._reviveLocationDto); + provideDefinition: (model, position, token): Thenable => { + return wireCancellationToken(token, this._proxy.$provideDefinition(handle, model.uri, position)).then(x => { + if ((x as any).definitions) { + return MainThreadLanguageFeatures._reviveSymbolDefinitionDto(x as any); + } + + return MainThreadLanguageFeatures._reviveLocationDto(x as any); + }); } }); } diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index dc3145effd14e..ba529868c0ef5 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -649,6 +649,7 @@ export function createApiFactory( CompletionList: extHostTypes.CompletionList, CompletionTriggerKind: extHostTypes.CompletionTriggerKind, DebugAdapterExecutable: extHostTypes.DebugAdapterExecutable, + SymbolDefinition: extHostTypes.SymbolDefinition, Diagnostic: extHostTypes.Diagnostic, DiagnosticRelatedInformation: extHostTypes.DiagnosticRelatedInformation, DiagnosticSeverity: extHostTypes.DiagnosticSeverity, diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index 4d160267c77e2..e8a4c76cdcd2d 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -641,6 +641,11 @@ export interface LocationDto { range: IRange; } +export interface SymbolDefinitionDto { + definingSpan?: LocationDto; + definitions: LocationDto[]; +} + export interface SymbolInformationDto extends IdObject { name: string; containerName?: string; @@ -696,7 +701,7 @@ export interface ExtHostLanguageFeaturesShape { $provideDocumentSymbols(handle: number, resource: UriComponents): TPromise; $provideCodeLenses(handle: number, resource: UriComponents): TPromise; $resolveCodeLens(handle: number, resource: UriComponents, symbol: modes.ICodeLensSymbol): TPromise; - $provideDefinition(handle: number, resource: UriComponents, position: IPosition): TPromise; + $provideDefinition(handle: number, resource: UriComponents, position: IPosition): TPromise; $provideImplementation(handle: number, resource: UriComponents, position: IPosition): TPromise; $provideTypeDefinition(handle: number, resource: UriComponents, position: IPosition): TPromise; $provideHover(handle: number, resource: UriComponents, position: IPosition): TPromise; diff --git a/src/vs/workbench/api/node/extHostLanguageFeatures.ts b/src/vs/workbench/api/node/extHostLanguageFeatures.ts index 0d4825c77bd19..b6b2a28df8a82 100644 --- a/src/vs/workbench/api/node/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/node/extHostLanguageFeatures.ts @@ -110,16 +110,36 @@ class DefinitionAdapter { this._provider = provider; } - provideDefinition(resource: URI, position: IPosition): TPromise { + provideDefinition(resource: URI, position: IPosition): TPromise { let doc = this._documents.getDocumentData(resource).document; let pos = TypeConverters.toPosition(position); + + if (this._provider.provideDefinition2) { + return asWinJsPromise(token => this._provider.provideDefinition2(doc, pos, token)).then(value => { + if (!value) { + return undefined; + } + + if (Array.isArray(value)) { + return value.map(TypeConverters.location.from); + } else if ((value as any).definitions) { + return TypeConverters.SymbolDefinition.from(value as any); + } else { + return TypeConverters.location.from(value as vscode.Location); + } + }); + } + return asWinJsPromise(token => this._provider.provideDefinition(doc, pos, token)).then(value => { + if (!value) { + return undefined; + } + if (Array.isArray(value)) { return value.map(TypeConverters.location.from); - } else if (value) { - return TypeConverters.location.from(value); + } else { + return TypeConverters.location.from(value as vscode.Location); } - return undefined; }); } } @@ -951,7 +971,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape { return this._createDisposable(handle); } - $provideDefinition(handle: number, resource: UriComponents, position: IPosition): TPromise { + $provideDefinition(handle: number, resource: UriComponents, position: IPosition): TPromise { return this._withAdapter(handle, DefinitionAdapter, adapter => adapter.provideDefinition(URI.revive(resource), position)); } diff --git a/src/vs/workbench/api/node/extHostTypeConverters.ts b/src/vs/workbench/api/node/extHostTypeConverters.ts index 0f4121566744f..0863b7b23d2ae 100644 --- a/src/vs/workbench/api/node/extHostTypeConverters.ts +++ b/src/vs/workbench/api/node/extHostTypeConverters.ts @@ -4,23 +4,23 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import * as modes from 'vs/editor/common/modes'; -import * as types from './extHostTypes'; -import { Position as EditorPosition, ITextEditorOptions } from 'vs/platform/editor/common/editor'; -import { IDecorationOptions } from 'vs/editor/common/editorCommon'; -import { EndOfLineSequence } from 'vs/editor/common/model'; -import * as vscode from 'vscode'; +import { IRelativePattern } from 'vs/base/common/glob'; +import * as htmlContent from 'vs/base/common/htmlContent'; import URI from 'vs/base/common/uri'; -import { ProgressLocation as MainProgressLocation } from 'vs/platform/progress/common/progress'; -import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles'; import { IPosition } from 'vs/editor/common/core/position'; import { IRange } from 'vs/editor/common/core/range'; 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'; -import { WorkspaceEditDto, ResourceTextEditDto } from 'vs/workbench/api/node/extHost.protocol'; -import { MarkerSeverity, IRelatedInformation, IMarkerData } from 'vs/platform/markers/common/markers'; +import { IDecorationOptions } from 'vs/editor/common/editorCommon'; +import { EndOfLineSequence } from 'vs/editor/common/model'; +import * as modes from 'vs/editor/common/modes'; +import { LanguageFilter, LanguageSelector } from 'vs/editor/common/modes/languageSelector'; +import { ITextEditorOptions, Position as EditorPosition } from 'vs/platform/editor/common/editor'; +import { IMarkerData, IRelatedInformation, MarkerSeverity } from 'vs/platform/markers/common/markers'; +import { ProgressLocation as MainProgressLocation } from 'vs/platform/progress/common/progress'; +import { ResourceTextEditDto, WorkspaceEditDto } from 'vs/workbench/api/node/extHost.protocol'; +import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles'; +import * as vscode from 'vscode'; +import * as types from './extHostTypes'; export interface PositionLike { line: number; @@ -364,6 +364,16 @@ export const location = { } }; +export namespace SymbolDefinition { + export function from(value: vscode.SymbolDefinition): modes.SymbolDefinition { + const span = value.definingSpan ? location.from(value.definingSpan) : undefined; + return { + definingSpan: span, + definitions: value.definitions.map(location.from) + }; + } +} + export function fromHover(hover: vscode.Hover): modes.Hover { return { range: fromRange(hover.range), diff --git a/src/vs/workbench/api/node/extHostTypes.ts b/src/vs/workbench/api/node/extHostTypes.ts index 1423c27788268..873777b94311b 100644 --- a/src/vs/workbench/api/node/extHostTypes.ts +++ b/src/vs/workbench/api/node/extHostTypes.ts @@ -739,6 +739,23 @@ export class DiagnosticRelatedInformation { } } +export class SymbolDefinition { + span: Location; + definitions: Location[]; + + constructor(span: Location, definitions: Location[]) { + this.span = span; + + if (!definitions) { + // skip + } else if (Array.isArray(definitions)) { + this.definitions = definitions; + } else { + throw new Error('Illegal argument'); + } + } +} + export class Diagnostic { range: Range; 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 511e5e963e581..924e41afa195f 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostLanguageFeatures.test.ts @@ -276,8 +276,8 @@ suite('ExtHostLanguageFeatures', function () { return rpcProtocol.sync().then(() => { return getDefinitionsAtPosition(model, new EditorPosition(1, 1)).then(value => { - assert.equal(value.length, 1); - let [entry] = value; + assert.equal(value.definitions.length, 1); + let [entry] = value.definitions; assert.deepEqual(entry.range, { startLineNumber: 2, startColumn: 3, endLineNumber: 4, endColumn: 5 }); assert.equal(entry.uri.toString(), model.uri.toString()); }); @@ -300,7 +300,7 @@ suite('ExtHostLanguageFeatures', function () { return rpcProtocol.sync().then(() => { return getDefinitionsAtPosition(model, new EditorPosition(1, 1)).then(value => { - assert.equal(value.length, 2); + assert.equal(value.definitions.length, 2); }); }); }); @@ -322,7 +322,7 @@ suite('ExtHostLanguageFeatures', function () { return rpcProtocol.sync().then(() => { return getDefinitionsAtPosition(model, new EditorPosition(1, 1)).then(value => { - assert.equal(value.length, 2); + assert.equal(value.definitions.length, 2); // let [first, second] = value; assert.equal(value[0].uri.authority, 'second'); @@ -347,7 +347,7 @@ suite('ExtHostLanguageFeatures', function () { return rpcProtocol.sync().then(() => { return getDefinitionsAtPosition(model, new EditorPosition(1, 1)).then(value => { - assert.equal(value.length, 1); + assert.equal(value.definitions.length, 1); }); }); }); @@ -364,8 +364,8 @@ suite('ExtHostLanguageFeatures', function () { return rpcProtocol.sync().then(() => { return getImplementationsAtPosition(model, new EditorPosition(1, 1)).then(value => { - assert.equal(value.length, 1); - let [entry] = value; + assert.equal(value.definitions.length, 1); + let [entry] = value.definitions; assert.deepEqual(entry.range, { startLineNumber: 2, startColumn: 3, endLineNumber: 4, endColumn: 5 }); assert.equal(entry.uri.toString(), model.uri.toString()); }); @@ -384,8 +384,8 @@ suite('ExtHostLanguageFeatures', function () { return rpcProtocol.sync().then(() => { return getTypeDefinitionsAtPosition(model, new EditorPosition(1, 1)).then(value => { - assert.equal(value.length, 1); - let [entry] = value; + assert.equal(value.definitions.length, 1); + let [entry] = value.definitions; assert.deepEqual(entry.range, { startLineNumber: 2, startColumn: 3, endLineNumber: 4, endColumn: 5 }); assert.equal(entry.uri.toString(), model.uri.toString()); });