Skip to content

Add command to manage breakpoint exception types in command palette #1566

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@
"command": "java.debug.pauseOthers",
"title": "Pause Others"
},
{
"command": "java.debug.breakpoints.exceptionTypes",
"title": "Debug: Breakpoint Exception Types..."
},
{
"command": "java.debug.variables.showHex",
"title": "Show as Hex"
Expand Down
122 changes: 122 additions & 0 deletions src/breakpointCommands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import * as vscode from "vscode";

export function registerBreakpointCommands(context: vscode.ExtensionContext): void {
context.subscriptions.push(vscode.commands.registerCommand('java.debug.breakpoints.exceptionTypes', exceptionTypes));
}

async function exceptionTypes() {
const config = vscode.workspace.getConfiguration('java.debug.settings.exceptionBreakpoint');
let currentTypes = config.get<string[]>('exceptionTypes', []);
const addExceptionTypeItem: vscode.QuickPickItem = {
label: '$(add) Add Exception Types...',
alwaysShow: true,
};
const removeExceptionTypeItem: any = (type: string): any => ({
label: type,
buttons: [{
iconPath: new vscode.ThemeIcon('close'),
tooltip: 'Remove this Exception Type'
}]
});

// Step 1: Show Breakpoint Exception Types
const pickStep = async (state: any) => {
return new Promise<any>((resolve) => {
const items: vscode.QuickPickItem[] = [
addExceptionTypeItem,
...currentTypes.map(type => removeExceptionTypeItem(type))
];
const quickPick = vscode.window.createQuickPick();
quickPick.items = items;
quickPick.title = 'Breakpoint Exception Types';
quickPick.canSelectMany = false;
quickPick.matchOnDescription = false;
quickPick.matchOnDetail = false;

quickPick.onDidAccept(() => {
const selected = quickPick.selectedItems[0];
if (selected.label.includes('Add Exception Types')) {
quickPick.hide();
// go to next step
resolve(state);
}
});

quickPick.onDidTriggerItemButton(async (e) => {
const typeToRemove = e.item.label;
currentTypes = currentTypes.filter(type => type !== typeToRemove);
await config.update('exceptionTypes', currentTypes, vscode.ConfigurationTarget.Global);
quickPick.items = [
addExceptionTypeItem,
...currentTypes.map(type => removeExceptionTypeItem(type))
];
});
quickPick.onDidHide(() => {
quickPick.dispose();
});
quickPick.show();
});
};

// Step 2: Add Exception Type(s)
const inputStep = async (state: any) => {
return new Promise<any>((resolve, reject) => {
const input = vscode.window.createInputBox();
input.title = 'Add Breakpoint Exception Type(s)';
input.placeholder = 'Enter exception type(s) (comma or space separated)';
input.prompt = 'Input exception types';
input.buttons = [vscode.QuickInputButtons.Back];
input.onDidAccept(async () => {
const exceptionType = input.value;
if (exceptionType) {
const types = exceptionType.split(/[,\s]+/).map(type => type.trim()).filter(type => type.length > 0);
let updated = false;
for (const type of types) {
if (!currentTypes.includes(type)) {
currentTypes.push(type);
updated = true;
}
}
if (updated) {
await config.update('exceptionTypes', currentTypes, vscode.ConfigurationTarget.Global);
}
}
input.hide();
// go back to pick step
resolve(state);
});
input.onDidTriggerButton((btn) => {
if (btn === vscode.QuickInputButtons.Back) {
input.hide();
reject({ stepBack: true });
}
});
input.onDidHide(() => {
input.dispose();
});
input.show();
});
};

while (true) {
await multiStepInput([pickStep, inputStep], {});
}
}

async function multiStepInput<T>(steps: Array<(input: T) => Promise<T>>, initial: T): Promise<T> {
let state = initial;
let currentStep = 0;
while (currentStep < steps.length) {
try {
state = await steps[currentStep](state);
currentStep++;
} catch (err) {
if (err?.stepBack) {
if (currentStep > 0) currentStep--;
} else {
throw err;
}
}
}
return state;
}
2 changes: 2 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { progressProvider } from "./progressImpl";
import { JavaTerminalLinkProvder } from "./terminalLinkProvider";
import { initializeThreadOperations } from "./threadOperations";
import * as utility from "./utility";
import { registerBreakpointCommands } from "./breakpointCommands";
import { registerVariableMenuCommands } from "./variableMenu";
import { promisify } from "util";

Expand All @@ -36,6 +37,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<any> {

function initializeExtension(_operationId: string, context: vscode.ExtensionContext): any {
registerDebugEventListener(context);
registerBreakpointCommands(context);
registerVariableMenuCommands(context);
context.subscriptions.push(vscode.window.registerTerminalLinkProvider(new JavaTerminalLinkProvder()));
context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider("java", new JavaDebugConfigurationProvider()));
Expand Down