diff --git a/Readme.md b/Readme.md index 40ca472..a29b158 100644 --- a/Readme.md +++ b/Readme.md @@ -72,6 +72,7 @@ Almost the same as VSCode. - `tsserver.restart` - `tsserver.organizeImports` - `tsserver.watchBuild` + - `tsserver.findAllFileReferences` - Code completion support. - Go to definition (more info in [microsoft/TypeScript#37777](https://github.com/microsoft/TypeScript/issues/37777)) - Code validation. diff --git a/package.json b/package.json index 56dd345..0ea3577 100644 --- a/package.json +++ b/package.json @@ -89,6 +89,11 @@ "category": "TSServer", "command": "tsserver.restart" }, + { + "title": "Find File References", + "category": "TSServer", + "command": "tsserver.findAllFileReferences" + }, { "title": "Run `tsc --watch` for current project by use vim's job feature.", "category": "TSServer", diff --git a/src/index.ts b/src/index.ts index f3d4ea0..cdd0936 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ import { commands, ExtensionContext, services, workspace } from 'coc.nvim' import TsserverService from './server' -import { AutoFixCommand, Command, ConfigurePluginCommand, OpenTsServerLogCommand, ReloadProjectsCommand, TypeScriptGoToProjectConfigCommand } from './server/commands' +import { AutoFixCommand, Command, ConfigurePluginCommand, FileReferencesCommand, OpenTsServerLogCommand, ReloadProjectsCommand, TypeScriptGoToProjectConfigCommand } from './server/commands' import { OrganizeImportsCommand } from './server/organizeImports' import { PluginManager } from './utils/plugins' @@ -21,6 +21,7 @@ export async function activate(context: ExtensionContext): Promise { registCommand(new ConfigurePluginCommand(pluginManager)) registCommand(new AutoFixCommand(service)) registCommand(new ReloadProjectsCommand(service)) + registCommand(new FileReferencesCommand(service)) registCommand(new OpenTsServerLogCommand(service)) registCommand(new TypeScriptGoToProjectConfigCommand(service)) registCommand(new OrganizeImportsCommand(service)) diff --git a/src/server/commands.ts b/src/server/commands.ts index 701f27b..78dfef0 100644 --- a/src/server/commands.ts +++ b/src/server/commands.ts @@ -1,9 +1,10 @@ import { commands, diagnosticManager, CancellationToken, Diagnostic, Disposable, ServiceStat, Uri as URI, window, workspace } from 'coc.nvim' -import { Range, TextEdit } from 'vscode-languageserver-types' +import { Location, Position, Range, TextEdit } from 'vscode-languageserver-types' import TsserverService from '../server' import { PluginManager } from '../utils/plugins' import * as Proto from './protocol' import TypeScriptServiceClientHost from './typescriptServiceClientHost' +import API from './utils/api' import { nodeModules } from './utils/helper' import { installModules } from './utils/modules' import * as typeConverters from './utils/typeConverters' @@ -184,6 +185,39 @@ export class ConfigurePluginCommand implements Command { } } +export class FileReferencesCommand implements Command { + public readonly id = 'tsserver.findAllFileReferences' + public static readonly minVersion = API.v420 + + public constructor( + private readonly service: TsserverService + ) {} + + public async execute() { + const client = await this.service.getClientHost() + if (client.serviceClient.apiVersion.lt(FileReferencesCommand.minVersion)) { + window.showMessage('Find file references failed. Requires TypeScript 4.2+.', 'error') + return + } + + const doc = await workspace.document + let { languageId } = doc.textDocument + if (client.serviceClient.modeIds.indexOf(languageId) == -1) return + + const openedFiledPath = client.serviceClient.toOpenedFilePath(doc.uri) + if (!openedFiledPath) return + + const response = await client.serviceClient.execute('fileReferences', { file: openedFiledPath }, CancellationToken.None) + if (response.type !== 'response' || !response.body) return + + const locations: Location[] = (response as Proto.FileReferencesResponse).body.refs.map(r => + typeConverters.Location.fromTextSpan(client.serviceClient.toResource(r.file), r) + ) + + await commands.executeCommand('editor.action.showReferences', doc.uri, Position.create(0, 0), locations) + } +} + export function registCommand(cmd: Command): Disposable { let { id, execute } = cmd return commands.registerCommand(id as string, execute, cmd) diff --git a/src/server/typescriptService.ts b/src/server/typescriptService.ts index 1dc60eb..47af526 100644 --- a/src/server/typescriptService.ts +++ b/src/server/typescriptService.ts @@ -19,7 +19,7 @@ export namespace ServerResponse { constructor( public readonly reason: string - ) { } + ) {} } // tslint:disable-next-line: new-parens @@ -80,6 +80,7 @@ export interface TypeScriptRequestTypes { 'selectionRange': [Proto.SelectionRangeRequestArgs, Proto.SelectionRangeResponse] 'signatureHelp': [Proto.SignatureHelpRequestArgs, Proto.SignatureHelpResponse] 'typeDefinition': [Proto.FileLocationRequestArgs, Proto.TypeDefinitionResponse] + 'fileReferences': [Proto.FileRequestArgs, Proto.FileReferencesResponse] } export interface ITypeScriptServiceClient {