Skip to content

Commit

Permalink
Finalize definition link (#54424)
Browse files Browse the repository at this point in the history
Finalize the definition link api

- Gives fields more explicit names (target and origin)
- Moves api to vscode.d.ts
- Makes other definition providers (such as type definition provider and implementation provider) also return definition links

Fixes #54101
  • Loading branch information
mjbvz authored Jul 18, 2018
1 parent 80a4724 commit 44cd521
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 107 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,7 @@ export default class TypeScriptDefinitionProvider extends DefinitionProviderBase
super(client);
}

public async provideDefinition() {
// Implemented by provideDefinition2
return undefined;
}

public async provideDefinition2(
public async provideDefinition(
document: vscode.TextDocument,
position: vscode.Position,
token: vscode.CancellationToken | boolean
Expand All @@ -44,10 +39,11 @@ export default class TypeScriptDefinitionProvider extends DefinitionProviderBase
const span = response.body.textSpan ? typeConverters.Range.fromTextSpan(response.body.textSpan) : undefined;
return locations
.map(location => {
const loc = typeConverters.Location.fromTextSpan(this.client.toResource(location.file), location);
return {
origin: span,
...loc,
const target = typeConverters.Location.fromTextSpan(this.client.toResource(location.file), location);
return <vscode.DefinitionLink>{
originSelectionRange: span,
targetRange: target.range,
targetUri: target.uri,
};
});
} catch {
Expand Down
4 changes: 2 additions & 2 deletions src/vs/editor/common/modes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ export interface ImplementationProvider {
/**
* Provide the implementation of the symbol at the given position and document.
*/
provideImplementation(model: model.ITextModel, position: Position, token: CancellationToken): Definition | Thenable<Definition>;
provideImplementation(model: model.ITextModel, position: Position, token: CancellationToken): DefinitionLink | Thenable<DefinitionLink>;
}

/**
Expand All @@ -576,7 +576,7 @@ export interface TypeDefinitionProvider {
/**
* Provide the type definition of the symbol at the given position and document.
*/
provideTypeDefinition(model: model.ITextModel, position: Position, token: CancellationToken): Definition | Thenable<Definition>;
provideTypeDefinition(model: model.ITextModel, position: Position, token: CancellationToken): DefinitionLink | Thenable<DefinitionLink>;
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/vs/monaco.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4933,7 +4933,7 @@ declare namespace monaco.languages {
/**
* Provide the implementation of the symbol at the given position and document.
*/
provideImplementation(model: editor.ITextModel, position: Position, token: CancellationToken): Definition | Thenable<Definition>;
provideImplementation(model: editor.ITextModel, position: Position, token: CancellationToken): DefinitionLink | Thenable<DefinitionLink>;
}

/**
Expand All @@ -4944,7 +4944,7 @@ declare namespace monaco.languages {
/**
* Provide the type definition of the symbol at the given position and document.
*/
provideTypeDefinition(model: editor.ITextModel, position: Position, token: CancellationToken): Definition | Thenable<Definition>;
provideTypeDefinition(model: editor.ITextModel, position: Position, token: CancellationToken): DefinitionLink | Thenable<DefinitionLink>;
}

/**
Expand Down
41 changes: 38 additions & 3 deletions src/vs/vscode.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2156,6 +2156,41 @@ declare module 'vscode' {
resolveCodeLens?(codeLens: CodeLens, token: CancellationToken): ProviderResult<CodeLens>;
}

/**
* Information about where a symbol is defined.
*
* Provides additional metadata over normal [location](#Location) definitions, including the range of
* the defining symbol
*/
export interface DefinitionLink {
/**
* Span of the symbol being defined in the source file.
*
* Used as the underlined span for mouse definition hover. Defaults to the word range at
* the definition position.
*/
originSelectionRange?: Range;

/**
* The resource identifier of the definition.
*/
targetUri: Uri;

/**
* The full range of the definition.
*
* For a class definition for example, this would be the entire body of the class definition.
*/
targetRange: Range;

/**
* The span of the symbol definition.
*
* For a class definition, this would be the class name itself in the class definition.
*/
targetSelectionRange?: Range;
}

/**
* 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
Expand All @@ -2179,7 +2214,7 @@ declare module 'vscode' {
* @return A definition or a thenable that resolves to such. The lack of a result can be
* signaled by returning `undefined` or `null`.
*/
provideDefinition(document: TextDocument, position: Position, token: CancellationToken): ProviderResult<Definition>;
provideDefinition(document: TextDocument, position: Position, token: CancellationToken): ProviderResult<Definition | DefinitionLink[]>;
}

/**
Expand All @@ -2197,7 +2232,7 @@ declare module 'vscode' {
* @return A definition or a thenable that resolves to such. The lack of a result can be
* signaled by returning `undefined` or `null`.
*/
provideImplementation(document: TextDocument, position: Position, token: CancellationToken): ProviderResult<Definition>;
provideImplementation(document: TextDocument, position: Position, token: CancellationToken): ProviderResult<Definition | DefinitionLink[]>;
}

/**
Expand All @@ -2215,7 +2250,7 @@ declare module 'vscode' {
* @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>;
provideTypeDefinition(document: TextDocument, position: Position, token: CancellationToken): ProviderResult<Definition | DefinitionLink[]>;
}

/**
Expand Down
43 changes: 0 additions & 43 deletions src/vs/vscode.proposed.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1054,47 +1054,4 @@ declare module 'vscode' {
export const onDidRenameFile: Event<FileRenameEvent>;
}
//#endregion

//#region Matt: Deinition range

/**
* Information about where a symbol is defined.
*
* Provides additional metadata over normal [location](#Location) definitions, including the range of
* the defining symbol
*/
export interface DefinitionLink {
/**
* Span of the symbol being defined in the source file.
*
* Used as the underlined span for mouse definition hover. Defaults to the word range at
* the definition position.
*/
origin?: Range;

/**
* The resource identifier of the definition.
*/
uri: Uri;

/**
* The full range of the definition.
*
* For a class definition for example, this would be the entire body of the class definition.
*/
range: Range;

/**
* The span of the symbol definition.
*
* For a class definition, this would be the class name itself in the class definition.
*/
selectionRange?: Range;
}

export interface DefinitionProvider {
provideDefinition2?(document: TextDocument, position: Position, token: CancellationToken): ProviderResult<Definition | DefinitionLink[]>;
}

//#endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,15 @@ export class MainThreadLanguageFeatures implements MainThreadLanguageFeaturesSha
$registerImplementationSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
this._registrations[handle] = modes.ImplementationProviderRegistry.register(typeConverters.LanguageSelector.from(selector), <modes.ImplementationProvider>{
provideImplementation: (model, position, token): Thenable<modes.Definition> => {
return wireCancellationToken(token, this._proxy.$provideImplementation(handle, model.uri, position)).then(MainThreadLanguageFeatures._reviveLocationDto);
return wireCancellationToken(token, this._proxy.$provideImplementation(handle, model.uri, position)).then(MainThreadLanguageFeatures._reviveDefinitionLinkDto);
}
});
}

$registerTypeDefinitionSupport(handle: number, selector: ISerializedDocumentFilter[]): void {
this._registrations[handle] = modes.TypeDefinitionProviderRegistry.register(typeConverters.LanguageSelector.from(selector), <modes.TypeDefinitionProvider>{
provideTypeDefinition: (model, position, token): Thenable<modes.Definition> => {
return wireCancellationToken(token, this._proxy.$provideTypeDefinition(handle, model.uri, position)).then(MainThreadLanguageFeatures._reviveLocationDto);
return wireCancellationToken(token, this._proxy.$provideTypeDefinition(handle, model.uri, position)).then(MainThreadLanguageFeatures._reviveDefinitionLinkDto);
}
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/vs/workbench/api/node/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -812,8 +812,8 @@ export interface ExtHostLanguageFeaturesShape {
$provideCodeLenses(handle: number, resource: UriComponents): TPromise<modes.ICodeLensSymbol[]>;
$resolveCodeLens(handle: number, resource: UriComponents, symbol: modes.ICodeLensSymbol): TPromise<modes.ICodeLensSymbol>;
$provideDefinition(handle: number, resource: UriComponents, position: IPosition): TPromise<DefinitionLinkDto[]>;
$provideImplementation(handle: number, resource: UriComponents, position: IPosition): TPromise<LocationDto | LocationDto[]>;
$provideTypeDefinition(handle: number, resource: UriComponents, position: IPosition): TPromise<LocationDto | LocationDto[]>;
$provideImplementation(handle: number, resource: UriComponents, position: IPosition): TPromise<DefinitionLinkDto[]>;
$provideTypeDefinition(handle: number, resource: UriComponents, position: IPosition): TPromise<DefinitionLinkDto[]>;
$provideHover(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.Hover>;
$provideDocumentHighlights(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.DocumentHighlight[]>;
$provideReferences(handle: number, resource: UriComponents, position: IPosition, context: modes.ReferenceContext): TPromise<LocationDto[]>;
Expand Down
59 changes: 16 additions & 43 deletions src/vs/workbench/api/node/extHostLanguageFeatures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,15 @@ class CodeLensAdapter {
}
}

function convertToDefinitionLinks(value: vscode.Definition): modes.DefinitionLink[] {
if (Array.isArray(value)) {
return (value as (vscode.DefinitionLink | vscode.Location)[]).map(typeConvert.DefinitionLink.from);
} else if (value) {
return [typeConvert.DefinitionLink.from(value)];
}
return undefined;
}

class DefinitionAdapter {

constructor(
Expand All @@ -153,29 +162,7 @@ class DefinitionAdapter {
provideDefinition(resource: URI, position: IPosition): TPromise<modes.DefinitionLink[]> {
let doc = this._documents.getDocumentData(resource).document;
let pos = typeConvert.Position.to(position);

return asWinJsPromise(token => this._provider.provideDefinition2 ? this._provider.provideDefinition2(doc, pos, token) : this._provider.provideDefinition(doc, pos, token)).then((value): modes.DefinitionLink[] => {
if (Array.isArray(value)) {
return (value as (vscode.DefinitionLink | vscode.Location)[]).map(x => DefinitionAdapter.convertDefinitionLink(x));
} else if (value) {
return [DefinitionAdapter.convertDefinitionLink(value)];
}
return undefined;
});
}

private static convertDefinitionLink(value: vscode.Location | vscode.DefinitionLink): modes.DefinitionLink {
const definitionLink = <vscode.DefinitionLink>value;
return {
origin: definitionLink.origin
? typeConvert.Range.from(definitionLink.origin)
: undefined,
uri: value.uri,
range: typeConvert.Range.from(value.range),
selectionRange: definitionLink.selectionRange
? typeConvert.Range.from(definitionLink.selectionRange)
: undefined,
};
return asWinJsPromise(token => this._provider.provideDefinition(doc, pos, token)).then(convertToDefinitionLinks);
}
}

Expand All @@ -186,17 +173,10 @@ class ImplementationAdapter {
private readonly _provider: vscode.ImplementationProvider
) { }

provideImplementation(resource: URI, position: IPosition): TPromise<modes.Definition> {
provideImplementation(resource: URI, position: IPosition): TPromise<modes.DefinitionLink[]> {
let doc = this._documents.getDocumentData(resource).document;
let pos = typeConvert.Position.to(position);
return asWinJsPromise(token => this._provider.provideImplementation(doc, pos, token)).then(value => {
if (Array.isArray(value)) {
return value.map(typeConvert.location.from);
} else if (value) {
return typeConvert.location.from(value);
}
return undefined;
});
return asWinJsPromise(token => this._provider.provideImplementation(doc, pos, token)).then(convertToDefinitionLinks);
}
}

Expand All @@ -207,17 +187,10 @@ class TypeDefinitionAdapter {
private readonly _provider: vscode.TypeDefinitionProvider
) { }

provideTypeDefinition(resource: URI, position: IPosition): TPromise<modes.Definition> {
provideTypeDefinition(resource: URI, position: IPosition): TPromise<modes.DefinitionLink[]> {
const doc = this._documents.getDocumentData(resource).document;
const pos = typeConvert.Position.to(position);
return asWinJsPromise(token => this._provider.provideTypeDefinition(doc, pos, token)).then(value => {
if (Array.isArray(value)) {
return value.map(typeConvert.location.from);
} else if (value) {
return typeConvert.location.from(value);
}
return undefined;
});
return asWinJsPromise(token => this._provider.provideTypeDefinition(doc, pos, token)).then(convertToDefinitionLinks);
}
}

Expand Down Expand Up @@ -999,7 +972,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}

$provideImplementation(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.Definition> {
$provideImplementation(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.DefinitionLink[]> {
return this._withAdapter(handle, ImplementationAdapter, adapter => adapter.provideImplementation(URI.revive(resource), position));
}

Expand All @@ -1009,7 +982,7 @@ export class ExtHostLanguageFeatures implements ExtHostLanguageFeaturesShape {
return this._createDisposable(handle);
}

$provideTypeDefinition(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.Definition> {
$provideTypeDefinition(handle: number, resource: UriComponents, position: IPosition): TPromise<modes.DefinitionLink[]> {
return this._withAdapter(handle, TypeDefinitionAdapter, adapter => adapter.provideTypeDefinition(URI.revive(resource), position));
}

Expand Down
17 changes: 17 additions & 0 deletions src/vs/workbench/api/node/extHostTypeConverters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,23 @@ export const location = {
}
};

export namespace DefinitionLink {
export function from(value: vscode.Location | vscode.DefinitionLink): modes.DefinitionLink {
const definitionLink = <vscode.DefinitionLink>value;
const location = <vscode.Location>value;
return {
origin: definitionLink.originSelectionRange
? Range.from(definitionLink.originSelectionRange)
: undefined,
uri: definitionLink.targetUri ? definitionLink.targetUri : location.uri,
range: Range.from(definitionLink.targetRange ? definitionLink.targetRange : location.range),
selectionRange: definitionLink.targetSelectionRange
? Range.from(definitionLink.targetSelectionRange)
: undefined,
};
}
}

export namespace Hover {
export function from(hover: vscode.Hover): modes.Hover {
return <modes.Hover>{
Expand Down

0 comments on commit 44cd521

Please sign in to comment.