Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'editors/code/src/commands.ts')
-rw-r--r--editors/code/src/commands.ts149
1 files changed, 131 insertions, 18 deletions
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index 8a953577e9..98ccd50dc0 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -8,10 +8,18 @@ import { applySnippetWorkspaceEdit, applySnippetTextEdits } from "./snippets";
import { spawnSync } from "child_process";
import { RunnableQuickPick, selectRunnable, createTask, createArgs } from "./run";
import { AstInspector } from "./ast_inspector";
-import { isRustDocument, isCargoTomlDocument, sleep, isRustEditor } from "./util";
+import {
+ isRustDocument,
+ isCargoTomlDocument,
+ sleep,
+ isRustEditor,
+ RustEditor,
+ RustDocument,
+} from "./util";
import { startDebugSession, makeDebugConfig } from "./debug";
import { LanguageClient } from "vscode-languageclient/node";
import { LINKED_COMMANDS } from "./client";
+import { DependencyId } from "./dependencies_provider";
export * from "./ast_inspector";
export * from "./run";
@@ -89,7 +97,13 @@ export function shuffleCrateGraph(ctx: CtxInit): Cmd {
export function triggerParameterHints(_: CtxInit): Cmd {
return async () => {
- await vscode.commands.executeCommand("editor.action.triggerParameterHints");
+ const parameterHintsEnabled = vscode.workspace
+ .getConfiguration("editor")
+ .get<boolean>("parameterHints.enabled");
+
+ if (parameterHintsEnabled) {
+ await vscode.commands.executeCommand("editor.action.triggerParameterHints");
+ }
};
}
@@ -260,6 +274,71 @@ export function openCargoToml(ctx: CtxInit): Cmd {
};
}
+export function revealDependency(ctx: CtxInit): Cmd {
+ return async (editor: RustEditor) => {
+ if (!ctx.dependencies?.isInitialized()) {
+ return;
+ }
+ const documentPath = editor.document.uri.fsPath;
+ const dep = ctx.dependencies?.getDependency(documentPath);
+ if (dep) {
+ await ctx.treeView?.reveal(dep, { select: true, expand: true });
+ } else {
+ await revealParentChain(editor.document, ctx);
+ }
+ };
+}
+
+/**
+ * This function calculates the parent chain of a given file until it reaches it crate root contained in ctx.dependencies.
+ * This is need because the TreeView is Lazy, so at first it only has the root dependencies: For example if we have the following crates:
+ * - core
+ * - alloc
+ * - std
+ *
+ * if I want to reveal alloc/src/str.rs, I have to:
+
+ * 1. reveal every children of alloc
+ * - core
+ * - alloc\
+ * &emsp;|-beches\
+ * &emsp;|-src\
+ * &emsp;|- ...
+ * - std
+ * 2. reveal every children of src:
+ * core
+ * alloc\
+ * &emsp;|-beches\
+ * &emsp;|-src\
+ * &emsp;&emsp;|- lib.rs\
+ * &emsp;&emsp;|- str.rs <------- FOUND IT!\
+ * &emsp;&emsp;|- ...\
+ * &emsp;|- ...\
+ * std
+ */
+async function revealParentChain(document: RustDocument, ctx: CtxInit) {
+ let documentPath = document.uri.fsPath;
+ const maxDepth = documentPath.split(path.sep).length - 1;
+ const parentChain: DependencyId[] = [{ id: documentPath.toLowerCase() }];
+ do {
+ documentPath = path.dirname(documentPath);
+ parentChain.push({ id: documentPath.toLowerCase() });
+ if (parentChain.length >= maxDepth) {
+ // this is an odd case that can happen when we change a crate version but we'd still have
+ // a open file referencing the old version
+ return;
+ }
+ } while (!ctx.dependencies?.contains(documentPath));
+ parentChain.reverse();
+ for (const idx in parentChain) {
+ await ctx.treeView?.reveal(parentChain[idx], { select: true, expand: true });
+ }
+}
+
+export async function execRevealDependency(e: RustEditor): Promise<void> {
+ await vscode.commands.executeCommand("rust-analyzer.revealDependency", e);
+}
+
export function ssr(ctx: CtxInit): Cmd {
return async () => {
const editor = vscode.window.activeTextEditor;
@@ -416,8 +495,20 @@ export function syntaxTree(ctx: CtxInit): Cmd {
function viewHirOrMir(ctx: CtxInit, xir: "hir" | "mir"): Cmd {
const viewXir = xir === "hir" ? "viewHir" : "viewMir";
const requestType = xir === "hir" ? ra.viewHir : ra.viewMir;
+ 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 {
const tdcp = new (class implements vscode.TextDocumentContentProvider {
- readonly uri = vscode.Uri.parse(`rust-analyzer-${xir}://${viewXir}/${xir}.rs`);
+ readonly uri = vscode.Uri.parse(uri);
readonly eventEmitter = new vscode.EventEmitter<vscode.Uri>();
constructor() {
vscode.workspace.onDidChangeTextDocument(
@@ -433,14 +524,14 @@ function viewHirOrMir(ctx: CtxInit, xir: "hir" | "mir"): Cmd {
}
private onDidChangeTextDocument(event: vscode.TextDocumentChangeEvent) {
- if (isRustDocument(event.document)) {
+ if (isRustDocument(event.document) && shouldUpdate) {
// 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)) {
+ if (editor && isRustEditor(editor) && shouldUpdate) {
this.eventEmitter.fire(this.uri);
}
}
@@ -467,9 +558,7 @@ function viewHirOrMir(ctx: CtxInit, xir: "hir" | "mir"): Cmd {
}
})();
- ctx.pushExtCleanup(
- vscode.workspace.registerTextDocumentContentProvider(`rust-analyzer-${xir}`, tdcp)
- );
+ ctx.pushExtCleanup(vscode.workspace.registerTextDocumentContentProvider(scheme, tdcp));
return async () => {
const document = await vscode.workspace.openTextDocument(tdcp.uri);
@@ -495,6 +584,20 @@ export function viewMir(ctx: CtxInit): Cmd {
return viewHirOrMir(ctx, "mir");
}
+// 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
+ );
+}
+
export function viewFileText(ctx: CtxInit): Cmd {
const tdcp = new (class implements vscode.TextDocumentContentProvider {
readonly uri = vscode.Uri.parse("rust-analyzer-file-text://viewFileText/file.rs");
@@ -663,21 +766,26 @@ function crateGraph(ctx: CtxInit, full: boolean): Cmd {
</head>
<body>
<script type="text/javascript" src="${uri}/d3/dist/d3.min.js"></script>
- <script type="text/javascript" src="${uri}/@hpcc-js/wasm/dist/index.min.js"></script>
+ <script type="text/javascript" src="${uri}/@hpcc-js/wasm/dist/graphviz.umd.js"></script>
<script type="text/javascript" src="${uri}/d3-graphviz/build/d3-graphviz.min.js"></script>
<div id="graph"></div>
<script>
+ let dot = \`${dot}\`;
let graph = d3.select("#graph")
- .graphviz()
+ .graphviz({ useWorker: false, useSharedWorker: false })
.fit(true)
.zoomScaleExtent([0.1, Infinity])
- .renderDot(\`${dot}\`);
+ .renderDot(dot);
d3.select(window).on("click", (event) => {
if (event.ctrlKey) {
graph.resetZoom(d3.transition().duration(100));
}
});
+ d3.select(window).on("copy", (event) => {
+ event.clipboardData.setData("text/plain", dot);
+ event.preventDefault();
+ });
</script>
</body>
`;
@@ -699,7 +807,7 @@ export function viewFullCrateGraph(ctx: CtxInit): Cmd {
// The contents of the file come from the `TextDocumentContentProvider`
export function expandMacro(ctx: CtxInit): Cmd {
function codeFormat(expanded: ra.ExpandedMacro): string {
- let result = `// Recursive expansion of ${expanded.name}! macro\n`;
+ let result = `// Recursive expansion of ${expanded.name} macro\n`;
result += "// " + "=".repeat(result.length - 3);
result += "\n\n";
result += expanded.expansion;
@@ -749,6 +857,10 @@ export function reloadWorkspace(ctx: CtxInit): Cmd {
return async () => ctx.client.sendRequest(ra.reloadWorkspace);
}
+export function rebuildProcMacros(ctx: CtxInit): Cmd {
+ return async () => ctx.client.sendRequest(ra.rebuildProcMacros);
+}
+
export function addProject(ctx: CtxInit): Cmd {
return async () => {
const discoverProjectCommand = ctx.config.discoverProjectCommand;
@@ -757,12 +869,13 @@ export function addProject(ctx: CtxInit): Cmd {
}
const workspaces: JsonProject[] = await Promise.all(
- vscode.workspace.workspaceFolders!.map(async (folder): Promise<JsonProject> => {
- const rustDocuments = vscode.workspace.textDocuments.filter(isRustDocument);
- return discoverWorkspace(rustDocuments, discoverProjectCommand, {
- cwd: folder.uri.fsPath,
- });
- })
+ vscode.workspace.textDocuments
+ .filter(isRustDocument)
+ .map(async (file): Promise<JsonProject> => {
+ return discoverWorkspace([file], discoverProjectCommand, {
+ cwd: path.dirname(file.uri.fsPath),
+ });
+ })
);
ctx.addToDiscoveredWorkspaces(workspaces);