提交 9d611d4d 编写于 作者: M Matt Bierner 提交者: GitHub

Add Go To Implementation Api (#18346)

* Add Go To Implementation Api

For #10806

Adds a new API for supporting  `go to implementation` command for languages. Implements an example for TS

* Rename

* Cleanup
上级 46e5ddde
......@@ -5,50 +5,18 @@
'use strict';
import { DefinitionProvider, TextDocument, Position, Range, CancellationToken, Definition, Location } from 'vscode';
import { DefinitionProvider, TextDocument, Position, CancellationToken, Definition } from 'vscode';
import * as Proto from '../protocol';
import { ITypescriptServiceClient } from '../typescriptService';
import DefinitionProviderBase from './definitionProviderBase';
export default class TypeScriptDefinitionProvider implements DefinitionProvider {
private client: ITypescriptServiceClient;
public tokens: string[] = [];
export default class TypeScriptDefinitionProvider extends DefinitionProviderBase implements DefinitionProvider {
constructor(client: ITypescriptServiceClient) {
this.client = client;
super(client);
}
public provideDefinition(document: TextDocument, position: Position, token: CancellationToken): Promise<Definition | null> {
const filepath = this.client.asAbsolutePath(document.uri);
if (!filepath) {
return Promise.resolve(null);
}
let args: Proto.FileLocationRequestArgs = {
file: filepath,
line: position.line + 1,
offset: position.character + 1
};
if (!args.file) {
return Promise.resolve(null);
}
return this.client.execute('definition', args, token).then(response => {
let locations: Proto.FileSpan[] = response.body || [];
if (!locations || locations.length === 0) {
return [] as Definition;
}
return locations.map(location => {
let resource = this.client.asUrl(location.file);
if (resource === null) {
return null;
} else {
return new Location(resource, new Range(location.start.line - 1, location.start.offset - 1, location.end.line - 1, location.end.offset - 1));
}
}).filter(x => x !== null) as Location[];
}, (error) => {
this.client.error(`'definition' request failed with error.`, error);
return [] as Definition;
});
public provideDefinition(document: TextDocument, position: Position, token: CancellationToken | boolean): Promise<Definition | null> {
return this.getSymbolLocations('definition', document, position, token);
}
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* 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 { TextDocument, Position, Range, CancellationToken, Location } from 'vscode';
import * as Proto from '../protocol';
import { ITypescriptServiceClient } from '../typescriptService';
export default class TypeScriptDefinitionProviderBase {
private client: ITypescriptServiceClient;
public tokens: string[] = [];
constructor(client: ITypescriptServiceClient) {
this.client = client;
}
protected getSymbolLocations(definitionType: 'definition' | 'implementation', document: TextDocument, position: Position, token: CancellationToken | boolean): Promise<Location[] | null> {
const filepath = this.client.asAbsolutePath(document.uri);
if (!filepath) {
return Promise.resolve(null);
}
let args: Proto.FileLocationRequestArgs = {
file: filepath,
line: position.line + 1,
offset: position.character + 1
};
if (!args.file) {
return Promise.resolve(null);
}
return this.client.execute(definitionType, args, token).then(response => {
let locations: Proto.FileSpan[] = (response && response.body) || [];
if (!locations || locations.length === 0) {
return [];
}
return locations.map(location => {
let resource = this.client.asUrl(location.file);
if (resource === null) {
return null;
} else {
return new Location(resource, new Range(location.start.line - 1, location.start.offset - 1, location.end.line - 1, location.end.offset - 1));
}
}).filter(x => x !== null) as Location[];
}, (error) => {
this.client.error(`'${definitionType}' request failed with error.`, error);
return [];
});
}
}
\ No newline at end of file
/*---------------------------------------------------------------------------------------------
* 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 { TypeDefinitionProvider, TextDocument, Position, CancellationToken, Definition } from 'vscode';
import { ITypescriptServiceClient } from '../typescriptService';
import DefinitionProviderBase from './definitionProviderBase';
export default class TypeScriptTypeDefinitionProvider extends DefinitionProviderBase implements TypeDefinitionProvider {
constructor(client: ITypescriptServiceClient) {
super(client);
}
public provideTypeDefinition(document: TextDocument, position: Position, token: CancellationToken | boolean): Promise<Definition | null> {
return this.getSymbolLocations('implementation', document, position, token);
}
}
\ No newline at end of file
......@@ -25,6 +25,7 @@ import { ITypescriptServiceClientHost } from './typescriptService';
import HoverProvider from './features/hoverProvider';
import DefinitionProvider from './features/definitionProvider';
import TypeDefinitionProvider from './features/TypeDefinitionProvider';
import DocumentHighlightProvider from './features/documentHighlightProvider';
import ReferenceProvider from './features/referenceProvider';
import DocumentSymbolProvider from './features/documentSymbolProvider';
......@@ -147,6 +148,7 @@ class LanguageProvider {
let hoverProvider = new HoverProvider(client);
let definitionProvider = new DefinitionProvider(client);
let typeDefinitionProvider = new TypeDefinitionProvider(client);
let documentHighlightProvider = new DocumentHighlightProvider(client);
let referenceProvider = new ReferenceProvider(client);
let documentSymbolProvider = new DocumentSymbolProvider(client);
......@@ -169,6 +171,7 @@ class LanguageProvider {
languages.registerCompletionItemProvider(selector, this.completionItemProvider, '.');
languages.registerHoverProvider(selector, hoverProvider);
languages.registerDefinitionProvider(selector, definitionProvider);
languages.registerTypeDefinitionProvider(selector, typeDefinitionProvider);
languages.registerDocumentHighlightProvider(selector, documentHighlightProvider);
languages.registerReferenceProvider(selector, referenceProvider);
languages.registerDocumentSymbolProvider(selector, documentSymbolProvider);
......
......@@ -87,6 +87,7 @@ export interface ITypescriptServiceClient {
execute(commant: 'completionEntryDetails', args: Proto.CompletionDetailsRequestArgs, token?: CancellationToken): Promise<Proto.CompletionDetailsResponse>;
execute(commant: 'signatureHelp', args: Proto.SignatureHelpRequestArgs, token?: CancellationToken): Promise<Proto.SignatureHelpResponse>;
execute(command: 'definition', args: Proto.FileLocationRequestArgs, token?: CancellationToken): Promise<Proto.DefinitionResponse>;
execute(command: 'implementation', args: Proto.FileLocationRequestArgs, token?: CancellationToken): Promise<Proto.ImplementationResponse>;
execute(command: 'references', args: Proto.FileLocationRequestArgs, token?: CancellationToken): Promise<Proto.ReferencesResponse>;
execute(command: 'navto', args: Proto.NavtoRequestArgs, token?: CancellationToken): Promise<Proto.NavtoResponse>;
execute(command: 'navbar', args: Proto.FileRequestArgs, token?: CancellationToken): Promise<Proto.NavBarResponse>;
......
......@@ -276,6 +276,13 @@ export function registerDefinitionProvider(languageId: string, provider: modes.D
return modes.DefinitionProviderRegistry.register(languageId, provider);
}
/**
* Register a type definition provider (used by e.g. go to implementation).
*/
export function registerTypeDefinitionProvider(languageId: string, provider: modes.TypeDefinitionProvider): IDisposable {
return modes.TypeDefinitionProviderRegistry.register(languageId, provider);
}
/**
* Register a code lens provider (used by e.g. inline code lenses).
*/
......@@ -633,6 +640,7 @@ export function createMonacoLanguagesAPI(): typeof monaco.languages {
registerDocumentSymbolProvider: registerDocumentSymbolProvider,
registerDocumentHighlightProvider: registerDocumentHighlightProvider,
registerDefinitionProvider: registerDefinitionProvider,
registerTypeDefinitionProvider: registerTypeDefinitionProvider,
registerCodeLensProvider: registerCodeLensProvider,
registerCodeActionProvider: registerCodeActionProvider,
registerDocumentFormattingEditProvider: registerDocumentFormattingEditProvider,
......
......@@ -3064,6 +3064,10 @@ export namespace ModeContextKeys {
* @internal
*/
export const hasDefinitionProvider = new RawContextKey<boolean>('editorHasDefinitionProvider', undefined);
/**
* @internal
*/
export const hasTypeDefinitionProvider = new RawContextKey<boolean>('editorHasTypeDefinitionProvider', undefined);
/**
* @internal
*/
......
......@@ -418,6 +418,7 @@ export interface Location {
* defined.
*/
export type Definition = Location | Location[];
/**
* The definition provider interface defines the contract between extensions and
* the [go to definition](https://code.visualstudio.com/docs/editor/editingevolved#_go-to-definition)
......@@ -430,6 +431,16 @@ export interface DefinitionProvider {
provideDefinition(model: editorCommon.IReadOnlyModel, position: Position, token: CancellationToken): Definition | Thenable<Definition>;
}
/**
* The type definition provider interface defines the contract between extensions and
* the go to implementation feature.
*/
export interface TypeDefinitionProvider {
/**
* Provide the implementation of the symbol at the given position and document.
*/
provideTypeDefinition(model: editorCommon.IReadOnlyModel, position: Position, token: CancellationToken): Definition | Thenable<Definition>;
}
/**
* A symbol kind.
......@@ -738,6 +749,11 @@ export const DocumentHighlightProviderRegistry = new LanguageFeatureRegistry<Doc
*/
export const DefinitionProviderRegistry = new LanguageFeatureRegistry<DefinitionProvider>();
/**
* @internal
*/
export const TypeDefinitionProviderRegistry = new LanguageFeatureRegistry<TypeDefinitionProvider>();
/**
* @internal
*/
......
......@@ -19,6 +19,7 @@ export class EditorModeContext {
private _hasCodeActionsProvider: IContextKey<boolean>;
private _hasCodeLensProvider: IContextKey<boolean>;
private _hasDefinitionProvider: IContextKey<boolean>;
private _hasTypeDefinitionProvider: IContextKey<boolean>;
private _hasHoverProvider: IContextKey<boolean>;
private _hasDocumentHighlightProvider: IContextKey<boolean>;
private _hasDocumentSymbolProvider: IContextKey<boolean>;
......@@ -39,6 +40,7 @@ export class EditorModeContext {
this._hasCodeActionsProvider = ModeContextKeys.hasCodeActionsProvider.bindTo(contextKeyService);
this._hasCodeLensProvider = ModeContextKeys.hasCodeLensProvider.bindTo(contextKeyService);
this._hasDefinitionProvider = ModeContextKeys.hasDefinitionProvider.bindTo(contextKeyService);
this._hasTypeDefinitionProvider = ModeContextKeys.hasTypeDefinitionProvider.bindTo(contextKeyService);
this._hasHoverProvider = ModeContextKeys.hasHoverProvider.bindTo(contextKeyService);
this._hasDocumentHighlightProvider = ModeContextKeys.hasDocumentHighlightProvider.bindTo(contextKeyService);
this._hasDocumentSymbolProvider = ModeContextKeys.hasDocumentSymbolProvider.bindTo(contextKeyService);
......@@ -57,6 +59,7 @@ export class EditorModeContext {
modes.CodeActionProviderRegistry.onDidChange(this._update, this, this._disposables);
modes.CodeLensProviderRegistry.onDidChange(this._update, this, this._disposables);
modes.DefinitionProviderRegistry.onDidChange(this._update, this, this._disposables);
modes.TypeDefinitionProviderRegistry.onDidChange(this._update, this, this._disposables);
modes.HoverProviderRegistry.onDidChange(this._update, this, this._disposables);
modes.DocumentHighlightProviderRegistry.onDidChange(this._update, this, this._disposables);
modes.DocumentSymbolProviderRegistry.onDidChange(this._update, this, this._disposables);
......@@ -79,6 +82,7 @@ export class EditorModeContext {
this._hasCodeActionsProvider.reset();
this._hasCodeLensProvider.reset();
this._hasDefinitionProvider.reset();
this._hasTypeDefinitionProvider.reset();
this._hasHoverProvider.reset();
this._hasDocumentHighlightProvider.reset();
this._hasDocumentSymbolProvider.reset();
......@@ -100,6 +104,7 @@ export class EditorModeContext {
this._hasCodeActionsProvider.set(modes.CodeActionProviderRegistry.has(model));
this._hasCodeLensProvider.set(modes.CodeLensProviderRegistry.has(model));
this._hasDefinitionProvider.set(modes.DefinitionProviderRegistry.has(model));
this._hasTypeDefinitionProvider.set(modes.TypeDefinitionProviderRegistry.has(model));
this._hasHoverProvider.set(modes.HoverProviderRegistry.has(model));
this._hasDocumentHighlightProvider.set(modes.DocumentHighlightProviderRegistry.has(model));
this._hasDocumentSymbolProvider.set(modes.DocumentSymbolProviderRegistry.has(model));
......
......@@ -26,13 +26,14 @@ import { editorAction, IActionOptions, ServicesAccessor, EditorAction } from 'vs
import { Location, DefinitionProviderRegistry } from 'vs/editor/common/modes';
import { ICodeEditor, IEditorMouseEvent, IMouseTarget } from 'vs/editor/browser/editorBrowser';
import { editorContribution } from 'vs/editor/browser/editorBrowserExtensions';
import { getDeclarationsAtPosition } from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration';
import { getDeclarationsAtPosition, getTypeDefinitionAtPosition } from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration';
import { ReferencesController } from 'vs/editor/contrib/referenceSearch/browser/referencesController';
import { ReferencesModel } from 'vs/editor/contrib/referenceSearch/browser/referencesModel';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { PeekContext } from 'vs/editor/contrib/zoneWidget/browser/peekViewWidget';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { ITextModelResolverService } from 'vs/editor/common/services/resolverService';
import * as corePosition from 'vs/editor/common/core/position';
import ModeContextKeys = editorCommon.ModeContextKeys;
import EditorContextKeys = editorCommon.EditorContextKeys;
......@@ -64,7 +65,7 @@ export class DefinitionAction extends EditorAction {
let model = editor.getModel();
let pos = editor.getPosition();
return getDeclarationsAtPosition(model, pos).then(references => {
return this.getDeclarationsAtPosition(model, pos).then(references => {
if (!references) {
return;
......@@ -104,6 +105,10 @@ export class DefinitionAction extends EditorAction {
});
}
protected getDeclarationsAtPosition(model: editorCommon.IModel, position: corePosition.Position): TPromise<Location[]> {
return getDeclarationsAtPosition(model, position);
}
private _onResult(editorService: IEditorService, editor: editorCommon.ICommonCodeEditor, model: ReferencesModel) {
if (this._configuration.openInPeek) {
this._openInPeek(editorService, editor, model);
......@@ -217,6 +222,35 @@ export class PeekDefinitionAction extends DefinitionAction {
}
}
@editorAction
export class GoToImplementationAction extends DefinitionAction {
public static ID = 'editor.action.goToImplementation';
constructor() {
super(new DefinitionActionConfig(), {
id: GoToImplementationAction.ID,
label: nls.localize('actions.goToImplementation.label', "Go to Implementation"),
alias: 'Go to Implementation',
precondition: ModeContextKeys.hasTypeDefinitionProvider,
kbOpts: {
kbExpr: EditorContextKeys.TextFocus,
primary: KeyMod.CtrlCmd | KeyCode.F12
},
menuOpts: {
group: 'navigation',
order: 1.3
}
});
}
protected getDeclarationsAtPosition(model: editorCommon.IModel, position: corePosition.Position): TPromise<Location[]> {
return getTypeDefinitionAtPosition(model, position);
}
}
// --- Editor Contribution to goto definition using the mouse and a modifier key
@editorContribution
......
......@@ -9,10 +9,24 @@ import { onUnexpectedExternalError } from 'vs/base/common/errors';
import { TPromise } from 'vs/base/common/winjs.base';
import { IReadOnlyModel } from 'vs/editor/common/editorCommon';
import { CommonEditorRegistry } from 'vs/editor/common/editorCommonExtensions';
import { DefinitionProviderRegistry, Location } from 'vs/editor/common/modes';
import { DefinitionProviderRegistry, TypeDefinitionProviderRegistry, Location } from 'vs/editor/common/modes';
import { asWinJsPromise } from 'vs/base/common/async';
import { Position } from 'vs/editor/common/core/position';
function outputResults(promises: TPromise<Location[]>[]) {
return TPromise.join(promises).then(allReferences => {
let result: Location[] = [];
for (let references of allReferences) {
if (Array.isArray(references)) {
result.push(...references);
} else if (references) {
result.push(references);
}
}
return result;
});
}
export function getDeclarationsAtPosition(model: IReadOnlyModel, position: Position): TPromise<Location[]> {
const provider = DefinitionProviderRegistry.ordered(model);
......@@ -27,18 +41,25 @@ export function getDeclarationsAtPosition(model: IReadOnlyModel, position: Posit
onUnexpectedExternalError(err);
});
});
return outputResults(promises);
}
return TPromise.join(promises).then(allReferences => {
let result: Location[] = [];
for (let references of allReferences) {
if (Array.isArray(references)) {
result.push(...references);
} else if (references) {
result.push(references);
}
}
return result;
export function getTypeDefinitionAtPosition(model: IReadOnlyModel, position: Position): TPromise<Location[]> {
const provider = TypeDefinitionProviderRegistry.ordered(model);
// get results
const promises = provider.map((provider, idx) => {
return asWinJsPromise((token) => {
return provider.provideTypeDefinition(model, position, token);
}).then(result => {
return result;
}, err => {
onUnexpectedExternalError(err);
});
});
return outputResults(promises);
}
CommonEditorRegistry.registerDefaultLanguageCommand('_executeDefinitionProvider', getDeclarationsAtPosition);
\ No newline at end of file
CommonEditorRegistry.registerDefaultLanguageCommand('_executeDefinitionProvider', getDeclarationsAtPosition);
CommonEditorRegistry.registerDefaultLanguageCommand('_executeTypeDefinitionProvider', getTypeDefinitionAtPosition);
\ No newline at end of file
......@@ -3960,6 +3960,11 @@ declare module monaco.languages {
*/
export function registerDefinitionProvider(languageId: string, provider: DefinitionProvider): IDisposable;
/**
* Register a type definition provider (used by e.g. go to implementation).
*/
export function registerTypeDefinitionProvider(languageId: string, provider: TypeDefinitionProvider): IDisposable;
/**
* Register a code lens provider (used by e.g. inline code lenses).
*/
......@@ -4539,6 +4544,17 @@ declare module monaco.languages {
provideDefinition(model: editor.IReadOnlyModel, position: Position, token: CancellationToken): Definition | Thenable<Definition>;
}
/**
* The type definition provider interface defines the contract between extensions and
* the go to implementation feature.
*/
export interface TypeDefinitionProvider {
/**
* Provide the implementation of the symbol at the given position and document.
*/
provideTypeDefinition(model: editor.IReadOnlyModel, position: Position, token: CancellationToken): Definition | Thenable<Definition>;
}
/**
* A symbol kind.
*/
......
......@@ -1632,6 +1632,24 @@ declare module 'vscode' {
provideDefinition(document: TextDocument, position: Position, token: CancellationToken): ProviderResult<Definition>;
}
/**
* The type definition provider interface defines the contract between extensions and
* the go to implementation feature.
*/
export interface TypeDefinitionProvider {
/**
* Provide the implementations of the symbol at the given position and document.
*
* @param document The document in which the command was invoked.
* @param position The position at which the command was invoked.
* @param token A cancellation token.
* @return A definition or a thenable that resolves to such. The lack of a result can be
* signaled by returning `undefined` or `null`.
*/
provideTypeDefinition(document: TextDocument, position: Position, token: CancellationToken): ProviderResult<Definition>;
}
/**
* MarkedString can be used to render human readable text. It is either a markdown string
* or a code-block that provides a language and a code snippet. Note that
......@@ -4117,6 +4135,18 @@ declare module 'vscode' {
*/
export function registerDefinitionProvider(selector: DocumentSelector, provider: DefinitionProvider): Disposable;
/**
* Register an type definition provider.
*
* Multiple providers can be registered for a language. In that case providers are sorted
* by their [score](#languages.match) and the best-matching provider is used.
*
* @param selector A selector that defines the documents this provider is applicable to.
* @param provider An implementation provider.
* @return A [disposable](#Disposable) that unregisters this provider when being disposed.
*/
export function registerTypeDefinitionProvider(selector: DocumentSelector, provider: TypeDefinitionProvider): Disposable;
/**
* Register a hover provider.
*
......
......@@ -180,6 +180,9 @@ export function createApiFactory(initData: IInitData, threadService: IThreadServ
registerDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.DefinitionProvider): vscode.Disposable {
return languageFeatures.registerDefinitionProvider(selector, provider);
},
registerTypeDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.TypeDefinitionProvider): vscode.Disposable {
return languageFeatures.registerTypeDefinitionProvider(selector, provider);
},
registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider): vscode.Disposable {
return languageFeatures.registerHoverProvider(selector, provider);
},
......
......@@ -153,6 +153,7 @@ export abstract class MainThreadLanguageFeaturesShape {
$registerCodeLensSupport(handle: number, selector: vscode.DocumentSelector, eventHandle: number): TPromise<any> { throw ni(); }
$emitCodeLensEvent(eventHandle: number, event?: any): TPromise<any> { throw ni(); }
$registerDeclaractionSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$registerImplementationSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$registerHoverProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$registerDocumentHighlightProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
$registerReferenceSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> { throw ni(); }
......@@ -329,6 +330,7 @@ export abstract class ExtHostLanguageFeaturesShape {
$provideCodeLenses(handle: number, resource: URI): TPromise<modes.ICodeLensSymbol[]> { throw ni(); }
$resolveCodeLens(handle: number, resource: URI, symbol: modes.ICodeLensSymbol): TPromise<modes.ICodeLensSymbol> { throw ni(); }
$provideDefinition(handle: number, resource: URI, position: editorCommon.IPosition): TPromise<modes.Definition> { throw ni(); }
$provideTypeDefinition(handle: number, resource: URI, position: editorCommon.IPosition): TPromise<modes.Definition> { throw ni(); }
$provideHover(handle: number, resource: URI, position: editorCommon.IPosition): TPromise<modes.Hover> { throw ni(); }
$provideDocumentHighlights(handle: number, resource: URI, position: editorCommon.IPosition): TPromise<modes.DocumentHighlight[]> { throw ni(); }
$provideReferences(handle: number, resource: URI, position: editorCommon.IPosition, context: modes.ReferenceContext): TPromise<modes.Location[]> { throw ni(); }
......
......@@ -46,6 +46,14 @@ export class ExtHostApiCommands {
],
returns: 'A promise that resolves to an array of Location-instances.'
});
this._register('vscode.executeTypeDefinitionProvider', this._executeTypeDefinitionProvider, {
description: 'Execute all implementation providers.',
args: [
{ name: 'uri', description: 'Uri of a text document', constraint: URI },
{ name: 'position', description: 'Position of a symbol', constraint: types.Position }
],
returns: 'A promise that resolves to an array of Location-instance.'
});
this._register('vscode.executeHoverProvider', this._executeHoverProvider, {
description: 'Execute all hover provider.',
args: [
......@@ -265,6 +273,18 @@ export class ExtHostApiCommands {
});
}
private _executeTypeDefinitionProvider(resource: URI, position: types.Position): Thenable<types.Location[]> {
const args = {
resource,
position: position && typeConverters.fromPosition(position)
};
return this._commands.executeCommand<modes.Location[]>('_executeTypeDefinitionProvider', args).then(value => {
if (Array.isArray(value)) {
return value.map(typeConverters.location.to);
}
});
}
private _executeHoverProvider(resource: URI, position: types.Position): Thenable<types.Hover[]> {
const args = {
resource,
......
......@@ -122,6 +122,29 @@ class DefinitionAdapter {
}
}
class ImplementationAdapter {
private _documents: ExtHostDocuments;
private _provider: vscode.TypeDefinitionProvider;
constructor(documents: ExtHostDocuments, provider: vscode.TypeDefinitionProvider) {
this._documents = documents;
this._provider = provider;
}
provideTypeDefinition(resource: URI, position: IPosition): TPromise<modes.Definition> {
let doc = this._documents.getDocumentData(resource).document;
let pos = TypeConverters.toPosition(position);
return asWinJsPromise(token => this._provider.provideTypeDefinition(doc, pos, token)).then(value => {
if (Array.isArray(value)) {
return value.map(TypeConverters.location.from);
} else if (value) {
return TypeConverters.location.from(value);
}
});
}
}
class HoverAdapter {
private _documents: ExtHostDocuments;
......@@ -614,7 +637,7 @@ class LinkProviderAdapter {
type Adapter = OutlineAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter
| DocumentHighlightAdapter | ReferenceAdapter | QuickFixAdapter | DocumentFormattingAdapter
| RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter
| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter;
| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter;
export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
......@@ -713,6 +736,17 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
return this._withAdapter(handle, DefinitionAdapter, adapter => adapter.provideDefinition(resource, position));
}
registerTypeDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.TypeDefinitionProvider): vscode.Disposable {
const handle = this._nextHandle();
this._adapter.set(handle, new ImplementationAdapter(this._documents, provider));
this._proxy.$registerImplementationSupport(handle, selector);
return this._createDisposable(handle);
}
$provideTypeDefinition(handle: number, resource: URI, position: IPosition): TPromise<modes.Definition> {
return this._withAdapter(handle, ImplementationAdapter, adapter => adapter.provideTypeDefinition(resource, position));
}
// --- extra info
registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider): vscode.Disposable {
......
......@@ -102,6 +102,15 @@ export class MainThreadLanguageFeatures extends MainThreadLanguageFeaturesShape
return undefined;
}
$registerImplementationSupport(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
this._registrations[handle] = modes.TypeDefinitionProviderRegistry.register(selector, <modes.TypeDefinitionProvider>{
provideTypeDefinition: (model, position, token): Thenable<modes.Definition> => {
return wireCancellationToken(token, this._proxy.$provideTypeDefinition(handle, model.uri, position));
}
});
return undefined;
}
// --- extra info
$registerHoverProvider(handle: number, selector: vscode.DocumentSelector): TPromise<any> {
......
......@@ -27,7 +27,7 @@ import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
import { getDocumentSymbols } from 'vs/editor/contrib/quickOpen/common/quickOpen';
import { DocumentSymbolProviderRegistry, DocumentHighlightKind } from 'vs/editor/common/modes';
import { getCodeLensData } from 'vs/editor/contrib/codelens/common/codelens';
import { getDeclarationsAtPosition } from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration';
import { getDeclarationsAtPosition, getTypeDefinitionAtPosition } from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration';
import { getHover } from 'vs/editor/contrib/hover/common/hover';
import { getOccurrencesAtPosition } from 'vs/editor/contrib/wordHighlighter/common/wordHighlighter';
import { provideReferences } from 'vs/editor/contrib/referenceSearch/common/referenceSearch';
......@@ -351,6 +351,26 @@ suite('ExtHostLanguageFeatures', function () {
});
});
// --- type definition
test('TypeDefinition, data conversion', function () {
disposables.push(extHost.registerTypeDefinitionProvider(defaultSelector, <vscode.TypeDefinitionProvider>{
provideTypeDefinition(): any {
return [new types.Location(model.uri, new types.Range(1, 2, 3, 4))];
}
}));
return threadService.sync().then(() => {
return getTypeDefinitionAtPosition(model, new EditorPosition(1, 1)).then(value => {
assert.equal(value.length, 1);
let [entry] = value;
assert.deepEqual(entry.range, { startLineNumber: 2, startColumn: 3, endLineNumber: 4, endColumn: 5 });
assert.equal(entry.uri.toString(), model.uri.toString());
});
});
});
// --- extra info
test('HoverProvider, word range at pos', function () {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册