Hoff
Hoff

Reputation: 39826

Typescript: accessing VS Code's "Find All References" programatically

One of the things I like about Typescript in VS Code is the ability to find all references to a function with Shift+F12 (or right-click). Is it possible to get to this mapping programatically, or to export it somehow?

The output would contain information like:

fileA.ClassA.methodA is referenced in fileB.ClassB.methodB

Since this is easy to do 'by hand', I'm hoping that it can also done programatically, but I'm not sure what interfaces are available.

enter image description here

Upvotes: 22

Views: 5550

Answers (5)

Carlo Capuano
Carlo Capuano

Reputation: 392

I was in the same quest and I passed by your post, I finally got it using ts-morph, here is as simple as it gets.

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");
            }
        }
    }
}

Upvotes: 8

Matt Bierner
Matt Bierner

Reputation: 65195

For the most flexible solution, you'll want to use the TypeScript Language Service API. The specific method you want is findReferences. At a super high level, your program will look like this:

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());

However that may be overkill depending on your needs. Setting up the language service can also be rather difficult.

Instead, you may be able to reuse VS Code's find all references logic. To do this, create a VS Code extension that executes the 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
   }
}

This means that you will have to run your program as a VS Code extension, but it is far easier to setup

Upvotes: 8

x00
x00

Reputation: 13823

Can't deliver a solution to you task, but as you struggling with this question for a long time, I'll try to point you in the, possibly, right direction:

  1. As you'll probably have to write an extension for VSCode, you should start with VS Code API. Or with a tutorial. Maybe this one: Your First Extension
  2. Then, there is an official extension which deals with "Find all references" command. I looked into - there are only 4 files of code, and they don't look too cryptic. So you can take this extension for a starting point and tweak to your needs.

I think this way is easier than Compiler API

Upvotes: 2

Vetterjack
Vetterjack

Reputation: 2505

I just found the package ts-simple-ast. They provide a function .findReferences() (see here).

Upvotes: 2

zeh
zeh

Reputation: 10659

You need to use the Compiler API. It allows you to reference all features of TypeScript with a JS API (tsc is "just" the command line version), including module hierarchy. I haven't looked at the source, but it's very likely that this is what the TS VSC language server uses internally.

Worst case scenario, you get an AST of a file so you can search for occurrences in any way you wish.

Upvotes: 6

Related Questions