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

"Show implementations" link display error fix #12277

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 35 additions & 3 deletions editors/code/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,46 @@ import { WorkspaceEdit } from "vscode";
import { Workspace } from "./ctx";
import { updateConfig } from "./config";
import { substituteVariablesInEnv } from "./config";
import { randomUUID } from "crypto";

export interface Env {
[name: string]: string;
}

function renderCommand(cmd: ra.CommandLink) {
return `[${cmd.title}](command:${cmd.command}?${encodeURIComponent(
JSON.stringify(cmd.arguments)
// Command URIs have a form of command:command-name?arguments, where
// arguments is a percent-encoded array of data we want to pass along to
// the command function. For "Show References" this is a list of all file
// URIs with locations of every reference, and it can get quite long.
//
// To work around it we use an intermediary linkToCommand command. When
// we render a command link, a reference to a command with all its arguments
// is stored in a map, and instead a linkToCommand link is rendered
// with the key to that map.
export const LINKED_COMMANDS = new Map<string, ra.CommandLink>();
listochkin marked this conversation as resolved.
Show resolved Hide resolved

// For now the map is cleaned up periodically (I've set it to every
// 10 minutes). In general case we'll probably need to introduce TTLs or
// flags to denote ephemeral links (like these in hover popups) and
// persistent links and clean those separately. But for now simply keeping
// the last few links in the map should be good enough. Likewise, we could
// add code to remove a target command from the map after the link is
// clicked, but assuming most links in hover sheets won't be clicked anyway
// this code won't change the overall memory use much.
setInterval(function cleanupOlderCommandLinks() {
// keys are returned in insertion order, we'll keep a few
// of recent keys available, and clean the rest
const keys = [...LINKED_COMMANDS.keys()];
const keysToRemove = keys.slice(0, keys.length - 10);
for (const key of keysToRemove) {
LINKED_COMMANDS.delete(key);
}
}, 10 * 60 * 1000);

function renderCommand(cmd: ra.CommandLink): string {
const commandId = randomUUID();
LINKED_COMMANDS.set(commandId, cmd);
return `[${cmd.title}](command:rust-analyzer.linkToCommand?${encodeURIComponent(
JSON.stringify([commandId])
)} '${cmd.tooltip}')`;
}

Expand Down
11 changes: 11 additions & 0 deletions editors/code/src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { AstInspector } from "./ast_inspector";
import { isRustDocument, isCargoTomlDocument, sleep, isRustEditor } from "./util";
import { startDebugSession, makeDebugConfig } from "./debug";
import { LanguageClient } from "vscode-languageclient/node";
import { LINKED_COMMANDS } from "./client";

export * from "./ast_inspector";
export * from "./run";
Expand Down Expand Up @@ -928,3 +929,13 @@ export function newDebugConfig(ctx: Ctx): Cmd {
await makeDebugConfig(ctx, item.runnable);
};
}

export function linkToCommand(ctx: Ctx): Cmd {
return async (commandId: string) => {
const link = LINKED_COMMANDS.get(commandId);
if (ctx.client && link) {
const { command, arguments: args = [] } = link;
await vscode.commands.executeCommand(command, ...args);
}
};
}
2 changes: 2 additions & 0 deletions editors/code/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ async function initCommonContext(context: vscode.ExtensionContext, ctx: Ctx) {
ctx.registerCommand("resolveCodeAction", commands.resolveCodeAction);
ctx.registerCommand("applyActionGroup", commands.applyActionGroup);
ctx.registerCommand("gotoLocation", commands.gotoLocation);

ctx.registerCommand("linkToCommand", commands.linkToCommand);
}

export async function deactivate() {
Expand Down