2019-12-30 13:07:04 -06:00
|
|
|
import * as vscode from "vscode";
|
|
|
|
import * as lc from "vscode-languageclient";
|
2020-05-25 07:56:26 -05:00
|
|
|
import * as ra from "./lsp_ext";
|
2021-08-10 08:35:37 -05:00
|
|
|
import * as path from "path";
|
2022-05-17 12:15:06 -05:00
|
|
|
|
2023-03-09 14:06:26 -06:00
|
|
|
import { Ctx, Cmd, CtxInit, discoverWorkspace } from "./ctx";
|
2020-05-25 07:12:53 -05:00
|
|
|
import { applySnippetWorkspaceEdit, applySnippetTextEdits } from "./snippets";
|
2020-05-25 04:10:31 -05:00
|
|
|
import { spawnSync } from "child_process";
|
2021-02-10 05:28:13 -06:00
|
|
|
import { RunnableQuickPick, selectRunnable, createTask, createArgs } from "./run";
|
2020-05-25 05:02:30 -05:00
|
|
|
import { AstInspector } from "./ast_inspector";
|
2022-07-17 10:38:56 -05:00
|
|
|
import { isRustDocument, isCargoTomlDocument, sleep, isRustEditor, RustEditor } from "./util";
|
2020-06-02 07:33:47 -05:00
|
|
|
import { startDebugSession, makeDebugConfig } from "./debug";
|
2021-02-27 11:04:43 -06:00
|
|
|
import { LanguageClient } from "vscode-languageclient/node";
|
2022-05-16 13:53:00 -05:00
|
|
|
import { LINKED_COMMANDS } from "./client";
|
2022-07-17 10:38:56 -05:00
|
|
|
import { DependencyId } from "./dependencies_provider";
|
2022-05-17 12:15:06 -05:00
|
|
|
|
2020-05-25 05:02:30 -05:00
|
|
|
export * from "./ast_inspector";
|
|
|
|
export * from "./run";
|
2020-05-25 04:10:31 -05:00
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function analyzerStatus(ctx: CtxInit): Cmd {
|
2020-05-25 04:10:31 -05:00
|
|
|
const tdcp = new (class implements vscode.TextDocumentContentProvider {
|
|
|
|
readonly uri = vscode.Uri.parse("rust-analyzer-status://status");
|
|
|
|
readonly eventEmitter = new vscode.EventEmitter<vscode.Uri>();
|
|
|
|
|
2022-10-17 07:20:14 -05:00
|
|
|
async provideTextDocumentContent(_uri: vscode.Uri): Promise<string> {
|
2020-05-25 04:10:31 -05:00
|
|
|
if (!vscode.window.activeTextEditor) return "";
|
2022-10-28 17:44:37 -05:00
|
|
|
const client = ctx.client;
|
2020-05-25 04:10:31 -05:00
|
|
|
|
2020-09-29 15:05:18 -05:00
|
|
|
const params: ra.AnalyzerStatusParams = {};
|
|
|
|
const doc = ctx.activeRustEditor?.document;
|
|
|
|
if (doc != null) {
|
2022-10-17 07:20:14 -05:00
|
|
|
params.textDocument = client.code2ProtocolConverter.asTextDocumentIdentifier(doc);
|
2020-09-29 15:05:18 -05:00
|
|
|
}
|
2022-10-17 07:20:14 -05:00
|
|
|
return await client.sendRequest(ra.analyzerStatus, params);
|
2020-05-25 04:10:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
get onDidChange(): vscode.Event<vscode.Uri> {
|
|
|
|
return this.eventEmitter.event;
|
|
|
|
}
|
|
|
|
})();
|
|
|
|
|
2022-10-17 07:20:14 -05:00
|
|
|
ctx.pushExtCleanup(
|
2020-05-25 04:10:31 -05:00
|
|
|
vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-status", tdcp)
|
|
|
|
);
|
|
|
|
|
|
|
|
return async () => {
|
|
|
|
const document = await vscode.workspace.openTextDocument(tdcp.uri);
|
2021-08-09 11:24:43 -05:00
|
|
|
tdcp.eventEmitter.fire(tdcp.uri);
|
|
|
|
void (await vscode.window.showTextDocument(document, {
|
|
|
|
viewColumn: vscode.ViewColumn.Two,
|
|
|
|
preserveFocus: true,
|
|
|
|
}));
|
2020-05-25 04:10:31 -05:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function memoryUsage(ctx: CtxInit): Cmd {
|
2020-07-07 05:10:14 -05:00
|
|
|
const tdcp = new (class implements vscode.TextDocumentContentProvider {
|
|
|
|
readonly uri = vscode.Uri.parse("rust-analyzer-memory://memory");
|
|
|
|
readonly eventEmitter = new vscode.EventEmitter<vscode.Uri>();
|
|
|
|
|
|
|
|
provideTextDocumentContent(_uri: vscode.Uri): vscode.ProviderResult<string> {
|
|
|
|
if (!vscode.window.activeTextEditor) return "";
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
return ctx.client.sendRequest(ra.memoryUsage).then((mem: any) => {
|
|
|
|
return "Per-query memory usage:\n" + mem + "\n(note: database has been cleared)";
|
|
|
|
});
|
2020-07-07 05:10:14 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
get onDidChange(): vscode.Event<vscode.Uri> {
|
|
|
|
return this.eventEmitter.event;
|
|
|
|
}
|
|
|
|
})();
|
|
|
|
|
2022-10-17 07:20:14 -05:00
|
|
|
ctx.pushExtCleanup(
|
2020-07-07 05:10:14 -05:00
|
|
|
vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-memory", tdcp)
|
|
|
|
);
|
|
|
|
|
|
|
|
return async () => {
|
|
|
|
tdcp.eventEmitter.fire(tdcp.uri);
|
|
|
|
const document = await vscode.workspace.openTextDocument(tdcp.uri);
|
|
|
|
return vscode.window.showTextDocument(document, vscode.ViewColumn.Two, true);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function shuffleCrateGraph(ctx: CtxInit): Cmd {
|
2021-12-07 08:38:12 -06:00
|
|
|
return async () => {
|
2022-10-28 17:44:37 -05:00
|
|
|
return ctx.client.sendRequest(ra.shuffleCrateGraph);
|
2021-12-07 08:38:12 -06:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-02-14 07:45:48 -06:00
|
|
|
export function triggerParameterHints(_: CtxInit): Cmd {
|
|
|
|
return async () => {
|
2023-04-20 14:13:33 -05:00
|
|
|
const parameterHintsEnabled = vscode.workspace
|
|
|
|
.getConfiguration("editor")
|
|
|
|
.get<boolean>("parameterHints.enabled");
|
2023-04-20 11:41:15 -05:00
|
|
|
|
2023-04-20 14:13:33 -05:00
|
|
|
if (parameterHintsEnabled) {
|
2023-04-20 11:41:15 -05:00
|
|
|
await vscode.commands.executeCommand("editor.action.triggerParameterHints");
|
|
|
|
}
|
2023-02-14 07:45:48 -06:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-03-10 03:13:30 -06:00
|
|
|
export function openLogs(ctx: CtxInit): Cmd {
|
|
|
|
return async () => {
|
|
|
|
if (ctx.client.outputChannel) {
|
|
|
|
ctx.client.outputChannel.show();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function matchingBrace(ctx: CtxInit): Cmd {
|
2020-05-25 04:10:31 -05:00
|
|
|
return async () => {
|
|
|
|
const editor = ctx.activeRustEditor;
|
2022-10-17 07:20:14 -05:00
|
|
|
if (!editor) return;
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
const client = ctx.client;
|
2020-05-25 04:10:31 -05:00
|
|
|
|
|
|
|
const response = await client.sendRequest(ra.matchingBrace, {
|
2022-10-17 07:20:14 -05:00
|
|
|
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document),
|
2020-05-25 04:10:31 -05:00
|
|
|
positions: editor.selections.map((s) =>
|
|
|
|
client.code2ProtocolConverter.asPosition(s.active)
|
|
|
|
),
|
|
|
|
});
|
|
|
|
editor.selections = editor.selections.map((sel, idx) => {
|
|
|
|
const active = client.protocol2CodeConverter.asPosition(response[idx]);
|
|
|
|
const anchor = sel.isEmpty ? active : sel.anchor;
|
|
|
|
return new vscode.Selection(anchor, active);
|
|
|
|
});
|
|
|
|
editor.revealRange(editor.selection);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function joinLines(ctx: CtxInit): Cmd {
|
2020-05-25 04:10:31 -05:00
|
|
|
return async () => {
|
|
|
|
const editor = ctx.activeRustEditor;
|
2022-10-17 07:20:14 -05:00
|
|
|
if (!editor) return;
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
const client = ctx.client;
|
2020-05-25 04:10:31 -05:00
|
|
|
|
|
|
|
const items: lc.TextEdit[] = await client.sendRequest(ra.joinLines, {
|
|
|
|
ranges: editor.selections.map((it) => client.code2ProtocolConverter.asRange(it)),
|
2022-10-17 07:20:14 -05:00
|
|
|
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document),
|
2020-05-25 04:10:31 -05:00
|
|
|
});
|
2022-05-21 10:38:10 -05:00
|
|
|
const textEdits = await client.protocol2CodeConverter.asTextEdits(items);
|
|
|
|
await editor.edit((builder) => {
|
|
|
|
textEdits.forEach((edit: any) => {
|
2020-05-25 04:10:31 -05:00
|
|
|
builder.replace(edit.range, edit.newText);
|
|
|
|
});
|
2021-02-09 08:12:46 -06:00
|
|
|
});
|
2020-05-25 04:10:31 -05:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function moveItemUp(ctx: CtxInit): Cmd {
|
2023-01-23 08:26:28 -06:00
|
|
|
return moveItem(ctx, "Up");
|
2021-03-16 07:37:00 -05:00
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function moveItemDown(ctx: CtxInit): Cmd {
|
2023-01-23 08:26:28 -06:00
|
|
|
return moveItem(ctx, "Down");
|
2021-03-16 07:37:00 -05:00
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function moveItem(ctx: CtxInit, direction: ra.Direction): Cmd {
|
2021-03-16 07:37:00 -05:00
|
|
|
return async () => {
|
|
|
|
const editor = ctx.activeRustEditor;
|
2022-10-17 07:20:14 -05:00
|
|
|
if (!editor) return;
|
2022-10-28 17:44:37 -05:00
|
|
|
const client = ctx.client;
|
2021-03-16 07:37:00 -05:00
|
|
|
|
2021-04-13 13:32:45 -05:00
|
|
|
const lcEdits = await client.sendRequest(ra.moveItem, {
|
2021-03-16 07:37:00 -05:00
|
|
|
range: client.code2ProtocolConverter.asRange(editor.selection),
|
2022-10-17 07:20:14 -05:00
|
|
|
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document),
|
2021-03-16 07:37:00 -05:00
|
|
|
direction,
|
|
|
|
});
|
|
|
|
|
2021-04-13 13:32:45 -05:00
|
|
|
if (!lcEdits) return;
|
2021-03-16 09:57:14 -05:00
|
|
|
|
2022-04-08 06:24:28 -05:00
|
|
|
const edits = await client.protocol2CodeConverter.asTextEdits(lcEdits);
|
2021-04-13 13:32:45 -05:00
|
|
|
await applySnippetTextEdits(editor, edits);
|
2021-03-16 07:37:00 -05:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function onEnter(ctx: CtxInit): Cmd {
|
2020-05-25 04:10:31 -05:00
|
|
|
async function handleKeypress() {
|
|
|
|
const editor = ctx.activeRustEditor;
|
|
|
|
|
2022-10-17 07:20:14 -05:00
|
|
|
if (!editor) return false;
|
2020-05-25 04:10:31 -05:00
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
const client = ctx.client;
|
2020-05-25 07:12:53 -05:00
|
|
|
const lcEdits = await client
|
|
|
|
.sendRequest(ra.onEnter, {
|
2022-10-17 07:20:14 -05:00
|
|
|
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(
|
2020-09-29 15:05:18 -05:00
|
|
|
editor.document
|
|
|
|
),
|
2020-05-25 04:10:31 -05:00
|
|
|
position: client.code2ProtocolConverter.asPosition(editor.selection.active),
|
2020-09-01 11:53:07 -05:00
|
|
|
})
|
|
|
|
.catch((_error: any) => {
|
|
|
|
// client.handleFailedRequest(OnEnterRequest.type, error, null);
|
2020-05-25 04:10:31 -05:00
|
|
|
return null;
|
|
|
|
});
|
2020-05-25 07:12:53 -05:00
|
|
|
if (!lcEdits) return false;
|
2020-05-25 04:10:31 -05:00
|
|
|
|
2022-04-08 06:24:28 -05:00
|
|
|
const edits = await client.protocol2CodeConverter.asTextEdits(lcEdits);
|
2020-05-25 07:12:53 -05:00
|
|
|
await applySnippetTextEdits(editor, edits);
|
2020-05-25 04:10:31 -05:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return async () => {
|
|
|
|
if (await handleKeypress()) return;
|
|
|
|
|
|
|
|
await vscode.commands.executeCommand("default:type", { text: "\n" });
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function parentModule(ctx: CtxInit): Cmd {
|
2020-05-25 04:10:31 -05:00
|
|
|
return async () => {
|
2021-10-02 21:58:10 -05:00
|
|
|
const editor = vscode.window.activeTextEditor;
|
2022-10-17 07:20:14 -05:00
|
|
|
if (!editor) return;
|
2021-10-02 21:58:10 -05:00
|
|
|
if (!(isRustDocument(editor.document) || isCargoTomlDocument(editor.document))) return;
|
2021-10-13 17:16:42 -05:00
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
const client = ctx.client;
|
2022-10-17 07:20:14 -05:00
|
|
|
|
2021-03-15 09:49:20 -05:00
|
|
|
const locations = await client.sendRequest(ra.parentModule, {
|
2022-10-17 07:20:14 -05:00
|
|
|
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document),
|
2021-03-15 09:49:20 -05:00
|
|
|
position: client.code2ProtocolConverter.asPosition(editor.selection.active),
|
2020-05-25 04:10:31 -05:00
|
|
|
});
|
2021-10-13 17:16:42 -05:00
|
|
|
if (!locations) return;
|
2020-05-25 04:10:31 -05:00
|
|
|
|
2021-03-15 09:49:20 -05:00
|
|
|
if (locations.length === 1) {
|
|
|
|
const loc = locations[0];
|
2020-05-25 04:10:31 -05:00
|
|
|
|
2021-03-15 09:49:20 -05:00
|
|
|
const uri = client.protocol2CodeConverter.asUri(loc.targetUri);
|
|
|
|
const range = client.protocol2CodeConverter.asRange(loc.targetRange);
|
|
|
|
|
|
|
|
const doc = await vscode.workspace.openTextDocument(uri);
|
|
|
|
const e = await vscode.window.showTextDocument(doc);
|
|
|
|
e.selection = new vscode.Selection(range.start, range.start);
|
|
|
|
e.revealRange(range, vscode.TextEditorRevealType.InCenter);
|
|
|
|
} else {
|
|
|
|
const uri = editor.document.uri.toString();
|
|
|
|
const position = client.code2ProtocolConverter.asPosition(editor.selection.active);
|
|
|
|
await showReferencesImpl(
|
|
|
|
client,
|
|
|
|
uri,
|
|
|
|
position,
|
|
|
|
locations.map((loc) => lc.Location.create(loc.targetUri, loc.targetRange))
|
|
|
|
);
|
|
|
|
}
|
2020-05-25 04:10:31 -05:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function openCargoToml(ctx: CtxInit): Cmd {
|
2020-11-12 19:48:07 -06:00
|
|
|
return async () => {
|
|
|
|
const editor = ctx.activeRustEditor;
|
2022-10-17 07:20:14 -05:00
|
|
|
if (!editor) return;
|
2020-11-12 19:48:07 -06:00
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
const client = ctx.client;
|
2020-11-12 19:48:07 -06:00
|
|
|
const response = await client.sendRequest(ra.openCargoToml, {
|
2022-10-17 07:20:14 -05:00
|
|
|
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document),
|
2020-11-12 19:48:07 -06:00
|
|
|
});
|
|
|
|
if (!response) return;
|
|
|
|
|
|
|
|
const uri = client.protocol2CodeConverter.asUri(response.uri);
|
|
|
|
const range = client.protocol2CodeConverter.asRange(response.range);
|
|
|
|
|
|
|
|
const doc = await vscode.workspace.openTextDocument(uri);
|
|
|
|
const e = await vscode.window.showTextDocument(doc);
|
|
|
|
e.selection = new vscode.Selection(range.start, range.start);
|
|
|
|
e.revealRange(range, vscode.TextEditorRevealType.InCenter);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-02-25 18:37:55 -06:00
|
|
|
export function revealDependency(ctx: CtxInit): Cmd {
|
|
|
|
return async (editor: RustEditor) => {
|
|
|
|
const rootPath = vscode.workspace.workspaceFolders![0].uri.fsPath;
|
|
|
|
const documentPath = editor.document.uri.fsPath;
|
|
|
|
if (documentPath.startsWith(rootPath)) return;
|
2023-04-02 19:58:20 -05:00
|
|
|
const dep = ctx.dependencies?.getDependency(documentPath);
|
2022-02-25 18:37:55 -06:00
|
|
|
if (dep) {
|
2023-04-02 19:58:20 -05:00
|
|
|
await ctx.treeView?.reveal(dep, { select: true, expand: true });
|
2022-02-25 18:37:55 -06:00
|
|
|
} else {
|
|
|
|
let documentPath = editor.document.uri.fsPath;
|
|
|
|
const parentChain: DependencyId[] = [{ id: documentPath.toLowerCase() }];
|
|
|
|
do {
|
|
|
|
documentPath = path.dirname(documentPath);
|
|
|
|
parentChain.push({ id: documentPath.toLowerCase() });
|
2023-04-02 19:58:20 -05:00
|
|
|
} while (!ctx.dependencies?.contains(documentPath));
|
2022-02-25 18:37:55 -06:00
|
|
|
parentChain.reverse();
|
|
|
|
for (const idx in parentChain) {
|
2023-04-02 19:58:20 -05:00
|
|
|
await ctx.treeView?.reveal(parentChain[idx], { select: true, expand: true });
|
2022-02-25 18:37:55 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function execRevealDependency(e: RustEditor): Promise<void> {
|
2022-07-17 10:38:56 -05:00
|
|
|
await vscode.commands.executeCommand("rust-analyzer.revealDependency", e);
|
2022-02-25 18:37:55 -06:00
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function ssr(ctx: CtxInit): Cmd {
|
2020-05-25 04:10:31 -05:00
|
|
|
return async () => {
|
2020-07-22 00:00:28 -05:00
|
|
|
const editor = vscode.window.activeTextEditor;
|
2022-10-17 07:20:14 -05:00
|
|
|
if (!editor) return;
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
const client = ctx.client;
|
2020-07-22 00:00:28 -05:00
|
|
|
|
|
|
|
const position = editor.selection.active;
|
2020-07-28 20:44:01 -05:00
|
|
|
const selections = editor.selections;
|
2022-10-17 07:20:14 -05:00
|
|
|
const textDocument = client.code2ProtocolConverter.asTextDocumentIdentifier(
|
2020-09-29 15:05:18 -05:00
|
|
|
editor.document
|
|
|
|
);
|
2020-05-25 04:10:31 -05:00
|
|
|
|
|
|
|
const options: vscode.InputBoxOptions = {
|
|
|
|
value: "() ==>> ()",
|
2020-09-15 06:32:56 -05:00
|
|
|
prompt: "Enter request, for example 'Foo($a) ==>> Foo::new($a)' ",
|
2020-05-25 04:10:31 -05:00
|
|
|
validateInput: async (x: string) => {
|
|
|
|
try {
|
2020-07-22 00:00:28 -05:00
|
|
|
await client.sendRequest(ra.ssr, {
|
2020-07-28 20:44:01 -05:00
|
|
|
query: x,
|
|
|
|
parseOnly: true,
|
|
|
|
textDocument,
|
|
|
|
position,
|
|
|
|
selections,
|
2020-07-22 00:00:28 -05:00
|
|
|
});
|
2020-05-25 04:10:31 -05:00
|
|
|
} catch (e) {
|
|
|
|
return e.toString();
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
},
|
|
|
|
};
|
|
|
|
const request = await vscode.window.showInputBox(options);
|
|
|
|
if (!request) return;
|
|
|
|
|
2021-02-09 08:12:46 -06:00
|
|
|
await vscode.window.withProgress(
|
|
|
|
{
|
2020-06-29 04:17:35 -05:00
|
|
|
location: vscode.ProgressLocation.Notification,
|
|
|
|
title: "Structured search replace in progress...",
|
|
|
|
cancellable: false,
|
2022-04-08 06:24:28 -05:00
|
|
|
},
|
|
|
|
async (_progress, token) => {
|
2020-07-22 00:00:28 -05:00
|
|
|
const edit = await client.sendRequest(ra.ssr, {
|
2020-07-28 20:44:01 -05:00
|
|
|
query: request,
|
|
|
|
parseOnly: false,
|
|
|
|
textDocument,
|
|
|
|
position,
|
|
|
|
selections,
|
2020-07-22 00:00:28 -05:00
|
|
|
});
|
2022-05-17 12:15:06 -05:00
|
|
|
|
2022-04-08 06:24:28 -05:00
|
|
|
await vscode.workspace.applyEdit(
|
|
|
|
await client.protocol2CodeConverter.asWorkspaceEdit(edit, token)
|
|
|
|
);
|
2021-02-09 08:12:46 -06:00
|
|
|
}
|
|
|
|
);
|
2020-05-25 04:10:31 -05:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function serverVersion(ctx: CtxInit): Cmd {
|
2020-05-25 04:10:31 -05:00
|
|
|
return async () => {
|
2022-10-17 07:53:46 -05:00
|
|
|
if (!ctx.serverPath) {
|
|
|
|
void vscode.window.showWarningMessage(`rust-analyzer server is not running`);
|
|
|
|
return;
|
|
|
|
}
|
2020-05-25 04:10:31 -05:00
|
|
|
const { stdout } = spawnSync(ctx.serverPath, ["--version"], { encoding: "utf8" });
|
2021-03-12 11:49:00 -06:00
|
|
|
const versionString = stdout.slice(`rust-analyzer `.length).trim();
|
2020-05-25 04:10:31 -05:00
|
|
|
|
|
|
|
void vscode.window.showInformationMessage(`rust-analyzer version: ${versionString}`);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-05-25 05:02:30 -05:00
|
|
|
// Opens the virtual file that will show the syntax tree
|
|
|
|
//
|
|
|
|
// The contents of the file come from the `TextDocumentContentProvider`
|
2022-10-28 17:44:37 -05:00
|
|
|
export function syntaxTree(ctx: CtxInit): Cmd {
|
2020-05-25 05:02:30 -05:00
|
|
|
const tdcp = new (class implements vscode.TextDocumentContentProvider {
|
2022-07-06 10:36:42 -05:00
|
|
|
readonly uri = vscode.Uri.parse("rust-analyzer-syntax-tree://syntaxtree/tree.rast");
|
2020-05-25 05:02:30 -05:00
|
|
|
readonly eventEmitter = new vscode.EventEmitter<vscode.Uri>();
|
|
|
|
constructor() {
|
|
|
|
vscode.workspace.onDidChangeTextDocument(
|
|
|
|
this.onDidChangeTextDocument,
|
|
|
|
this,
|
|
|
|
ctx.subscriptions
|
|
|
|
);
|
|
|
|
vscode.window.onDidChangeActiveTextEditor(
|
|
|
|
this.onDidChangeActiveTextEditor,
|
|
|
|
this,
|
|
|
|
ctx.subscriptions
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
private onDidChangeTextDocument(event: vscode.TextDocumentChangeEvent) {
|
|
|
|
if (isRustDocument(event.document)) {
|
|
|
|
// We need to order this after language server updates, but there's no API for that.
|
|
|
|
// Hence, good old sleep().
|
|
|
|
void sleep(10).then(() => this.eventEmitter.fire(this.uri));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private onDidChangeActiveTextEditor(editor: vscode.TextEditor | undefined) {
|
|
|
|
if (editor && isRustEditor(editor)) {
|
|
|
|
this.eventEmitter.fire(this.uri);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-17 07:20:14 -05:00
|
|
|
async provideTextDocumentContent(
|
2020-05-25 05:02:30 -05:00
|
|
|
uri: vscode.Uri,
|
|
|
|
ct: vscode.CancellationToken
|
2022-10-17 07:20:14 -05:00
|
|
|
): Promise<string> {
|
2020-05-25 05:02:30 -05:00
|
|
|
const rustEditor = ctx.activeRustEditor;
|
|
|
|
if (!rustEditor) return "";
|
2022-10-28 17:44:37 -05:00
|
|
|
const client = ctx.client;
|
2020-05-25 05:02:30 -05:00
|
|
|
|
|
|
|
// When the range based query is enabled we take the range of the selection
|
|
|
|
const range =
|
|
|
|
uri.query === "range=true" && !rustEditor.selection.isEmpty
|
2022-10-17 07:20:14 -05:00
|
|
|
? client.code2ProtocolConverter.asRange(rustEditor.selection)
|
2020-05-25 05:02:30 -05:00
|
|
|
: null;
|
|
|
|
|
|
|
|
const params = { textDocument: { uri: rustEditor.document.uri.toString() }, range };
|
2022-10-17 07:20:14 -05:00
|
|
|
return client.sendRequest(ra.syntaxTree, params, ct);
|
2020-05-25 05:02:30 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
get onDidChange(): vscode.Event<vscode.Uri> {
|
|
|
|
return this.eventEmitter.event;
|
|
|
|
}
|
|
|
|
})();
|
|
|
|
|
2022-10-17 08:05:20 -05:00
|
|
|
ctx.pushExtCleanup(new AstInspector(ctx));
|
2022-10-17 07:20:14 -05:00
|
|
|
ctx.pushExtCleanup(
|
2022-07-06 10:36:42 -05:00
|
|
|
vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-syntax-tree", tdcp)
|
|
|
|
);
|
2022-10-17 07:20:14 -05:00
|
|
|
ctx.pushExtCleanup(
|
2020-05-25 05:02:30 -05:00
|
|
|
vscode.languages.setLanguageConfiguration("ra_syntax_tree", {
|
|
|
|
brackets: [["[", ")"]],
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
return async () => {
|
|
|
|
const editor = vscode.window.activeTextEditor;
|
|
|
|
const rangeEnabled = !!editor && !editor.selection.isEmpty;
|
|
|
|
|
|
|
|
const uri = rangeEnabled ? vscode.Uri.parse(`${tdcp.uri.toString()}?range=true`) : tdcp.uri;
|
|
|
|
|
|
|
|
const document = await vscode.workspace.openTextDocument(uri);
|
|
|
|
|
|
|
|
tdcp.eventEmitter.fire(uri);
|
|
|
|
|
|
|
|
void (await vscode.window.showTextDocument(document, {
|
|
|
|
viewColumn: vscode.ViewColumn.Two,
|
|
|
|
preserveFocus: true,
|
|
|
|
}));
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-02-26 06:34:41 -06:00
|
|
|
function viewHirOrMir(ctx: CtxInit, xir: "hir" | "mir"): Cmd {
|
|
|
|
const viewXir = xir === "hir" ? "viewHir" : "viewMir";
|
|
|
|
const requestType = xir === "hir" ? ra.viewHir : ra.viewMir;
|
2023-04-28 12:14:30 -05:00
|
|
|
const uri = `rust-analyzer-${xir}://${viewXir}/${xir}.rs`;
|
|
|
|
const scheme = `rust-analyzer-${xir}`;
|
|
|
|
return viewFileUsingTextDocumentContentProvider(ctx, requestType, uri, scheme, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
function viewFileUsingTextDocumentContentProvider(
|
|
|
|
ctx: CtxInit,
|
|
|
|
requestType: lc.RequestType<lc.TextDocumentPositionParams, string, void>,
|
|
|
|
uri: string,
|
|
|
|
scheme: string,
|
|
|
|
shouldUpdate: boolean
|
|
|
|
): Cmd {
|
2020-12-28 12:29:58 -06:00
|
|
|
const tdcp = new (class implements vscode.TextDocumentContentProvider {
|
2023-04-28 12:14:30 -05:00
|
|
|
readonly uri = vscode.Uri.parse(uri);
|
2020-12-28 12:29:58 -06:00
|
|
|
readonly eventEmitter = new vscode.EventEmitter<vscode.Uri>();
|
|
|
|
constructor() {
|
|
|
|
vscode.workspace.onDidChangeTextDocument(
|
|
|
|
this.onDidChangeTextDocument,
|
|
|
|
this,
|
|
|
|
ctx.subscriptions
|
|
|
|
);
|
|
|
|
vscode.window.onDidChangeActiveTextEditor(
|
|
|
|
this.onDidChangeActiveTextEditor,
|
|
|
|
this,
|
|
|
|
ctx.subscriptions
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
private onDidChangeTextDocument(event: vscode.TextDocumentChangeEvent) {
|
2023-04-28 12:14:30 -05:00
|
|
|
if (isRustDocument(event.document) && shouldUpdate) {
|
2020-12-28 12:29:58 -06:00
|
|
|
// We need to order this after language server updates, but there's no API for that.
|
|
|
|
// Hence, good old sleep().
|
|
|
|
void sleep(10).then(() => this.eventEmitter.fire(this.uri));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private onDidChangeActiveTextEditor(editor: vscode.TextEditor | undefined) {
|
2023-04-28 12:14:30 -05:00
|
|
|
if (editor && isRustEditor(editor) && shouldUpdate) {
|
2020-12-28 12:29:58 -06:00
|
|
|
this.eventEmitter.fire(this.uri);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-17 07:20:14 -05:00
|
|
|
async provideTextDocumentContent(
|
2020-12-28 12:29:58 -06:00
|
|
|
_uri: vscode.Uri,
|
|
|
|
ct: vscode.CancellationToken
|
2022-10-17 07:20:14 -05:00
|
|
|
): Promise<string> {
|
2020-12-28 12:29:58 -06:00
|
|
|
const rustEditor = ctx.activeRustEditor;
|
2022-10-17 07:20:14 -05:00
|
|
|
if (!rustEditor) return "";
|
2020-12-28 12:29:58 -06:00
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
const client = ctx.client;
|
2020-12-28 12:29:58 -06:00
|
|
|
const params = {
|
|
|
|
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(
|
|
|
|
rustEditor.document
|
|
|
|
),
|
2021-03-15 09:49:20 -05:00
|
|
|
position: client.code2ProtocolConverter.asPosition(rustEditor.selection.active),
|
2020-12-28 12:29:58 -06:00
|
|
|
};
|
2023-02-26 06:34:41 -06:00
|
|
|
return client.sendRequest(requestType, params, ct);
|
2020-12-28 12:29:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
get onDidChange(): vscode.Event<vscode.Uri> {
|
|
|
|
return this.eventEmitter.event;
|
|
|
|
}
|
|
|
|
})();
|
|
|
|
|
2023-04-28 12:14:30 -05:00
|
|
|
ctx.pushExtCleanup(vscode.workspace.registerTextDocumentContentProvider(scheme, tdcp));
|
2022-03-31 07:50:33 -05:00
|
|
|
|
|
|
|
return async () => {
|
|
|
|
const document = await vscode.workspace.openTextDocument(tdcp.uri);
|
|
|
|
tdcp.eventEmitter.fire(tdcp.uri);
|
|
|
|
void (await vscode.window.showTextDocument(document, {
|
|
|
|
viewColumn: vscode.ViewColumn.Two,
|
|
|
|
preserveFocus: true,
|
|
|
|
}));
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-02-26 06:34:41 -06:00
|
|
|
// Opens the virtual file that will show the HIR of the function containing the cursor position
|
|
|
|
//
|
|
|
|
// The contents of the file come from the `TextDocumentContentProvider`
|
|
|
|
export function viewHir(ctx: CtxInit): Cmd {
|
|
|
|
return viewHirOrMir(ctx, "hir");
|
|
|
|
}
|
|
|
|
|
|
|
|
// Opens the virtual file that will show the MIR of the function containing the cursor position
|
|
|
|
//
|
|
|
|
// The contents of the file come from the `TextDocumentContentProvider`
|
|
|
|
export function viewMir(ctx: CtxInit): Cmd {
|
|
|
|
return viewHirOrMir(ctx, "mir");
|
|
|
|
}
|
|
|
|
|
2023-04-28 12:14:30 -05:00
|
|
|
// Opens the virtual file that will show the MIR of the function containing the cursor position
|
|
|
|
//
|
|
|
|
// The contents of the file come from the `TextDocumentContentProvider`
|
|
|
|
export function interpretFunction(ctx: CtxInit): Cmd {
|
|
|
|
const uri = `rust-analyzer-interpret-function://interpretFunction/result.log`;
|
|
|
|
return viewFileUsingTextDocumentContentProvider(
|
|
|
|
ctx,
|
|
|
|
ra.interpretFunction,
|
|
|
|
uri,
|
|
|
|
`rust-analyzer-interpret-function`,
|
|
|
|
false
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function viewFileText(ctx: CtxInit): Cmd {
|
2022-03-31 07:50:33 -05:00
|
|
|
const tdcp = new (class implements vscode.TextDocumentContentProvider {
|
2022-07-06 10:36:42 -05:00
|
|
|
readonly uri = vscode.Uri.parse("rust-analyzer-file-text://viewFileText/file.rs");
|
2022-03-31 07:50:33 -05:00
|
|
|
readonly eventEmitter = new vscode.EventEmitter<vscode.Uri>();
|
|
|
|
constructor() {
|
|
|
|
vscode.workspace.onDidChangeTextDocument(
|
|
|
|
this.onDidChangeTextDocument,
|
|
|
|
this,
|
|
|
|
ctx.subscriptions
|
|
|
|
);
|
|
|
|
vscode.window.onDidChangeActiveTextEditor(
|
|
|
|
this.onDidChangeActiveTextEditor,
|
|
|
|
this,
|
|
|
|
ctx.subscriptions
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
private onDidChangeTextDocument(event: vscode.TextDocumentChangeEvent) {
|
|
|
|
if (isRustDocument(event.document)) {
|
|
|
|
// We need to order this after language server updates, but there's no API for that.
|
|
|
|
// Hence, good old sleep().
|
|
|
|
void sleep(10).then(() => this.eventEmitter.fire(this.uri));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private onDidChangeActiveTextEditor(editor: vscode.TextEditor | undefined) {
|
|
|
|
if (editor && isRustEditor(editor)) {
|
|
|
|
this.eventEmitter.fire(this.uri);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-17 07:20:14 -05:00
|
|
|
async provideTextDocumentContent(
|
2022-03-31 07:50:33 -05:00
|
|
|
_uri: vscode.Uri,
|
|
|
|
ct: vscode.CancellationToken
|
2022-10-17 07:20:14 -05:00
|
|
|
): Promise<string> {
|
2022-03-31 07:50:33 -05:00
|
|
|
const rustEditor = ctx.activeRustEditor;
|
2022-10-17 07:20:14 -05:00
|
|
|
if (!rustEditor) return "";
|
2022-10-28 17:44:37 -05:00
|
|
|
const client = ctx.client;
|
2022-03-31 07:50:33 -05:00
|
|
|
|
|
|
|
const params = client.code2ProtocolConverter.asTextDocumentIdentifier(
|
|
|
|
rustEditor.document
|
|
|
|
);
|
|
|
|
return client.sendRequest(ra.viewFileText, params, ct);
|
|
|
|
}
|
|
|
|
|
|
|
|
get onDidChange(): vscode.Event<vscode.Uri> {
|
|
|
|
return this.eventEmitter.event;
|
|
|
|
}
|
|
|
|
})();
|
|
|
|
|
2022-10-17 07:20:14 -05:00
|
|
|
ctx.pushExtCleanup(
|
2022-07-06 10:36:42 -05:00
|
|
|
vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-file-text", tdcp)
|
|
|
|
);
|
2020-12-28 12:29:58 -06:00
|
|
|
|
|
|
|
return async () => {
|
2021-01-01 13:35:10 -06:00
|
|
|
const document = await vscode.workspace.openTextDocument(tdcp.uri);
|
|
|
|
tdcp.eventEmitter.fire(tdcp.uri);
|
2020-12-28 12:29:58 -06:00
|
|
|
void (await vscode.window.showTextDocument(document, {
|
|
|
|
viewColumn: vscode.ViewColumn.Two,
|
|
|
|
preserveFocus: true,
|
|
|
|
}));
|
|
|
|
};
|
|
|
|
}
|
2020-05-25 05:02:30 -05:00
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function viewItemTree(ctx: CtxInit): Cmd {
|
2021-05-21 16:59:52 -05:00
|
|
|
const tdcp = new (class implements vscode.TextDocumentContentProvider {
|
2022-07-06 10:36:42 -05:00
|
|
|
readonly uri = vscode.Uri.parse("rust-analyzer-item-tree://viewItemTree/itemtree.rs");
|
2021-05-21 16:59:52 -05:00
|
|
|
readonly eventEmitter = new vscode.EventEmitter<vscode.Uri>();
|
|
|
|
constructor() {
|
|
|
|
vscode.workspace.onDidChangeTextDocument(
|
|
|
|
this.onDidChangeTextDocument,
|
|
|
|
this,
|
|
|
|
ctx.subscriptions
|
|
|
|
);
|
|
|
|
vscode.window.onDidChangeActiveTextEditor(
|
|
|
|
this.onDidChangeActiveTextEditor,
|
|
|
|
this,
|
|
|
|
ctx.subscriptions
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
private onDidChangeTextDocument(event: vscode.TextDocumentChangeEvent) {
|
|
|
|
if (isRustDocument(event.document)) {
|
|
|
|
// We need to order this after language server updates, but there's no API for that.
|
|
|
|
// Hence, good old sleep().
|
|
|
|
void sleep(10).then(() => this.eventEmitter.fire(this.uri));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private onDidChangeActiveTextEditor(editor: vscode.TextEditor | undefined) {
|
|
|
|
if (editor && isRustEditor(editor)) {
|
|
|
|
this.eventEmitter.fire(this.uri);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-17 07:20:14 -05:00
|
|
|
async provideTextDocumentContent(
|
2021-05-21 16:59:52 -05:00
|
|
|
_uri: vscode.Uri,
|
|
|
|
ct: vscode.CancellationToken
|
2022-10-17 07:20:14 -05:00
|
|
|
): Promise<string> {
|
2021-05-21 16:59:52 -05:00
|
|
|
const rustEditor = ctx.activeRustEditor;
|
2022-10-17 07:20:14 -05:00
|
|
|
if (!rustEditor) return "";
|
2022-10-28 17:44:37 -05:00
|
|
|
const client = ctx.client;
|
2021-05-21 16:59:52 -05:00
|
|
|
|
|
|
|
const params = {
|
|
|
|
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(
|
|
|
|
rustEditor.document
|
|
|
|
),
|
|
|
|
};
|
|
|
|
return client.sendRequest(ra.viewItemTree, params, ct);
|
|
|
|
}
|
|
|
|
|
|
|
|
get onDidChange(): vscode.Event<vscode.Uri> {
|
|
|
|
return this.eventEmitter.event;
|
|
|
|
}
|
|
|
|
})();
|
|
|
|
|
2022-10-17 07:20:14 -05:00
|
|
|
ctx.pushExtCleanup(
|
2022-07-06 10:36:42 -05:00
|
|
|
vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-item-tree", tdcp)
|
|
|
|
);
|
2021-05-21 16:59:52 -05:00
|
|
|
|
|
|
|
return async () => {
|
|
|
|
const document = await vscode.workspace.openTextDocument(tdcp.uri);
|
|
|
|
tdcp.eventEmitter.fire(tdcp.uri);
|
|
|
|
void (await vscode.window.showTextDocument(document, {
|
|
|
|
viewColumn: vscode.ViewColumn.Two,
|
|
|
|
preserveFocus: true,
|
|
|
|
}));
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
function crateGraph(ctx: CtxInit, full: boolean): Cmd {
|
2021-05-11 09:15:31 -05:00
|
|
|
return async () => {
|
2021-08-09 12:45:42 -05:00
|
|
|
const nodeModulesPath = vscode.Uri.file(path.join(ctx.extensionPath, "node_modules"));
|
2021-08-06 12:14:47 -05:00
|
|
|
|
2021-08-10 08:34:30 -05:00
|
|
|
const panel = vscode.window.createWebviewPanel(
|
|
|
|
"rust-analyzer.crate-graph",
|
|
|
|
"rust-analyzer crate graph",
|
|
|
|
vscode.ViewColumn.Two,
|
|
|
|
{
|
|
|
|
enableScripts: true,
|
2021-08-10 08:35:37 -05:00
|
|
|
retainContextWhenHidden: true,
|
2021-08-09 12:45:42 -05:00
|
|
|
localResourceRoots: [nodeModulesPath],
|
2021-08-10 08:35:37 -05:00
|
|
|
}
|
|
|
|
);
|
2021-07-01 17:08:05 -05:00
|
|
|
const params = {
|
|
|
|
full: full,
|
|
|
|
};
|
2022-10-28 17:44:37 -05:00
|
|
|
const client = ctx.client;
|
2022-10-17 07:20:14 -05:00
|
|
|
const dot = await client.sendRequest(ra.viewCrateGraph, params);
|
2021-08-10 07:42:50 -05:00
|
|
|
const uri = panel.webview.asWebviewUri(nodeModulesPath);
|
2021-08-10 08:35:37 -05:00
|
|
|
|
2021-08-10 08:34:30 -05:00
|
|
|
const html = `
|
2021-08-09 02:01:42 -05:00
|
|
|
<!DOCTYPE html>
|
|
|
|
<meta charset="utf-8">
|
|
|
|
<head>
|
|
|
|
<style>
|
|
|
|
/* Fill the entire view */
|
|
|
|
html, body { margin:0; padding:0; overflow:hidden }
|
|
|
|
svg { position:fixed; top:0; left:0; height:100%; width:100% }
|
|
|
|
|
2022-08-17 08:44:58 -05:00
|
|
|
/* Disable the graphviz background and fill the polygons */
|
2021-08-09 02:01:42 -05:00
|
|
|
.graph > polygon { display:none; }
|
|
|
|
:is(.node,.edge) polygon { fill: white; }
|
|
|
|
|
|
|
|
/* Invert the line colours for dark themes */
|
|
|
|
body:not(.vscode-light) .edge path { stroke: white; }
|
|
|
|
</style>
|
|
|
|
</head>
|
|
|
|
<body>
|
2021-08-10 07:42:50 -05:00
|
|
|
<script type="text/javascript" src="${uri}/d3/dist/d3.min.js"></script>
|
2023-04-13 10:38:12 -05:00
|
|
|
<script type="text/javascript" src="${uri}/@hpcc-js/wasm/dist/graphviz.umd.js"></script>
|
2021-08-10 07:42:50 -05:00
|
|
|
<script type="text/javascript" src="${uri}/d3-graphviz/build/d3-graphviz.min.js"></script>
|
2021-08-09 02:01:42 -05:00
|
|
|
<div id="graph"></div>
|
|
|
|
<script>
|
2023-04-13 15:01:57 -05:00
|
|
|
let dot = \`${dot}\`;
|
2021-08-09 02:01:42 -05:00
|
|
|
let graph = d3.select("#graph")
|
2023-04-13 10:38:12 -05:00
|
|
|
.graphviz({ useWorker: false, useSharedWorker: false })
|
2021-08-09 02:01:42 -05:00
|
|
|
.fit(true)
|
|
|
|
.zoomScaleExtent([0.1, Infinity])
|
2023-04-13 15:01:57 -05:00
|
|
|
.renderDot(dot);
|
2021-08-09 02:01:42 -05:00
|
|
|
|
|
|
|
d3.select(window).on("click", (event) => {
|
|
|
|
if (event.ctrlKey) {
|
|
|
|
graph.resetZoom(d3.transition().duration(100));
|
|
|
|
}
|
|
|
|
});
|
2023-04-13 15:01:57 -05:00
|
|
|
d3.select(window).on("copy", (event) => {
|
|
|
|
event.clipboardData.setData("text/plain", dot);
|
|
|
|
event.preventDefault();
|
|
|
|
});
|
2021-08-09 02:01:42 -05:00
|
|
|
</script>
|
|
|
|
</body>
|
|
|
|
`;
|
2021-08-10 08:34:30 -05:00
|
|
|
|
|
|
|
panel.webview.html = html;
|
2021-05-11 09:15:31 -05:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function viewCrateGraph(ctx: CtxInit): Cmd {
|
2021-07-01 17:08:05 -05:00
|
|
|
return crateGraph(ctx, false);
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function viewFullCrateGraph(ctx: CtxInit): Cmd {
|
2021-07-01 17:08:05 -05:00
|
|
|
return crateGraph(ctx, true);
|
|
|
|
}
|
|
|
|
|
2020-05-25 04:10:31 -05:00
|
|
|
// Opens the virtual file that will show the syntax tree
|
|
|
|
//
|
|
|
|
// The contents of the file come from the `TextDocumentContentProvider`
|
2022-10-28 17:44:37 -05:00
|
|
|
export function expandMacro(ctx: CtxInit): Cmd {
|
2020-05-25 04:10:31 -05:00
|
|
|
function codeFormat(expanded: ra.ExpandedMacro): string {
|
2023-04-02 05:45:39 -05:00
|
|
|
let result = `// Recursive expansion of ${expanded.name} macro\n`;
|
2020-05-25 04:10:31 -05:00
|
|
|
result += "// " + "=".repeat(result.length - 3);
|
|
|
|
result += "\n\n";
|
|
|
|
result += expanded.expansion;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
const tdcp = new (class implements vscode.TextDocumentContentProvider {
|
2022-07-06 10:36:42 -05:00
|
|
|
uri = vscode.Uri.parse("rust-analyzer-expand-macro://expandMacro/[EXPANSION].rs");
|
2020-05-25 04:10:31 -05:00
|
|
|
eventEmitter = new vscode.EventEmitter<vscode.Uri>();
|
|
|
|
async provideTextDocumentContent(_uri: vscode.Uri): Promise<string> {
|
|
|
|
const editor = vscode.window.activeTextEditor;
|
2022-10-17 07:20:14 -05:00
|
|
|
if (!editor) return "";
|
2022-10-28 17:44:37 -05:00
|
|
|
const client = ctx.client;
|
2020-05-25 04:10:31 -05:00
|
|
|
|
|
|
|
const position = editor.selection.active;
|
|
|
|
|
|
|
|
const expanded = await client.sendRequest(ra.expandMacro, {
|
2022-10-17 07:20:14 -05:00
|
|
|
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(
|
2020-09-29 15:05:18 -05:00
|
|
|
editor.document
|
|
|
|
),
|
2020-05-25 04:10:31 -05:00
|
|
|
position,
|
|
|
|
});
|
|
|
|
|
|
|
|
if (expanded == null) return "Not available";
|
|
|
|
|
|
|
|
return codeFormat(expanded);
|
|
|
|
}
|
|
|
|
|
|
|
|
get onDidChange(): vscode.Event<vscode.Uri> {
|
|
|
|
return this.eventEmitter.event;
|
|
|
|
}
|
|
|
|
})();
|
|
|
|
|
2022-10-17 07:20:14 -05:00
|
|
|
ctx.pushExtCleanup(
|
2022-07-06 10:36:42 -05:00
|
|
|
vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-expand-macro", tdcp)
|
|
|
|
);
|
2020-05-25 04:10:31 -05:00
|
|
|
|
|
|
|
return async () => {
|
|
|
|
const document = await vscode.workspace.openTextDocument(tdcp.uri);
|
|
|
|
tdcp.eventEmitter.fire(tdcp.uri);
|
|
|
|
return vscode.window.showTextDocument(document, vscode.ViewColumn.Two, true);
|
|
|
|
};
|
|
|
|
}
|
2020-02-02 13:37:22 -06:00
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function reloadWorkspace(ctx: CtxInit): Cmd {
|
|
|
|
return async () => ctx.client.sendRequest(ra.reloadWorkspace);
|
2019-12-30 07:53:43 -06:00
|
|
|
}
|
|
|
|
|
2023-03-26 01:39:28 -05:00
|
|
|
export function rebuildProcMacros(ctx: CtxInit): Cmd {
|
|
|
|
return async () => ctx.client.sendRequest(ra.rebuildProcMacros);
|
2023-03-25 10:47:41 -05:00
|
|
|
}
|
|
|
|
|
2023-03-09 14:06:26 -06:00
|
|
|
export function addProject(ctx: CtxInit): Cmd {
|
|
|
|
return async () => {
|
|
|
|
const discoverProjectCommand = ctx.config.discoverProjectCommand;
|
|
|
|
if (!discoverProjectCommand) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-03-09 14:27:24 -06:00
|
|
|
const workspaces: JsonProject[] = await Promise.all(
|
2023-04-08 10:22:22 -05:00
|
|
|
vscode.workspace.textDocuments
|
|
|
|
.filter(isRustDocument)
|
|
|
|
.map(async (file): Promise<JsonProject> => {
|
|
|
|
return discoverWorkspace([file], discoverProjectCommand, {
|
|
|
|
cwd: path.dirname(file.uri.fsPath),
|
|
|
|
});
|
|
|
|
})
|
2023-03-09 14:27:24 -06:00
|
|
|
);
|
2023-03-09 14:06:26 -06:00
|
|
|
|
2023-03-10 18:35:05 -06:00
|
|
|
ctx.addToDiscoveredWorkspaces(workspaces);
|
|
|
|
|
|
|
|
// this is a workaround to avoid needing writing the `rust-project.json` into
|
|
|
|
// a workspace-level VS Code-specific settings folder. We'd like to keep the
|
|
|
|
// `rust-project.json` entirely in-memory.
|
|
|
|
await ctx.client?.sendNotification(lc.DidChangeConfigurationNotification.type, {
|
|
|
|
settings: "",
|
2023-03-09 14:06:26 -06:00
|
|
|
});
|
2023-03-09 14:27:24 -06:00
|
|
|
};
|
2023-03-09 14:06:26 -06:00
|
|
|
}
|
|
|
|
|
2021-02-27 11:04:43 -06:00
|
|
|
async function showReferencesImpl(
|
2022-10-17 07:20:14 -05:00
|
|
|
client: LanguageClient | undefined,
|
2021-02-27 11:04:43 -06:00
|
|
|
uri: string,
|
|
|
|
position: lc.Position,
|
|
|
|
locations: lc.Location[]
|
|
|
|
) {
|
|
|
|
if (client) {
|
|
|
|
await vscode.commands.executeCommand(
|
|
|
|
"editor.action.showReferences",
|
|
|
|
vscode.Uri.parse(uri),
|
|
|
|
client.protocol2CodeConverter.asPosition(position),
|
|
|
|
locations.map(client.protocol2CodeConverter.asLocation)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function showReferences(ctx: CtxInit): Cmd {
|
2021-02-09 08:12:46 -06:00
|
|
|
return async (uri: string, position: lc.Position, locations: lc.Location[]) => {
|
2022-10-28 17:44:37 -05:00
|
|
|
await showReferencesImpl(ctx.client, uri, position, locations);
|
2019-12-30 13:07:04 -06:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function applyActionGroup(_ctx: CtxInit): Cmd {
|
2020-11-10 11:20:01 -06:00
|
|
|
return async (actions: { label: string; arguments: lc.CodeAction }[]) => {
|
2020-05-22 10:29:55 -05:00
|
|
|
const selectedAction = await vscode.window.showQuickPick(actions);
|
|
|
|
if (!selectedAction) return;
|
2021-02-09 08:12:46 -06:00
|
|
|
await vscode.commands.executeCommand(
|
2020-06-02 15:21:48 -05:00
|
|
|
"rust-analyzer.resolveCodeAction",
|
|
|
|
selectedAction.arguments
|
2021-02-09 08:12:46 -06:00
|
|
|
);
|
2020-06-02 15:21:48 -05:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function gotoLocation(ctx: CtxInit): Cmd {
|
2020-06-10 15:01:19 -05:00
|
|
|
return async (locationLink: lc.LocationLink) => {
|
2022-10-28 17:44:37 -05:00
|
|
|
const client = ctx.client;
|
2022-10-17 07:20:14 -05:00
|
|
|
const uri = client.protocol2CodeConverter.asUri(locationLink.targetUri);
|
|
|
|
let range = client.protocol2CodeConverter.asRange(locationLink.targetSelectionRange);
|
|
|
|
// collapse the range to a cursor position
|
|
|
|
range = range.with({ end: range.start });
|
2020-06-10 15:01:19 -05:00
|
|
|
|
2022-10-17 07:20:14 -05:00
|
|
|
await vscode.window.showTextDocument(uri, { selection: range });
|
2020-06-10 15:01:19 -05:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function openDocs(ctx: CtxInit): Cmd {
|
2020-08-30 03:02:29 -05:00
|
|
|
return async () => {
|
|
|
|
const editor = vscode.window.activeTextEditor;
|
2022-10-17 07:20:14 -05:00
|
|
|
if (!editor) {
|
2020-09-03 02:55:24 -05:00
|
|
|
return;
|
2020-08-30 03:02:29 -05:00
|
|
|
}
|
2022-10-28 17:44:37 -05:00
|
|
|
const client = ctx.client;
|
2020-08-30 03:02:29 -05:00
|
|
|
|
|
|
|
const position = editor.selection.active;
|
|
|
|
const textDocument = { uri: editor.document.uri.toString() };
|
|
|
|
|
|
|
|
const doclink = await client.sendRequest(ra.openDocs, { position, textDocument });
|
|
|
|
|
2020-09-01 03:26:10 -05:00
|
|
|
if (doclink != null) {
|
2021-02-09 08:12:46 -06:00
|
|
|
await vscode.commands.executeCommand("vscode.open", vscode.Uri.parse(doclink));
|
2020-09-01 03:26:10 -05:00
|
|
|
}
|
2020-08-30 03:02:29 -05:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function cancelFlycheck(ctx: CtxInit): Cmd {
|
2022-08-19 01:52:31 -05:00
|
|
|
return async () => {
|
2022-12-17 16:29:25 -06:00
|
|
|
await ctx.client.sendNotification(ra.cancelFlycheck);
|
2022-12-16 15:43:14 -06:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-12-17 16:43:26 -06:00
|
|
|
export function clearFlycheck(ctx: CtxInit): Cmd {
|
|
|
|
return async () => {
|
|
|
|
await ctx.client.sendNotification(ra.clearFlycheck);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-12-16 15:43:14 -06:00
|
|
|
export function runFlycheck(ctx: CtxInit): Cmd {
|
|
|
|
return async () => {
|
|
|
|
const editor = ctx.activeRustEditor;
|
2022-10-28 17:44:37 -05:00
|
|
|
const client = ctx.client;
|
2022-12-16 15:43:14 -06:00
|
|
|
const params = editor ? { uri: editor.document.uri.toString() } : null;
|
|
|
|
|
|
|
|
await client.sendNotification(ra.runFlycheck, { textDocument: params });
|
2022-08-19 01:52:31 -05:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function resolveCodeAction(ctx: CtxInit): Cmd {
|
2020-11-10 11:20:01 -06:00
|
|
|
return async (params: lc.CodeAction) => {
|
2022-10-28 17:44:37 -05:00
|
|
|
const client = ctx.client;
|
2020-11-10 11:20:01 -06:00
|
|
|
params.command = undefined;
|
2022-12-16 15:43:14 -06:00
|
|
|
const item = await client.sendRequest(lc.CodeActionResolveRequest.type, params);
|
2022-10-17 07:20:14 -05:00
|
|
|
if (!item?.edit) {
|
2020-06-02 15:21:48 -05:00
|
|
|
return;
|
|
|
|
}
|
2020-12-29 08:43:17 -06:00
|
|
|
const itemEdit = item.edit;
|
2022-12-16 15:43:14 -06:00
|
|
|
const edit = await client.protocol2CodeConverter.asWorkspaceEdit(itemEdit);
|
2020-12-29 08:43:17 -06:00
|
|
|
// filter out all text edits and recreate the WorkspaceEdit without them so we can apply
|
|
|
|
// snippet edits on our own
|
2021-02-05 14:26:14 -06:00
|
|
|
const lcFileSystemEdit = {
|
|
|
|
...itemEdit,
|
|
|
|
documentChanges: itemEdit.documentChanges?.filter((change) => "kind" in change),
|
|
|
|
};
|
2022-04-08 06:24:28 -05:00
|
|
|
const fileSystemEdit = await client.protocol2CodeConverter.asWorkspaceEdit(
|
|
|
|
lcFileSystemEdit
|
|
|
|
);
|
2021-02-05 14:26:14 -06:00
|
|
|
await vscode.workspace.applyEdit(fileSystemEdit);
|
2020-12-29 08:43:17 -06:00
|
|
|
await applySnippetWorkspaceEdit(edit);
|
2022-04-19 11:37:18 -05:00
|
|
|
if (item.command != null) {
|
|
|
|
await vscode.commands.executeCommand(item.command.command, item.command.arguments);
|
|
|
|
}
|
2019-12-31 11:55:34 -06:00
|
|
|
};
|
2019-12-30 16:45:50 -06:00
|
|
|
}
|
2020-05-17 18:53:55 -05:00
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function applySnippetWorkspaceEditCommand(_ctx: CtxInit): Cmd {
|
2020-05-17 18:53:55 -05:00
|
|
|
return async (edit: vscode.WorkspaceEdit) => {
|
2020-05-21 07:26:44 -05:00
|
|
|
await applySnippetWorkspaceEdit(edit);
|
|
|
|
};
|
|
|
|
}
|
2020-06-02 07:33:47 -05:00
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function run(ctx: CtxInit): Cmd {
|
2020-06-02 07:33:47 -05:00
|
|
|
let prevRunnable: RunnableQuickPick | undefined;
|
|
|
|
|
|
|
|
return async () => {
|
|
|
|
const item = await selectRunnable(ctx, prevRunnable);
|
|
|
|
if (!item) return;
|
|
|
|
|
|
|
|
item.detail = "rerun";
|
|
|
|
prevRunnable = item;
|
2020-06-18 14:20:13 -05:00
|
|
|
const task = await createTask(item.runnable, ctx.config);
|
2020-06-02 07:33:47 -05:00
|
|
|
return await vscode.tasks.executeTask(task);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function peekTests(ctx: CtxInit): Cmd {
|
2021-02-27 11:04:43 -06:00
|
|
|
return async () => {
|
|
|
|
const editor = ctx.activeRustEditor;
|
2022-10-17 07:20:14 -05:00
|
|
|
if (!editor) return;
|
2022-10-28 17:44:37 -05:00
|
|
|
const client = ctx.client;
|
2021-02-27 11:04:43 -06:00
|
|
|
|
2021-02-27 12:07:23 -06:00
|
|
|
await vscode.window.withProgress(
|
|
|
|
{
|
|
|
|
location: vscode.ProgressLocation.Notification,
|
|
|
|
title: "Looking for tests...",
|
|
|
|
cancellable: false,
|
|
|
|
},
|
|
|
|
async (_progress, _token) => {
|
|
|
|
const uri = editor.document.uri.toString();
|
|
|
|
const position = client.code2ProtocolConverter.asPosition(editor.selection.active);
|
2022-05-17 12:15:06 -05:00
|
|
|
|
2021-02-27 12:07:23 -06:00
|
|
|
const tests = await client.sendRequest(ra.relatedTests, {
|
|
|
|
textDocument: { uri: uri },
|
|
|
|
position: position,
|
|
|
|
});
|
|
|
|
const locations: lc.Location[] = tests.map((it) =>
|
|
|
|
lc.Location.create(
|
|
|
|
it.runnable.location!.targetUri,
|
|
|
|
it.runnable.location!.targetSelectionRange
|
2022-05-17 12:15:06 -05:00
|
|
|
)
|
2021-02-27 12:07:23 -06:00
|
|
|
);
|
2022-05-17 12:15:06 -05:00
|
|
|
|
2021-02-27 12:07:23 -06:00
|
|
|
await showReferencesImpl(client, uri, position, locations);
|
|
|
|
}
|
|
|
|
);
|
2021-02-27 11:04:43 -06:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function runSingle(ctx: CtxInit): Cmd {
|
2020-06-02 07:33:47 -05:00
|
|
|
return async (runnable: ra.Runnable) => {
|
|
|
|
const editor = ctx.activeRustEditor;
|
|
|
|
if (!editor) return;
|
|
|
|
|
2020-06-18 14:20:13 -05:00
|
|
|
const task = await createTask(runnable, ctx.config);
|
2020-06-02 07:33:47 -05:00
|
|
|
task.group = vscode.TaskGroup.Build;
|
|
|
|
task.presentationOptions = {
|
|
|
|
reveal: vscode.TaskRevealKind.Always,
|
|
|
|
panel: vscode.TaskPanelKind.Dedicated,
|
|
|
|
clear: true,
|
|
|
|
};
|
|
|
|
|
|
|
|
return vscode.tasks.executeTask(task);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function copyRunCommandLine(ctx: CtxInit) {
|
2021-02-10 05:28:13 -06:00
|
|
|
let prevRunnable: RunnableQuickPick | undefined;
|
|
|
|
return async () => {
|
|
|
|
const item = await selectRunnable(ctx, prevRunnable);
|
|
|
|
if (!item) return;
|
|
|
|
const args = createArgs(item.runnable);
|
|
|
|
const commandLine = ["cargo", ...args].join(" ");
|
|
|
|
await vscode.env.clipboard.writeText(commandLine);
|
|
|
|
await vscode.window.showInformationMessage("Cargo invocation copied to the clipboard.");
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function debug(ctx: CtxInit): Cmd {
|
2020-06-02 07:33:47 -05:00
|
|
|
let prevDebuggee: RunnableQuickPick | undefined;
|
|
|
|
|
|
|
|
return async () => {
|
|
|
|
const item = await selectRunnable(ctx, prevDebuggee, true);
|
|
|
|
if (!item) return;
|
|
|
|
|
|
|
|
item.detail = "restart";
|
|
|
|
prevDebuggee = item;
|
|
|
|
return await startDebugSession(ctx, item.runnable);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function debugSingle(ctx: CtxInit): Cmd {
|
2020-06-02 07:33:47 -05:00
|
|
|
return async (config: ra.Runnable) => {
|
|
|
|
await startDebugSession(ctx, config);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-10-28 17:44:37 -05:00
|
|
|
export function newDebugConfig(ctx: CtxInit): Cmd {
|
2020-06-02 07:33:47 -05:00
|
|
|
return async () => {
|
|
|
|
const item = await selectRunnable(ctx, undefined, true, false);
|
|
|
|
if (!item) return;
|
|
|
|
|
|
|
|
await makeDebugConfig(ctx, item.runnable);
|
|
|
|
};
|
|
|
|
}
|
2022-05-16 13:53:00 -05:00
|
|
|
|
2022-10-17 07:20:14 -05:00
|
|
|
export function linkToCommand(_: Ctx): Cmd {
|
2022-05-16 13:53:00 -05:00
|
|
|
return async (commandId: string) => {
|
|
|
|
const link = LINKED_COMMANDS.get(commandId);
|
2022-10-17 07:20:14 -05:00
|
|
|
if (link) {
|
2022-05-16 13:53:00 -05:00
|
|
|
const { command, arguments: args = [] } = link;
|
|
|
|
await vscode.commands.executeCommand(command, ...args);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|