Add Type Definition Provider API (#19699)

* Add Type Definition Provider API

Adds a new API to support type definition providers and adds an initial type definition provider for TypeScript

* Fix comment

* Addressing comments

* Fixer menu option ordering

* Added simple test
This commit is contained in:
Matt Bierner
2017-02-02 14:01:23 -08:00
committed by GitHub
parent 7907093430
commit a87586c7c3
18 changed files with 285 additions and 46 deletions

View File

@@ -14,7 +14,12 @@ export default class TypeScriptDefinitionProviderBase {
constructor(
private client: ITypescriptServiceClient) { }
protected getSymbolLocations(definitionType: 'definition' | 'implementation', document: TextDocument, position: Position, token: CancellationToken | boolean): Promise<Location[] | null> {
protected getSymbolLocations(
definitionType: 'definition' | 'implementation' | 'typeDefinition',
document: TextDocument,
position: Position,
token: CancellationToken | boolean
): Promise<Location[] | null> {
const filepath = this.client.normalizePath(document.uri);
if (!filepath) {
return Promise.resolve(null);

View File

@@ -0,0 +1,21 @@
/*---------------------------------------------------------------------------------------------
* 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('typeDefinition', document, position, token);
}
}

View File

@@ -26,6 +26,7 @@ import { ITypescriptServiceClientHost } from './typescriptService';
import HoverProvider from './features/hoverProvider';
import DefinitionProvider from './features/definitionProvider';
import ImplementationProvider from './features/ImplementationProvider';
import TypeDefintionProvider from './features/typeDefinitionProvider';
import DocumentHighlightProvider from './features/documentHighlightProvider';
import ReferenceProvider from './features/referenceProvider';
import DocumentSymbolProvider from './features/documentSymbolProvider';
@@ -155,6 +156,7 @@ class LanguageProvider {
let hoverProvider = new HoverProvider(client);
let definitionProvider = new DefinitionProvider(client);
let implementationProvider = new ImplementationProvider(client);
const typeDefinitionProvider = new TypeDefintionProvider(client);
let documentHighlightProvider = new DocumentHighlightProvider(client);
let referenceProvider = new ReferenceProvider(client);
let documentSymbolProvider = new DocumentSymbolProvider(client);
@@ -181,6 +183,9 @@ class LanguageProvider {
// TODO: TS 2.1.5 returns incorrect results for implementation locations.
languages.registerImplementationProvider(selector, implementationProvider);
}
if (client.apiVersion.has213Features()) {
languages.registerTypeDefinitionProvider(selector, typeDefinitionProvider);
}
languages.registerDocumentHighlightProvider(selector, documentHighlightProvider);
languages.registerReferenceProvider(selector, referenceProvider);
languages.registerDocumentSymbolProvider(selector, documentSymbolProvider);

View File

@@ -88,6 +88,7 @@ export interface ITypescriptServiceClient {
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: 'typeDefinition', args: Proto.FileLocationRequestArgs, token?: CancellationToken): Promise<Proto.TypeDefinitionResponse>;
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>;

View File

@@ -275,12 +275,19 @@ export function registerDefinitionProvider(languageId: string, provider: modes.D
}
/**
* Register a type implementation provider (used by e.g. go to implementation).
* Register a implementation provider (used by e.g. go to implementation).
*/
export function registerImplementationProvider(languageId: string, provider: modes.ImplementationProvider): IDisposable {
return modes.ImplementationProviderRegistry.register(languageId, provider);
}
/**
* Register a type definition provider (used by e.g. go to type definition).
*/
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).
*/
@@ -682,6 +689,7 @@ export function createMonacoLanguagesAPI(): typeof monaco.languages {
registerDocumentHighlightProvider: registerDocumentHighlightProvider,
registerDefinitionProvider: registerDefinitionProvider,
registerImplementationProvider: registerImplementationProvider,
registerTypeDefinitionProvider: registerTypeDefinitionProvider,
registerCodeLensProvider: registerCodeLensProvider,
registerCodeActionProvider: registerCodeActionProvider,
registerDocumentFormattingEditProvider: registerDocumentFormattingEditProvider,

View File

@@ -3146,6 +3146,10 @@ export namespace ModeContextKeys {
* @internal
*/
export const hasImplementationProvider = new RawContextKey<boolean>('editorHasImplementationProvider', undefined);
/**
* @internal
*/
export const hasTypeDefinitionProvider = new RawContextKey<boolean>('editorHasTypeDefinitionProvider', undefined);
/**
* @internal
*/

View File

@@ -429,7 +429,7 @@ export interface DefinitionProvider {
}
/**
* The type definition provider interface defines the contract between extensions and
* The implementation provider interface defines the contract between extensions and
* the go to implementation feature.
*/
export interface ImplementationProvider {
@@ -439,6 +439,17 @@ export interface ImplementationProvider {
provideImplementation(model: editorCommon.IReadOnlyModel, position: Position, token: CancellationToken): Definition | Thenable<Definition>;
}
/**
* The type definition provider interface defines the contract between extensions and
* the go to type definition feature.
*/
export interface TypeDefinitionProvider {
/**
* Provide the type definition of the symbol at the given position and document.
*/
provideTypeDefinition(model: editorCommon.IReadOnlyModel, position: Position, token: CancellationToken): Definition | Thenable<Definition>;
}
/**
* A symbol kind.
*/
@@ -751,6 +762,11 @@ export const DefinitionProviderRegistry = new LanguageFeatureRegistry<Definition
*/
export const ImplementationProviderRegistry = new LanguageFeatureRegistry<ImplementationProvider>();
/**
* @internal
*/
export const TypeDefinitionProviderRegistry = new LanguageFeatureRegistry<TypeDefinitionProvider>();
/**
* @internal
*/

View File

@@ -21,6 +21,7 @@ export class EditorModeContext {
private _hasCodeLensProvider: IContextKey<boolean>;
private _hasDefinitionProvider: IContextKey<boolean>;
private _hasImplementationProvider: IContextKey<boolean>;
private _hasTypeDefinitionProvider: IContextKey<boolean>;
private _hasHoverProvider: IContextKey<boolean>;
private _hasDocumentHighlightProvider: IContextKey<boolean>;
private _hasDocumentSymbolProvider: IContextKey<boolean>;
@@ -43,6 +44,7 @@ export class EditorModeContext {
this._hasCodeLensProvider = ModeContextKeys.hasCodeLensProvider.bindTo(contextKeyService);
this._hasDefinitionProvider = ModeContextKeys.hasDefinitionProvider.bindTo(contextKeyService);
this._hasImplementationProvider = ModeContextKeys.hasImplementationProvider.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);
@@ -63,6 +65,7 @@ export class EditorModeContext {
modes.CodeLensProviderRegistry.onDidChange(this._update, this, this._disposables);
modes.DefinitionProviderRegistry.onDidChange(this._update, this, this._disposables);
modes.ImplementationProviderRegistry.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);
@@ -86,6 +89,7 @@ export class EditorModeContext {
this._hasCodeLensProvider.reset();
this._hasDefinitionProvider.reset();
this._hasImplementationProvider.reset();
this._hasTypeDefinitionProvider.reset();
this._hasHoverProvider.reset();
this._hasDocumentHighlightProvider.reset();
this._hasDocumentSymbolProvider.reset();
@@ -109,6 +113,7 @@ export class EditorModeContext {
this._hasCodeLensProvider.set(modes.CodeLensProviderRegistry.has(model));
this._hasDefinitionProvider.set(modes.DefinitionProviderRegistry.has(model));
this._hasImplementationProvider.set(modes.ImplementationProviderRegistry.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));

View File

@@ -26,7 +26,7 @@ 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, getImplementationAtPosition } from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration';
import { getDefinitionsAtPosition, getImplementationsAtPosition, getTypeDefinitionsAtPosition } 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';
@@ -106,7 +106,7 @@ export class DefinitionAction extends EditorAction {
}
protected getDeclarationsAtPosition(model: editorCommon.IModel, position: corePosition.Position): TPromise<Location[]> {
return getDeclarationsAtPosition(model, position);
return getDefinitionsAtPosition(model, position);
}
private _onResult(editorService: IEditorService, editor: editorCommon.ICommonCodeEditor, model: ReferencesModel) {
@@ -255,7 +255,7 @@ export class GoToImplementationAction extends DefinitionAction {
}
protected getDeclarationsAtPosition(model: editorCommon.IModel, position: corePosition.Position): TPromise<Location[]> {
return getImplementationAtPosition(model, position);
return getImplementationsAtPosition(model, position);
}
}
@@ -275,19 +275,70 @@ export class PeekImplementationAction extends DefinitionAction {
kbOpts: {
kbExpr: EditorContextKeys.TextFocus,
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.F12
},
menuOpts: {
group: 'navigation',
order: 1.3
}
});
}
protected getDeclarationsAtPosition(model: editorCommon.IModel, position: corePosition.Position): TPromise<Location[]> {
return getImplementationAtPosition(model, position);
return getImplementationsAtPosition(model, position);
}
}
@editorAction
export class GoToTypeDefintionAction extends DefinitionAction {
public static ID = 'editor.action.goToTypeDefinition';
constructor() {
super(new DefinitionActionConfig(), {
id: GoToTypeDefintionAction.ID,
label: nls.localize('actions.goToTypeDefinition.label', "Go to Type Definition"),
alias: 'Go to Type Definition',
precondition: ContextKeyExpr.and(
ModeContextKeys.hasTypeDefinitionProvider,
ModeContextKeys.isInEmbeddedEditor.toNegated()),
kbOpts: {
kbExpr: EditorContextKeys.TextFocus,
primary: 0
},
menuOpts: {
group: 'navigation',
order: 1.4
}
});
}
protected getDeclarationsAtPosition(model: editorCommon.IModel, position: corePosition.Position): TPromise<Location[]> {
return getTypeDefinitionsAtPosition(model, position);
}
}
@editorAction
export class PeekTypeDefinitionAction extends DefinitionAction {
public static ID = 'editor.action.peekTypeDefinition';
constructor() {
super(new DefinitionActionConfig(false, true, false), {
id: PeekTypeDefinitionAction.ID,
label: nls.localize('actions.peekTypeDefinition.label', "Peek Type Definition"),
alias: 'Peek Type Definition',
precondition: ContextKeyExpr.and(
ModeContextKeys.hasTypeDefinitionProvider,
ModeContextKeys.isInEmbeddedEditor.toNegated()),
kbOpts: {
kbExpr: EditorContextKeys.TextFocus,
primary: 0
}
});
}
protected getDeclarationsAtPosition(model: editorCommon.IModel, position: corePosition.Position): TPromise<Location[]> {
return getTypeDefinitionsAtPosition(model, position);
}
}
// --- Editor Contribution to goto definition using the mouse and a modifier key
@editorContribution
@@ -541,7 +592,7 @@ class GotoDefinitionWithMouseEditorContribution implements editorCommon.IEditorC
return TPromise.as(null);
}
return getDeclarationsAtPosition(this.editor.getModel(), target.position);
return getDefinitionsAtPosition(this.editor.getModel(), target.position);
}
private gotoDefinition(target: IMouseTarget, sideBySide: boolean): TPromise<any> {

View File

@@ -9,7 +9,9 @@ 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, ImplementationProviderRegistry, Location } from 'vs/editor/common/modes';
import LanguageFeatureRegistry from 'vs/editor/common/modes/languageFeatureRegistry';
import { DefinitionProviderRegistry, ImplementationProviderRegistry, TypeDefinitionProviderRegistry, Location } 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';
@@ -27,14 +29,18 @@ function outputResults(promises: TPromise<Location[]>[]) {
});
}
export function getDeclarationsAtPosition(model: IReadOnlyModel, position: Position): TPromise<Location[]> {
const provider = DefinitionProviderRegistry.ordered(model);
function getDefinitions<T>(
model: IReadOnlyModel,
position: Position,
registry: LanguageFeatureRegistry<T>,
provide: (provider: T, model: IReadOnlyModel, position: Position, token: CancellationToken) => Location | Location[] | Thenable<Location | Location[]>
): TPromise<Location[]> {
const provider = registry.ordered(model);
// get results
const promises = provider.map((provider, idx) => {
return asWinJsPromise((token) => {
return provider.provideDefinition(model, position, token);
return provide(provider, model, position, token);
}).then(result => {
return result;
}, err => {
@@ -44,22 +50,25 @@ export function getDeclarationsAtPosition(model: IReadOnlyModel, position: Posit
return outputResults(promises);
}
export function getImplementationAtPosition(model: IReadOnlyModel, position: Position): TPromise<Location[]> {
const provider = ImplementationProviderRegistry.ordered(model);
// get results
const promises = provider.map((provider, idx) => {
return asWinJsPromise((token) => {
return provider.provideImplementation(model, position, token);
}).then(result => {
return result;
}, err => {
onUnexpectedExternalError(err);
});
export function getDefinitionsAtPosition(model: IReadOnlyModel, position: Position): TPromise<Location[]> {
return getDefinitions(model, position, DefinitionProviderRegistry, (provider, model, position, token) => {
return provider.provideDefinition(model, position, token);
});
return outputResults(promises);
}
CommonEditorRegistry.registerDefaultLanguageCommand('_executeDefinitionProvider', getDeclarationsAtPosition);
CommonEditorRegistry.registerDefaultLanguageCommand('_executeImplementationProvider', getImplementationAtPosition);
export function getImplementationsAtPosition(model: IReadOnlyModel, position: Position): TPromise<Location[]> {
return getDefinitions(model, position, ImplementationProviderRegistry, (provider, model, position, token) => {
return provider.provideImplementation(model, position, token);
});
}
export function getTypeDefinitionsAtPosition(model: IReadOnlyModel, position: Position): TPromise<Location[]> {
return getDefinitions(model, position, TypeDefinitionProviderRegistry, (provider, model, position, token) => {
return provider.provideTypeDefinition(model, position, token);
});
}
CommonEditorRegistry.registerDefaultLanguageCommand('_executeDefinitionProvider', getDefinitionsAtPosition);
CommonEditorRegistry.registerDefaultLanguageCommand('_executeImplementationProvider', getImplementationsAtPosition);
CommonEditorRegistry.registerDefaultLanguageCommand('_executeTypeDefinitionProvider', getTypeDefinitionsAtPosition);

View File

@@ -73,7 +73,7 @@ export class ReferenceAction extends EditorAction {
},
menuOpts: {
group: 'navigation',
order: 1.3
order: 1.5
}
});
}

20
src/vs/monaco.d.ts vendored
View File

@@ -3953,10 +3953,15 @@ declare module monaco.languages {
export function registerDefinitionProvider(languageId: string, provider: DefinitionProvider): IDisposable;
/**
* Register a type implementation provider (used by e.g. go to implementation).
* Register a implementation provider (used by e.g. go to implementation).
*/
export function registerImplementationProvider(languageId: string, provider: ImplementationProvider): IDisposable;
/**
* Register a type definition provider (used by e.g. go to type definition).
*/
export function registerTypeDefinitionProvider(languageId: string, provider: TypeDefinitionProvider): IDisposable;
/**
* Register a code lens provider (used by e.g. inline code lenses).
*/
@@ -4570,7 +4575,7 @@ declare module monaco.languages {
}
/**
* The type definition provider interface defines the contract between extensions and
* The implementation provider interface defines the contract between extensions and
* the go to implementation feature.
*/
export interface ImplementationProvider {
@@ -4580,6 +4585,17 @@ declare module monaco.languages {
provideImplementation(model: editor.IReadOnlyModel, position: Position, token: CancellationToken): Definition | Thenable<Definition>;
}
/**
* The type definition provider interface defines the contract between extensions and
* the go to type definition feature.
*/
export interface TypeDefinitionProvider {
/**
* Provide the type definition of the symbol at the given position and document.
*/
provideTypeDefinition(model: editor.IReadOnlyModel, position: Position, token: CancellationToken): Definition | Thenable<Definition>;
}
/**
* A symbol kind.
*/

33
src/vs/vscode.d.ts vendored
View File

@@ -1650,7 +1650,7 @@ declare module 'vscode' {
}
/**
* The type implemenetation provider interface defines the contract between extensions and
* The implemenetation provider interface defines the contract between extensions and
* the go to implementation feature.
*/
export interface ImplementationProvider {
@@ -1667,6 +1667,24 @@ declare module 'vscode' {
provideImplementation(document: TextDocument, position: Position, token: CancellationToken): ProviderResult<Definition>;
}
/**
* The type definition provider defines the contract between extensions and
* the go to type definition feature.
*/
export interface TypeDefinitionProvider {
/**
* Provide the type definition 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
@@ -4173,6 +4191,19 @@ declare module 'vscode' {
*/
export function registerImplementationProvider(selector: DocumentSelector, provider: ImplementationProvider): Disposable;
/**
* Register a type definition provider.
*
* Multiple providers can be registered for a language. In that case providers are asked in
* parallel and the results are merged. A failing provider (rejected promise or exception) will
* not cause a failure of the whole operation.
*
* @param selector A selector that defines the documents this provider is applicable to.
* @param provider A type definition provider.
* @return A [disposable](#Disposable) that unregisters this provider when being disposed.
*/
export function registerTypeDefinitionProvider(selector: DocumentSelector, provider: TypeDefinitionProvider): Disposable;
/**
* Register a hover provider.
*

View File

@@ -215,6 +215,9 @@ export function createApiFactory(initData: IInitData, threadService: IThreadServ
registerImplementationProvider(selector: vscode.DocumentSelector, provider: vscode.ImplementationProvider): vscode.Disposable {
return languageFeatures.registerImplementationProvider(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);
},

View File

@@ -156,6 +156,7 @@ export abstract class MainThreadLanguageFeaturesShape {
$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(); }
$registerTypeDefinitionSupport(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(); }
@@ -361,6 +362,7 @@ export abstract class ExtHostLanguageFeaturesShape {
$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(); }
$provideImplementation(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(); }

View File

@@ -101,7 +101,6 @@ class CodeLensAdapter {
}
class DefinitionAdapter {
private _documents: ExtHostDocuments;
private _provider: vscode.DefinitionProvider;
@@ -125,7 +124,6 @@ class DefinitionAdapter {
}
class ImplementationAdapter {
private _documents: ExtHostDocuments;
private _provider: vscode.ImplementationProvider;
@@ -148,6 +146,30 @@ class ImplementationAdapter {
}
}
class TypeDefinitionAdapter {
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> {
const doc = this._documents.getDocumentData(resource).document;
const 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);
}
return undefined;
});
}
}
class HoverAdapter {
private _documents: ExtHostDocuments;
@@ -650,7 +672,7 @@ class LinkProviderAdapter {
type Adapter = OutlineAdapter | CodeLensAdapter | DefinitionAdapter | HoverAdapter
| DocumentHighlightAdapter | ReferenceAdapter | QuickFixAdapter | DocumentFormattingAdapter
| RangeFormattingAdapter | OnTypeFormattingAdapter | NavigateTypeAdapter | RenameAdapter
| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter;
| SuggestAdapter | SignatureHelpAdapter | LinkProviderAdapter | ImplementationAdapter | TypeDefinitionAdapter;
export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
@@ -760,6 +782,17 @@ export class ExtHostLanguageFeatures extends ExtHostLanguageFeaturesShape {
return this._withAdapter(handle, ImplementationAdapter, adapter => adapter.provideImplementation(resource, position));
}
registerTypeDefinitionProvider(selector: vscode.DocumentSelector, provider: vscode.TypeDefinitionProvider): vscode.Disposable {
const handle = this._nextHandle();
this._adapter.set(handle, new TypeDefinitionAdapter(this._documents, provider));
this._proxy.$registerTypeDefinitionSupport(handle, selector);
return this._createDisposable(handle);
}
$provideTypeDefinition(handle: number, resource: URI, position: IPosition): TPromise<modes.Definition> {
return this._withAdapter(handle, TypeDefinitionAdapter, adapter => adapter.provideTypeDefinition(resource, position));
}
// --- extra info
registerHoverProvider(selector: vscode.DocumentSelector, provider: vscode.HoverProvider): vscode.Disposable {

View File

@@ -111,6 +111,15 @@ export class MainThreadLanguageFeatures extends MainThreadLanguageFeaturesShape
return undefined;
}
$registerTypeDefinitionSupport(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> {

View File

@@ -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, getImplementationAtPosition } from 'vs/editor/contrib/goToDeclaration/common/goToDeclaration';
import { getDefinitionsAtPosition, getImplementationsAtPosition, getTypeDefinitionsAtPosition } 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';
@@ -275,7 +275,7 @@ suite('ExtHostLanguageFeatures', function () {
return threadService.sync().then(() => {
return getDeclarationsAtPosition(model, new EditorPosition(1, 1)).then(value => {
return getDefinitionsAtPosition(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 });
@@ -299,7 +299,7 @@ suite('ExtHostLanguageFeatures', function () {
return threadService.sync().then(() => {
return getDeclarationsAtPosition(model, new EditorPosition(1, 1)).then(value => {
return getDefinitionsAtPosition(model, new EditorPosition(1, 1)).then(value => {
assert.equal(value.length, 2);
});
});
@@ -321,7 +321,7 @@ suite('ExtHostLanguageFeatures', function () {
return threadService.sync().then(() => {
return getDeclarationsAtPosition(model, new EditorPosition(1, 1)).then(value => {
return getDefinitionsAtPosition(model, new EditorPosition(1, 1)).then(value => {
assert.equal(value.length, 2);
// let [first, second] = value;
@@ -346,13 +346,13 @@ suite('ExtHostLanguageFeatures', function () {
return threadService.sync().then(() => {
return getDeclarationsAtPosition(model, new EditorPosition(1, 1)).then(value => {
return getDefinitionsAtPosition(model, new EditorPosition(1, 1)).then(value => {
assert.equal(value.length, 1);
});
});
});
// --- type implementation
// --- implementation
test('Implementation, data conversion', function () {
@@ -363,7 +363,27 @@ suite('ExtHostLanguageFeatures', function () {
}));
return threadService.sync().then(() => {
return getImplementationAtPosition(model, new EditorPosition(1, 1)).then(value => {
return getImplementationsAtPosition(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());
});
});
});
// --- type definition
test('Type Definition, 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 getTypeDefinitionsAtPosition(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 });