Support DefinitionLink for definition provider

This commit is contained in:
Qiming Zhao 2021-07-23 00:04:28 +08:00
parent 225bef61f7
commit c556e99cf1
2 changed files with 42 additions and 5 deletions

View file

@ -3,10 +3,10 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { TextDocument } from 'coc.nvim'
import { DefinitionProvider, ImplementationProvider, TypeDefinitionProvider } from 'coc.nvim'
import { CancellationToken, Definition, Location, Position } from 'vscode-languageserver-protocol'
import { DefinitionProvider, CancellationToken, Definition, Location, Position, DefinitionLink, ImplementationProvider, TypeDefinitionProvider } from 'coc.nvim'
import * as Proto from '../protocol'
import { ITypeScriptServiceClient } from '../typescriptService'
import API from '../utils/api'
import * as typeConverters from '../utils/typeConverters'
export default class TypeScriptDefinitionProvider implements DefinitionProvider, TypeDefinitionProvider, ImplementationProvider {
@ -41,12 +41,44 @@ export default class TypeScriptDefinitionProvider implements DefinitionProvider,
}
}
public provideDefinition(
public async provideDefinition(
document: TextDocument,
position: Position,
token: CancellationToken
): Promise<Definition | undefined> {
return this.getSymbolLocations('definition', document, position, token)
): Promise<Definition | DefinitionLink[] | undefined> {
if (this.client.apiVersion.gte(API.v270)) {
const filepath = this.client.toOpenedFilePath(document.uri)
if (!filepath) {
return undefined
}
const args = typeConverters.Position.toFileLocationRequestArgs(filepath, position)
const response = await this.client.execute('definitionAndBoundSpan', args, token)
if (response.type !== 'response' || !response.body) {
return undefined
}
const span = response.body.textSpan ? typeConverters.Range.fromTextSpan(response.body.textSpan) : undefined
return response.body.definitions
.map((location): DefinitionLink => {
const target = typeConverters.Location.fromTextSpan(this.client.toResource(location.file), location)
if (location.contextStart && location.contextEnd) {
return {
originSelectionRange: span,
targetRange: typeConverters.Range.fromLocations(location.contextStart, location.contextEnd),
targetUri: target.uri,
targetSelectionRange: target.range,
}
}
return {
originSelectionRange: span,
targetRange: target.range,
targetUri: target.uri,
targetSelectionRange: target.range,
}
})
}
return await this.getSymbolLocations('definition', document, position, token)
}
public provideTypeDefinition(

View file

@ -23,6 +23,11 @@ export namespace Range {
}
}
}
export const fromLocations = (start: Proto.Location, end: Proto.Location): language.Range =>
language.Range.create(
Math.max(0, start.line - 1), Math.max(start.offset - 1, 0),
Math.max(0, end.line - 1), Math.max(0, end.offset - 1))
export const toFormattingRequestArgs = (file: string, range: language.Range): Proto.FormatRequestArgs => ({
file,