Modify existing CodeLens in VS Code Extension

Viewed 473

In VS Code, if your language extension provides it, you will get codelens to show you a reference count above functions, variables, and other symbols. Like so: https://i.imgur.com/HXzgjGh.png

I'm taking over a project, and one of my first tasks is restructuring. As part of that, I would love to pull references into local/external without having to "show all references".

I went through the extension API example, and have been looking through the API. Afterwards I built a few, mostly pointless, extensions to learn a bit more about how they work. I can insert a codelens with whatever data I want, but now I'm stuck. There doesn't seem to be a way to get the existing codelens, or really, do anything to access that information that built the "i references".

Another clue I found along my way: The way this works is by the language defining the symbols. However, there doesn't seem to be any way to iterate over them either? I could re-parse everything and make my own codelens analysis, but that will take longer than manually checking the scope. It also seems to be more complicated than necessary.

I was hoping for an event that is triggered when a codelens is generated/changed and provide that codelens back to me. It seems like the codelens is bubbled and I have no access to it.

My ideal would be two get two pieces of information:

  1. Get the number i from "i references".
  2. Get the line it applies to.

Is this possible or out of the scope of the API? I can rewrite the parsing, but something is already generating that information, so I would prefer to access it.

1 Answers

I found the answer to my own question, eventually. Namely, the built in commands. Turns out, you can get the document symbols and execute the reference provider using two commands (which I turned into functions here):

async function getSymbols(document: TextDocument): Promise<SymbolInformation[]>
{
    return await commands.executeCommand<SymbolInformation[]>('vscode.executeDocumentSymbolProvider', 
                                                                document.uri) || [];
}

async function getReferences(location: Location): Promise<Location[]>
{
    return await commands.executeCommand<Location[]>('vscode.executeReferenceProvider',
                                                    location.uri,
                                                    new Position(
                                                        location.range.start.line,
                                                        location.range.start.character)) || [];
}

I later chain these two in a separate function call involving certain conditions.

This isn't exactly what I wanted to do (get the codelens return value), but it allows me to re-use what is implemented without having to reinvent the wheel.

Related