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.ts | 149 |
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\ + *  |-beches\ + *  |-src\ + *  |- ... + * - std + * 2. reveal every children of src: + * core + * alloc\ + *  |-beches\ + *  |-src\ + *   |- lib.rs\ + *   |- str.rs <------- FOUND IT!\ + *   |- ...\ + *  |- ...\ + * 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); |