Typescript:以编程方式访问 VS Code 的 "Find All References"
Typescript: accessing VS Code's "Find All References" programatically
我喜欢 VS Code 中的 Typescript 的一个原因是能够使用 Shift+F12(或右键单击)查找对函数的所有引用。是否可以通过编程方式获取此映射,或以某种方式导出它?
输出将包含如下信息:
fileA.ClassA.methodA is referenced in fileB.ClassB.methodB
因为这很容易做到 'by hand',我希望它也可以通过编程方式完成,但我不确定有哪些接口可用。
您需要使用Compiler API。它允许您使用 JS API(tsc 是 "just" 命令行版本)引用 TypeScript 的所有功能,包括模块层次结构。没看源码,不过很有可能这是TS VSC语言服务器内部使用的。
最坏的情况是,您会得到一个文件的 AST,这样您就可以按照您希望的任何方式搜索匹配项。
我刚找到包 ts-simple-ast. They provide a function .findReferences()
(see here)。
无法为您的任务提供解决方案,但由于您在这个问题上苦苦挣扎了很长时间,我会尽力为您指明正确的方向:
- 由于您可能必须为 VSCode 编写扩展,因此您应该从 VS Code API. Or with a tutorial. Maybe this one: Your First Extension
开始
- 然后,有一个处理"Find all references"命令的官方extension。我调查了一下——只有 4 个代码文件,它们看起来并不太神秘。因此,您可以以此扩展为起点并根据您的需要进行调整。
我觉得这种方式比编译器API
简单
对于最灵活的解决方案,您需要使用 TypeScript Language Service API。你要的具体方法是findReferences
。在超高层,您的程序将如下所示:
import ts from 'typescript'
// create service host
// see https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#incremental-build-support-using-the-language-services
const services = ts.createLanguageService(servicesHost, ts.createDocumentRegistry());
然而,根据您的需要,这可能有点矫枉过正。设置语言服务也可能相当困难。
相反,您可以重用 VS Code 的查找所有引用逻辑。为此,创建一个执行 vscode.executeReferenceProvider
command
的 VS 代码扩展
import * vscode from 'vscode';
export async function activate() {
const referenceLocation = await vscode.commands.executeCommand('vscode.executeReferenceProvider',
tsDocumentURI, // Uri of document containing symbol to find references for
new vscode.Position(0, 10), // Position (line, column) of symbol find references for
);
for (const location of referenceLocation) {
// do something with the locations, such as writing them to disk as json
}
}
这意味着您必须 运行 您的程序作为 VS Code 扩展,但设置起来要容易得多
我在同一个任务中,我路过你的 post,我终于用 ts-morph 得到了它,
就这么简单。
import { Project } from "ts-morph";
const project = new Project({
tsConfigFilePath: "<yourproject>\tsconfig.json",
});
for(const sourceFile of project.getSourceFiles()){
for(const classDeclaration of sourceFile.getClasses()){
console.log("---------")
console.log("Class ",classDeclaration.getName())
console.log("---------")
const referencedSymbols = classDeclaration.findReferences();
for (const referencedSymbol of referencedSymbols) {
for (const reference of referencedSymbol.getReferences()) {
console.log("---------")
console.log("REFERENCE")
console.log("---------")
console.log("File path: " + reference.getSourceFile().getFilePath());
console.log("Start: " + reference.getTextSpan().getStart());
console.log("Length: " + reference.getTextSpan().getLength());
console.log("Parent kind: " + reference.getNode().getParentOrThrow().getKindName());
console.log("\n");
}
}
}
}
我喜欢 VS Code 中的 Typescript 的一个原因是能够使用 Shift+F12(或右键单击)查找对函数的所有引用。是否可以通过编程方式获取此映射,或以某种方式导出它?
输出将包含如下信息:
fileA.ClassA.methodA is referenced in fileB.ClassB.methodB
因为这很容易做到 'by hand',我希望它也可以通过编程方式完成,但我不确定有哪些接口可用。
您需要使用Compiler API。它允许您使用 JS API(tsc 是 "just" 命令行版本)引用 TypeScript 的所有功能,包括模块层次结构。没看源码,不过很有可能这是TS VSC语言服务器内部使用的。
最坏的情况是,您会得到一个文件的 AST,这样您就可以按照您希望的任何方式搜索匹配项。
我刚找到包 ts-simple-ast. They provide a function .findReferences()
(see here)。
无法为您的任务提供解决方案,但由于您在这个问题上苦苦挣扎了很长时间,我会尽力为您指明正确的方向:
- 由于您可能必须为 VSCode 编写扩展,因此您应该从 VS Code API. Or with a tutorial. Maybe this one: Your First Extension 开始
- 然后,有一个处理"Find all references"命令的官方extension。我调查了一下——只有 4 个代码文件,它们看起来并不太神秘。因此,您可以以此扩展为起点并根据您的需要进行调整。
我觉得这种方式比编译器API
简单对于最灵活的解决方案,您需要使用 TypeScript Language Service API。你要的具体方法是findReferences
。在超高层,您的程序将如下所示:
import ts from 'typescript'
// create service host
// see https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#incremental-build-support-using-the-language-services
const services = ts.createLanguageService(servicesHost, ts.createDocumentRegistry());
然而,根据您的需要,这可能有点矫枉过正。设置语言服务也可能相当困难。
相反,您可以重用 VS Code 的查找所有引用逻辑。为此,创建一个执行 vscode.executeReferenceProvider
command
import * vscode from 'vscode';
export async function activate() {
const referenceLocation = await vscode.commands.executeCommand('vscode.executeReferenceProvider',
tsDocumentURI, // Uri of document containing symbol to find references for
new vscode.Position(0, 10), // Position (line, column) of symbol find references for
);
for (const location of referenceLocation) {
// do something with the locations, such as writing them to disk as json
}
}
这意味着您必须 运行 您的程序作为 VS Code 扩展,但设置起来要容易得多
我在同一个任务中,我路过你的 post,我终于用 ts-morph 得到了它, 就这么简单。
import { Project } from "ts-morph";
const project = new Project({
tsConfigFilePath: "<yourproject>\tsconfig.json",
});
for(const sourceFile of project.getSourceFiles()){
for(const classDeclaration of sourceFile.getClasses()){
console.log("---------")
console.log("Class ",classDeclaration.getName())
console.log("---------")
const referencedSymbols = classDeclaration.findReferences();
for (const referencedSymbol of referencedSymbols) {
for (const reference of referencedSymbol.getReferences()) {
console.log("---------")
console.log("REFERENCE")
console.log("---------")
console.log("File path: " + reference.getSourceFile().getFilePath());
console.log("Start: " + reference.getTextSpan().getStart());
console.log("Length: " + reference.getTextSpan().getLength());
console.log("Parent kind: " + reference.getNode().getParentOrThrow().getKindName());
console.log("\n");
}
}
}
}