Skip to content
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
2 changes: 1 addition & 1 deletion .deslop.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# agent-pmo:a72c926
[threshold]
max_duplication_percent = 11
max_duplication_percent = 10

[defaults]
exclude = [
Expand Down
14 changes: 5 additions & 9 deletions src/editors/vscode/src/profiler-diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as vscode from 'vscode';
import { type LanguageClient } from 'vscode-languageclient/node';
import { escapeHtml, getErrorMessage } from './utils.js';
import { ObjectGraphPanel } from './profiler-graph.js';
import { pickDumpFile } from './profiler-prompts.js';

// ── LSP types ─────────────────────────────────────────────────────

Expand Down Expand Up @@ -449,23 +450,18 @@ export async function detectLeaksWorkflow(
}

/** The one `.dmp` file the user picks for `which` side, or undefined on cancel. */
async function pickDump(which: 'BASELINE' | 'COMPARISON'): Promise<vscode.Uri | undefined> {
const picked = await vscode.window.showOpenDialog({
canSelectMany: false,
filters: { 'Dump files': ['dmp'] },
title: `Select ${which} dump file`,
});
return picked?.[0];
async function pickDump(which: 'BASELINE' | 'COMPARISON'): Promise<string | undefined> {
return await pickDumpFile(`Select ${which} dump file`);
}

/** Pick the comparison dump, then open the diff of `baseline` against it. */
async function diffAgainst(
baseline: vscode.Uri,
baseline: string,
context: vscode.ExtensionContext,
client: LanguageClient,
): Promise<void> {
const comparison = await pickDump('COMPARISON');
if (comparison !== undefined) {
await HeapDiffPanel.open(baseline.fsPath, comparison.fsPath, context, client);
await HeapDiffPanel.open(baseline, comparison, context, client);
}
}
22 changes: 7 additions & 15 deletions src/editors/vscode/src/profiler-graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import * as vscode from 'vscode';
import { type LanguageClient } from 'vscode-languageclient/node';
import { getErrorMessage } from './utils.js';
import { askObjectAddress, pickDumpFile } from './profiler-prompts.js';

interface ObjectGraphNode {
readonly id: string;
Expand Down Expand Up @@ -112,20 +113,11 @@ export async function promptAndOpenGraph(
context: vscode.ExtensionContext,
client: LanguageClient,
): Promise<void> {
const dumpFiles = await vscode.window.showOpenDialog({
canSelectMany: false,
filters: { 'Dump files': ['dmp'] },
title: 'Select memory dump file for object graph',
});
const selectedFile = dumpFiles?.[0];
if (selectedFile === undefined) return;

const rootAddress = await vscode.window.showInputBox({
prompt: 'Enter the root object address (hex, e.g. 00007ff812345678)',
placeHolder: '00007ff812345678',
validateInput: (v) => (v.trim().length > 0 ? undefined : 'Address is required'),
});
const dumpPath = await pickDumpFile('Select memory dump file for object graph');
if (dumpPath === undefined) return;
const rootAddress = await askObjectAddress(
'Enter the root object address (hex, e.g. 00007ff812345678)',
);
if (rootAddress === undefined) return;

await ObjectGraphPanel.open(selectedFile.fsPath, rootAddress.trim(), context, client);
await ObjectGraphPanel.open(dumpPath, rootAddress.trim(), context, client);
}
36 changes: 36 additions & 0 deletions src/editors/vscode/src/profiler-prompts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// The dialogs the profiler commands share: pick a file, ask for an object
// address, and show a plain-text report. Each resolves `undefined` when the
// user cancels, so a command can simply stop.
import * as vscode from 'vscode';

/** The one file the user picks in an Open dialog, or `undefined` on cancel. */
export async function pickOneFile(
filters: Record<string, string[]>,
title: string,
): Promise<string | undefined> {
const picked = await vscode.window.showOpenDialog({ canSelectMany: false, filters, title });
return picked?.[0]?.fsPath;
}

/** A memory dump (`.dmp`) the user picks, or `undefined` on cancel. */
export async function pickDumpFile(title = 'Select memory dump file'): Promise<string | undefined> {
return await pickOneFile({ 'Dump files': ['dmp'] }, title);
}

/** A non-empty object address (hex) the user types, or `undefined` on cancel. */
export async function askObjectAddress(prompt: string): Promise<string | undefined> {
return await vscode.window.showInputBox({
prompt,
placeHolder: '00007ff812345678',
validateInput: (v) => (v.trim().length > 0 ? undefined : 'Address is required'),
});
}

/** Show `lines` as a plain-text preview document. */
export async function showPlainText(lines: readonly string[]): Promise<void> {
const doc = await vscode.workspace.openTextDocument({
content: lines.join('\n'),
language: 'plaintext',
});
await vscode.window.showTextDocument(doc, { preview: true });
}
Loading
Loading