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.ts386
1 files changed, 336 insertions, 50 deletions
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index 98ccd50dc0..e21f536f26 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -3,23 +3,24 @@ import * as lc from "vscode-languageclient";
import * as ra from "./lsp_ext";
import * as path from "path";
-import { Ctx, Cmd, CtxInit, discoverWorkspace } from "./ctx";
+import { type Ctx, type Cmd, type CtxInit, discoverWorkspace } from "./ctx";
import { applySnippetWorkspaceEdit, applySnippetTextEdits } from "./snippets";
import { spawnSync } from "child_process";
-import { RunnableQuickPick, selectRunnable, createTask, createArgs } from "./run";
+import { type RunnableQuickPick, selectRunnable, createTask, createArgs } from "./run";
import { AstInspector } from "./ast_inspector";
import {
isRustDocument,
isCargoTomlDocument,
sleep,
isRustEditor,
- RustEditor,
- RustDocument,
+ type RustEditor,
+ type RustDocument,
} from "./util";
import { startDebugSession, makeDebugConfig } from "./debug";
-import { LanguageClient } from "vscode-languageclient/node";
+import type { LanguageClient } from "vscode-languageclient/node";
import { LINKED_COMMANDS } from "./client";
-import { DependencyId } from "./dependencies_provider";
+import type { DependencyId } from "./dependencies_provider";
+import { unwrapUndefinable } from "./undefinable";
export * from "./ast_inspector";
export * from "./run";
@@ -47,7 +48,7 @@ export function analyzerStatus(ctx: CtxInit): Cmd {
})();
ctx.pushExtCleanup(
- vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-status", tdcp)
+ vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-status", tdcp),
);
return async () => {
@@ -79,7 +80,7 @@ export function memoryUsage(ctx: CtxInit): Cmd {
})();
ctx.pushExtCleanup(
- vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-memory", tdcp)
+ vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-memory", tdcp),
);
return async () => {
@@ -125,11 +126,12 @@ export function matchingBrace(ctx: CtxInit): Cmd {
const response = await client.sendRequest(ra.matchingBrace, {
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document),
positions: editor.selections.map((s) =>
- client.code2ProtocolConverter.asPosition(s.active)
+ client.code2ProtocolConverter.asPosition(s.active),
),
});
editor.selections = editor.selections.map((sel, idx) => {
- const active = client.protocol2CodeConverter.asPosition(response[idx]);
+ const position = unwrapUndefinable(response[idx]);
+ const active = client.protocol2CodeConverter.asPosition(position);
const anchor = sel.isEmpty ? active : sel.anchor;
return new vscode.Selection(anchor, active);
});
@@ -194,7 +196,7 @@ export function onEnter(ctx: CtxInit): Cmd {
const lcEdits = await client
.sendRequest(ra.onEnter, {
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(
- editor.document
+ editor.document,
),
position: client.code2ProtocolConverter.asPosition(editor.selection.active),
})
@@ -231,7 +233,7 @@ export function parentModule(ctx: CtxInit): Cmd {
if (!locations) return;
if (locations.length === 1) {
- const loc = locations[0];
+ const loc = unwrapUndefinable(locations[0]);
const uri = client.protocol2CodeConverter.asUri(loc.targetUri);
const range = client.protocol2CodeConverter.asRange(loc.targetRange);
@@ -247,7 +249,7 @@ export function parentModule(ctx: CtxInit): Cmd {
client,
uri,
position,
- locations.map((loc) => lc.Location.create(loc.targetUri, loc.targetRange))
+ locations.map((loc) => lc.Location.create(loc.targetUri, loc.targetRange)),
);
}
};
@@ -331,7 +333,13 @@ async function revealParentChain(document: RustDocument, ctx: CtxInit) {
} while (!ctx.dependencies?.contains(documentPath));
parentChain.reverse();
for (const idx in parentChain) {
- await ctx.treeView?.reveal(parentChain[idx], { select: true, expand: true });
+ const treeView = ctx.treeView;
+ if (!treeView) {
+ continue;
+ }
+
+ const dependency = unwrapUndefinable(parentChain[idx]);
+ await treeView.reveal(dependency, { select: true, expand: true });
}
}
@@ -349,7 +357,7 @@ export function ssr(ctx: CtxInit): Cmd {
const position = editor.selection.active;
const selections = editor.selections;
const textDocument = client.code2ProtocolConverter.asTextDocumentIdentifier(
- editor.document
+ editor.document,
);
const options: vscode.InputBoxOptions = {
@@ -365,7 +373,7 @@ export function ssr(ctx: CtxInit): Cmd {
selections,
});
} catch (e) {
- return e.toString();
+ return String(e);
}
return null;
},
@@ -389,9 +397,9 @@ export function ssr(ctx: CtxInit): Cmd {
});
await vscode.workspace.applyEdit(
- await client.protocol2CodeConverter.asWorkspaceEdit(edit, token)
+ await client.protocol2CodeConverter.asWorkspaceEdit(edit, token),
);
- }
+ },
);
};
}
@@ -420,12 +428,12 @@ export function syntaxTree(ctx: CtxInit): Cmd {
vscode.workspace.onDidChangeTextDocument(
this.onDidChangeTextDocument,
this,
- ctx.subscriptions
+ ctx.subscriptions,
);
vscode.window.onDidChangeActiveTextEditor(
this.onDidChangeActiveTextEditor,
this,
- ctx.subscriptions
+ ctx.subscriptions,
);
}
@@ -444,7 +452,7 @@ export function syntaxTree(ctx: CtxInit): Cmd {
async provideTextDocumentContent(
uri: vscode.Uri,
- ct: vscode.CancellationToken
+ ct: vscode.CancellationToken,
): Promise<string> {
const rustEditor = ctx.activeRustEditor;
if (!rustEditor) return "";
@@ -467,12 +475,12 @@ export function syntaxTree(ctx: CtxInit): Cmd {
ctx.pushExtCleanup(new AstInspector(ctx));
ctx.pushExtCleanup(
- vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-syntax-tree", tdcp)
+ vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-syntax-tree", tdcp),
);
ctx.pushExtCleanup(
vscode.languages.setLanguageConfiguration("ra_syntax_tree", {
brackets: [["[", ")"]],
- })
+ }),
);
return async () => {
@@ -505,7 +513,7 @@ function viewFileUsingTextDocumentContentProvider(
requestType: lc.RequestType<lc.TextDocumentPositionParams, string, void>,
uri: string,
scheme: string,
- shouldUpdate: boolean
+ shouldUpdate: boolean,
): Cmd {
const tdcp = new (class implements vscode.TextDocumentContentProvider {
readonly uri = vscode.Uri.parse(uri);
@@ -514,12 +522,12 @@ function viewFileUsingTextDocumentContentProvider(
vscode.workspace.onDidChangeTextDocument(
this.onDidChangeTextDocument,
this,
- ctx.subscriptions
+ ctx.subscriptions,
);
vscode.window.onDidChangeActiveTextEditor(
this.onDidChangeActiveTextEditor,
this,
- ctx.subscriptions
+ ctx.subscriptions,
);
}
@@ -538,7 +546,7 @@ function viewFileUsingTextDocumentContentProvider(
async provideTextDocumentContent(
_uri: vscode.Uri,
- ct: vscode.CancellationToken
+ ct: vscode.CancellationToken,
): Promise<string> {
const rustEditor = ctx.activeRustEditor;
if (!rustEditor) return "";
@@ -546,7 +554,7 @@ function viewFileUsingTextDocumentContentProvider(
const client = ctx.client;
const params = {
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(
- rustEditor.document
+ rustEditor.document,
),
position: client.code2ProtocolConverter.asPosition(rustEditor.selection.active),
};
@@ -594,7 +602,7 @@ export function interpretFunction(ctx: CtxInit): Cmd {
ra.interpretFunction,
uri,
`rust-analyzer-interpret-function`,
- false
+ false,
);
}
@@ -606,12 +614,12 @@ export function viewFileText(ctx: CtxInit): Cmd {
vscode.workspace.onDidChangeTextDocument(
this.onDidChangeTextDocument,
this,
- ctx.subscriptions
+ ctx.subscriptions,
);
vscode.window.onDidChangeActiveTextEditor(
this.onDidChangeActiveTextEditor,
this,
- ctx.subscriptions
+ ctx.subscriptions,
);
}
@@ -630,14 +638,14 @@ export function viewFileText(ctx: CtxInit): Cmd {
async provideTextDocumentContent(
_uri: vscode.Uri,
- ct: vscode.CancellationToken
+ ct: vscode.CancellationToken,
): Promise<string> {
const rustEditor = ctx.activeRustEditor;
if (!rustEditor) return "";
const client = ctx.client;
const params = client.code2ProtocolConverter.asTextDocumentIdentifier(
- rustEditor.document
+ rustEditor.document,
);
return client.sendRequest(ra.viewFileText, params, ct);
}
@@ -648,7 +656,7 @@ export function viewFileText(ctx: CtxInit): Cmd {
})();
ctx.pushExtCleanup(
- vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-file-text", tdcp)
+ vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-file-text", tdcp),
);
return async () => {
@@ -669,12 +677,12 @@ export function viewItemTree(ctx: CtxInit): Cmd {
vscode.workspace.onDidChangeTextDocument(
this.onDidChangeTextDocument,
this,
- ctx.subscriptions
+ ctx.subscriptions,
);
vscode.window.onDidChangeActiveTextEditor(
this.onDidChangeActiveTextEditor,
this,
- ctx.subscriptions
+ ctx.subscriptions,
);
}
@@ -693,7 +701,7 @@ export function viewItemTree(ctx: CtxInit): Cmd {
async provideTextDocumentContent(
_uri: vscode.Uri,
- ct: vscode.CancellationToken
+ ct: vscode.CancellationToken,
): Promise<string> {
const rustEditor = ctx.activeRustEditor;
if (!rustEditor) return "";
@@ -701,7 +709,7 @@ export function viewItemTree(ctx: CtxInit): Cmd {
const params = {
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(
- rustEditor.document
+ rustEditor.document,
),
};
return client.sendRequest(ra.viewItemTree, params, ct);
@@ -713,7 +721,7 @@ export function viewItemTree(ctx: CtxInit): Cmd {
})();
ctx.pushExtCleanup(
- vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-item-tree", tdcp)
+ vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-item-tree", tdcp),
);
return async () => {
@@ -738,7 +746,7 @@ function crateGraph(ctx: CtxInit, full: boolean): Cmd {
enableScripts: true,
retainContextWhenHidden: true,
localResourceRoots: [nodeModulesPath],
- }
+ },
);
const params = {
full: full,
@@ -827,7 +835,7 @@ export function expandMacro(ctx: CtxInit): Cmd {
const expanded = await client.sendRequest(ra.expandMacro, {
textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(
- editor.document
+ editor.document,
),
position,
});
@@ -843,7 +851,7 @@ export function expandMacro(ctx: CtxInit): Cmd {
})();
ctx.pushExtCleanup(
- vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-expand-macro", tdcp)
+ vscode.workspace.registerTextDocumentContentProvider("rust-analyzer-expand-macro", tdcp),
);
return async () => {
@@ -875,7 +883,7 @@ export function addProject(ctx: CtxInit): Cmd {
return discoverWorkspace([file], discoverProjectCommand, {
cwd: path.dirname(file.uri.fsPath),
});
- })
+ }),
);
ctx.addToDiscoveredWorkspaces(workspaces);
@@ -893,14 +901,14 @@ async function showReferencesImpl(
client: LanguageClient | undefined,
uri: string,
position: lc.Position,
- locations: lc.Location[]
+ 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)
+ locations.map(client.protocol2CodeConverter.asLocation),
);
}
}
@@ -917,7 +925,7 @@ export function applyActionGroup(_ctx: CtxInit): Cmd {
if (!selectedAction) return;
await vscode.commands.executeCommand(
"rust-analyzer.resolveCodeAction",
- selectedAction.arguments
+ selectedAction.arguments,
);
};
}
@@ -992,7 +1000,7 @@ export function resolveCodeAction(ctx: CtxInit): Cmd {
documentChanges: itemEdit.documentChanges?.filter((change) => "kind" in change),
};
const fileSystemEdit = await client.protocol2CodeConverter.asWorkspaceEdit(
- lcFileSystemEdit
+ lcFileSystemEdit,
);
await vscode.workspace.applyEdit(fileSystemEdit);
await applySnippetWorkspaceEdit(edit);
@@ -1045,12 +1053,12 @@ export function peekTests(ctx: CtxInit): Cmd {
const locations: lc.Location[] = tests.map((it) =>
lc.Location.create(
it.runnable.location!.targetUri,
- it.runnable.location!.targetSelectionRange
- )
+ it.runnable.location!.targetSelectionRange,
+ ),
);
await showReferencesImpl(client, uri, position, locations);
- }
+ },
);
};
}
@@ -1121,3 +1129,281 @@ export function linkToCommand(_: Ctx): Cmd {
}
};
}
+
+export function viewMemoryLayout(ctx: CtxInit): Cmd {
+ return async () => {
+ const editor = vscode.window.activeTextEditor;
+ if (!editor) return;
+ const client = ctx.client;
+
+ const position = editor.selection.active;
+ const expanded = await client.sendRequest(ra.viewRecursiveMemoryLayout, {
+ textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(editor.document),
+ position,
+ });
+
+ const document = vscode.window.createWebviewPanel(
+ "memory_layout",
+ "[Memory Layout]",
+ vscode.ViewColumn.Two,
+ { enableScripts: true },
+ );
+
+ document.webview.html = `<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Document</title>
+ <style>
+ * {
+ box-sizing: border-box;
+ }
+
+ body {
+ margin: 0;
+ overflow: hidden;
+ min-height: 100%;
+ height: 100vh;
+ padding: 32px;
+ position: relative;
+ display: block;
+
+ background-color: var(--vscode-editor-background);
+ font-family: var(--vscode-editor-font-family);
+ font-size: var(--vscode-editor-font-size);
+ color: var(--vscode-editor-foreground);
+ }
+
+ .container {
+ position: relative;
+ }
+
+ .trans {
+ transition: all 0.2s ease-in-out;
+ }
+
+ .grid {
+ height: 100%;
+ position: relative;
+ color: var(--vscode-commandCenter-activeBorder);
+ pointer-events: none;
+ }
+
+ .grid-line {
+ position: absolute;
+ width: 100%;
+ height: 1px;
+ background-color: var(--vscode-commandCenter-activeBorder);
+ }
+
+ #tooltip {
+ position: fixed;
+ display: none;
+ z-index: 1;
+ pointer-events: none;
+ padding: 4px 8px;
+ z-index: 2;
+
+ color: var(--vscode-editorHoverWidget-foreground);
+ background-color: var(--vscode-editorHoverWidget-background);
+ border: 1px solid var(--vscode-editorHoverWidget-border);
+ }
+
+ #tooltip b {
+ color: var(--vscode-editorInlayHint-typeForeground);
+ }
+
+ #tooltip ul {
+ margin-left: 0;
+ padding-left: 20px;
+ }
+
+ table {
+ position: absolute;
+ transform: rotateZ(90deg) rotateX(180deg);
+ transform-origin: top left;
+ border-collapse: collapse;
+ table-layout: fixed;
+ left: 48px;
+ top: 0;
+ max-height: calc(100vw - 64px - 48px);
+ z-index: 1;
+ }
+
+ td {
+ border: 1px solid var(--vscode-focusBorder);
+ writing-mode: vertical-rl;
+ text-orientation: sideways-right;
+
+ height: 80px;
+ }
+
+ td p {
+ height: calc(100% - 16px);
+ width: calc(100% - 8px);
+ margin: 8px 4px;
+ display: inline-block;
+ transform: rotateY(180deg);
+ pointer-events: none;
+ overflow: hidden;
+ }
+
+ td p * {
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ display: inline-block;
+ height: 100%;
+ }
+
+ td p b {
+ color: var(--vscode-editorInlayHint-typeForeground);
+ }
+
+ td:hover {
+ background-color: var(--vscode-editor-hoverHighlightBackground);
+ }
+
+ td:empty {
+ visibility: hidden;
+ border: 0;
+ }
+ </style>
+</head>
+<body>
+ <div id="tooltip"></div>
+</body>
+<script>(function() {
+
+const data = ${JSON.stringify(expanded)}
+
+if (!(data && data.nodes.length)) {
+ document.body.innerText = "Not Available"
+ return
+}
+
+data.nodes.map(n => {
+ n.typename = n.typename.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', ' & quot; ').replaceAll("'", '&#039;')
+ return n
+})
+
+let height = window.innerHeight - 64
+
+addEventListener("resize", e => {
+ const new_height = window.innerHeight - 64
+ height = new_height
+ container.classList.remove("trans")
+ table.classList.remove("trans")
+ locate()
+ setTimeout(() => { // give delay to redraw, annoying but needed
+ container.classList.add("trans")
+ table.classList.add("trans")
+ }, 0)
+})
+
+const container = document.createElement("div")
+container.classList.add("container")
+container.classList.add("trans")
+document.body.appendChild(container)
+
+const tooltip = document.getElementById("tooltip")
+
+let y = 0
+let zoom = 1.0
+
+const table = document.createElement("table")
+table.classList.add("trans")
+container.appendChild(table)
+const rows = []
+
+function node_t(idx, depth, offset) {
+ if (!rows[depth]) {
+ rows[depth] = { el: document.createElement("tr"), offset: 0 }
+ }
+
+ if (rows[depth].offset < offset) {
+ const pad = document.createElement("td")
+ pad.colSpan = offset - rows[depth].offset
+ rows[depth].el.appendChild(pad)
+ rows[depth].offset += offset - rows[depth].offset
+ }
+
+ const td = document.createElement("td")
+ td.innerHTML = '<p><span>' + data.nodes[idx].itemName + ':</span> <b>' + data.nodes[idx].typename + '</b></p>'
+
+ td.colSpan = data.nodes[idx].size
+
+ td.addEventListener("mouseover", e => {
+ const node = data.nodes[idx]
+ tooltip.innerHTML = node.itemName + ": <b>" + node.typename + "</b><br/>"
+ + "<ul>"
+ + "<li>size = " + node.size + "</li>"
+ + "<li>align = " + node.alignment + "</li>"
+ + "<li>field offset = " + node.offset + "</li>"
+ + "</ul>"
+ + "<i>double click to focus</i>"
+
+ tooltip.style.display = "block"
+ })
+ td.addEventListener("mouseleave", _ => tooltip.style.display = "none")
+ const total_offset = rows[depth].offset
+ td.addEventListener("dblclick", e => {
+ const node = data.nodes[idx]
+ zoom = data.nodes[0].size / node.size
+ y = -(total_offset) / data.nodes[0].size * zoom
+ x = 0
+ locate()
+ })
+
+ rows[depth].el.appendChild(td)
+ rows[depth].offset += data.nodes[idx].size
+
+
+ if (data.nodes[idx].childrenStart != -1) {
+ for (let i = 0; i < data.nodes[idx].childrenLen; i++) {
+ if (data.nodes[data.nodes[idx].childrenStart + i].size) {
+ node_t(data.nodes[idx].childrenStart + i, depth + 1, offset + data.nodes[data.nodes[idx].childrenStart + i].offset)
+ }
+ }
+ }
+}
+
+node_t(0, 0, 0)
+
+for (const row of rows) table.appendChild(row.el)
+
+const grid = document.createElement("div")
+grid.classList.add("grid")
+container.appendChild(grid)
+
+for (let i = 0; i < data.nodes[0].size / 8 + 1; i++) {
+ const el = document.createElement("div")
+ el.classList.add("grid-line")
+ el.style.top = (i / (data.nodes[0].size / 8) * 100) + "%"
+ el.innerText = i * 8
+ grid.appendChild(el)
+}
+
+addEventListener("mousemove", e => {
+ tooltip.style.top = e.clientY + 10 + "px"
+ tooltip.style.left = e.clientX + 10 + "px"
+})
+
+function locate() {
+ container.style.top = height * y + "px"
+ container.style.height = (height * zoom) + "px"
+
+ table.style.width = container.style.height
+}
+
+locate()
+
+})()
+</script>
+</html>`;
+
+ ctx.pushExtCleanup(document);
+ };
+}