Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Interact with the running vscode Language Server #1493

Open
ams1 opened this issue Jun 10, 2024 · 1 comment
Open

Interact with the running vscode Language Server #1493

ams1 opened this issue Jun 10, 2024 · 1 comment

Comments

@ams1
Copy link

ams1 commented Jun 10, 2024

Hi 👋,

Big THANK YOU for maintaining our essential tooling! 🫡

Context:
Although I love and heavily use commands like Find All References, Show Call Hierarchy etc., OFTEN, for documentation purposes I feel the need to EXTRACT those results I see in the references tab in a way that I can do further processing outside vscode: ex. as from - to pairs (function from invokes function to) - so I could build a graph-like document (using graphviz etc.).

My question:
Is there a 'simple' way to access the running vscode server instance attached to my current vscode project and programmatically send it commands/be able to capture some json output - instead of interacting with it from the menu?

By 'simple' I mean for example curl or maybe a short extension.

If there is no simple way, could you please point me to where I should start digging regarding the normal way 😄 - some examples?
At first glance it seems extensions are focused more on the language server side - I don't want to maintain the server itself - the one I have running does a great job already - I just want to be able to interact with it programmatically.

Hope I made a good job describing my problem and hope this is a good place to pose the question. 🤗

Thank you.

@ams1
Copy link
Author

ams1 commented Jun 10, 2024

Hi, me again 😄

In the meantime I found a way (not sure if it's the best) using an extension and the following commands from https://code.visualstudio.com/api/references/commands:

vscode.prepareCallHierarchy - Prepare call hierarchy at a position inside a document

  • uri - Uri of a text document
  • position - A position in a text document
  • (returns) - A promise that resolves to an array of CallHierarchyItem-instances

vscode.provideIncomingCalls - Compute incoming calls for an item

  • item - A call hierarchy item
  • (returns) - A promise that resolves to an array of CallHierarchyIncomingCall-instances

vscode.provideOutgoingCalls - Compute outgoing calls for an item

  • item - A call hierarchy item
  • (returns) - A promise that resolves to an array of CallHierarchyOutgoingCall-instances

A working snippet (maybe it helps others).

import * as vscode from 'vscode';

async function logOutgoingCalls(item: vscode.CallHierarchyItem) {
	const outgoingCalls: vscode.CallHierarchyOutgoingCall[] = await vscode.commands.executeCommand('vscode.provideOutgoingCalls', item);

	// iterate over outgoingCalls
	for (const outgoingCall of outgoingCalls) {
		console.log(item.name, '-[:invokes]->', outgoingCall.to.name);

		// recursively log outgoing calls
		// TODO: handle cycles
		await logOutgoingCalls(outgoingCall.to);
	}
}

async function logIncomingCalls(item: vscode.CallHierarchyItem) {
	const incomingCalls: vscode.CallHierarchyIncomingCall[] = await vscode.commands.executeCommand('vscode.provideIncomingCalls', item);

	// iterate over incomingCalls
	for (const incomingCall of incomingCalls) {
		console.log(incomingCall.from.name, '-[:invokes]->', item.name);

		// recursively log incoming calls
		// TODO: handle cycles
		await logIncomingCalls(incomingCall.from);
	}
}

export function activate(context: vscode.ExtensionContext) {
	console.log('Congratulations, your extension is now active!');

	let disposable = vscode.commands.registerCommand('extension.logCallHierarchy', async () => {
		if (vscode.window.activeTextEditor) {
			const position = vscode.window.activeTextEditor.selection.active;
			const uri = vscode.window.activeTextEditor.document.uri;

			const items: vscode.CallHierarchyItem[] = await vscode.commands.executeCommand('vscode.prepareCallHierarchy', uri, position);
			if (items) {
				for (const item of items) {

					// log incoming calls
					console.log('Incoming calls of ', item.name);
					await logIncomingCalls(item);

					// log outgoing calls
					console.log('Outgoing calls of ', item.name);
					await logOutgoingCalls(item);
				}
			}
		}
	});

	context.subscriptions.push(disposable);

	let statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100);
	statusBarItem.command = 'extension.logCallHierarchy';
	statusBarItem.text = "Log Call Hierarchy";
	statusBarItem.show();
	context.subscriptions.push(statusBarItem);
}

export function deactivate() { }

From my point of view this can be closed - thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant