support exception configuration
This commit is contained in:
Родитель
0b4141442b
Коммит
6d637b7689
|
@ -4,6 +4,7 @@
|
|||
!bin/Release/*
|
||||
!out/extension.js
|
||||
!node_modules/vscode-nls/**/*
|
||||
!node_modules/vscode-debugprotocol/**/*
|
||||
!package.json
|
||||
!package.nls.json
|
||||
!README.md
|
||||
|
|
43
package.json
43
package.json
|
@ -26,6 +26,7 @@
|
|||
"node": "^6.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"vscode-debugprotocol": "^1.17.0",
|
||||
"vscode-nls": "^2.0.2"
|
||||
},
|
||||
"repository": {
|
||||
|
@ -50,9 +51,40 @@
|
|||
},
|
||||
"main": "./out/extension",
|
||||
"activationEvents": [
|
||||
"onCommand:extension.mono-debug.configureExceptions"
|
||||
"onCommand:extension.mono-debug.configureExceptions",
|
||||
"onCommand:extension.mono-debug.startSession"
|
||||
],
|
||||
"contributes": {
|
||||
|
||||
"configuration": {
|
||||
"type": "object",
|
||||
"title": "Mono Debug Exception Configuration",
|
||||
"properties": {
|
||||
"mono-debug.exceptionOptions": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string",
|
||||
"enum": [ "never", "always", "unhandled", "userUnhandled" ],
|
||||
"enumDescriptions": [
|
||||
"never breaks",
|
||||
"breaks when exception handled or unhandled",
|
||||
"breaks when exception unhandled"
|
||||
],
|
||||
"description": "Possible conditions when a thrown exception should result in a break.",
|
||||
"default": "never"
|
||||
},
|
||||
"description": "Configuration options for exceptions",
|
||||
"default": {
|
||||
"System.Exception": "never",
|
||||
"System.SystemException": "never",
|
||||
"System.NullReferenceException": "always",
|
||||
"System.IndexOutOfRangeException": "unhandled",
|
||||
"System.ArithmeticException": "unhandled"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"commands": [
|
||||
{
|
||||
"command": "extension.mono-debug.configureExceptions",
|
||||
|
@ -60,6 +92,12 @@
|
|||
"category": "Debug"
|
||||
}
|
||||
],
|
||||
"keybindings": [
|
||||
{
|
||||
"command": "extension.mono-debug.configureExceptions",
|
||||
"key": "f3"
|
||||
}
|
||||
],
|
||||
"breakpoints": [
|
||||
{
|
||||
"language": "csharp"
|
||||
|
@ -79,6 +117,9 @@
|
|||
"runtime": "mono"
|
||||
},
|
||||
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
|
||||
|
||||
"startSessionCommand": "extension.mono-debug.startSession",
|
||||
|
||||
"initialConfigurations": [
|
||||
{
|
||||
"name": "%mono.launch.config.name%",
|
||||
|
|
|
@ -15,15 +15,6 @@ namespace VSCodeDebug
|
|||
{
|
||||
public class MonoDebugSession : DebugSession
|
||||
{
|
||||
|
||||
private readonly string[] EXCEPTIONS = new String[] {
|
||||
"System.Exception",
|
||||
"System.SystemException",
|
||||
"System.NullReferenceException",
|
||||
"System.IndexOutOfRangeException",
|
||||
"System.ArithmeticException"
|
||||
};
|
||||
|
||||
private const string MONO = "mono";
|
||||
private readonly string[] MONO_EXTENSIONS = new String[] {
|
||||
".cs", ".csx",
|
||||
|
@ -182,31 +173,19 @@ namespace VSCodeDebug
|
|||
supportsEvaluateForHovers = false,
|
||||
|
||||
// This debug adapter does not support exception breakpoint filters
|
||||
exceptionBreakpointFilters = exceptionFilters()
|
||||
exceptionBreakpointFilters = new dynamic[0]
|
||||
});
|
||||
|
||||
// Mono Debug is ready to accept breakpoints immediately
|
||||
SendEvent(new InitializedEvent());
|
||||
}
|
||||
|
||||
private object[] exceptionFilters()
|
||||
{
|
||||
var exceptions = new List<object>();
|
||||
|
||||
foreach (var e in EXCEPTIONS) {
|
||||
exceptions.Add(new {
|
||||
label = e,
|
||||
filter = e
|
||||
});
|
||||
}
|
||||
|
||||
return exceptions.ToArray();
|
||||
}
|
||||
|
||||
public override void Launch(Response response, dynamic args)
|
||||
{
|
||||
_attachMode = false;
|
||||
|
||||
SetExceptionBreakpoints(args.__exceptionOptions);
|
||||
|
||||
// validate argument 'program'
|
||||
string programPath = getString(args, "program");
|
||||
if (programPath == null) {
|
||||
|
@ -408,6 +387,8 @@ namespace VSCodeDebug
|
|||
{
|
||||
_attachMode = true;
|
||||
|
||||
SetExceptionBreakpoints(args.__exceptionOptions);
|
||||
|
||||
// validate argument 'address'
|
||||
var host = getString(args, "address");
|
||||
if (host == null) {
|
||||
|
@ -521,30 +502,7 @@ namespace VSCodeDebug
|
|||
|
||||
public override void SetExceptionBreakpoints(Response response, dynamic args)
|
||||
{
|
||||
// validate argument 'filters'
|
||||
string[] filters = null;
|
||||
if (args.filters != null) {
|
||||
filters = args.filters.ToObject<string[]>();
|
||||
if (filters != null && filters.Length == 0) {
|
||||
filters = null;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var cp in _catchpoints) {
|
||||
_session.Breakpoints.Remove(cp);
|
||||
}
|
||||
_catchpoints.Clear();
|
||||
|
||||
|
||||
if (filters != null) {
|
||||
foreach (var filter in filters) {
|
||||
_catchpoints.Add(_session.Breakpoints.AddCatchpoint(filter));
|
||||
}
|
||||
}
|
||||
|
||||
/** Configuration options for selected exceptions. */
|
||||
//exceptionOptions ?: ExceptionOptions[];
|
||||
|
||||
SetExceptionBreakpoints(args.exceptionOptions);
|
||||
SendResponse(response);
|
||||
}
|
||||
|
||||
|
@ -785,6 +743,42 @@ namespace VSCodeDebug
|
|||
|
||||
//---- private ------------------------------------------
|
||||
|
||||
private void SetExceptionBreakpoints(dynamic exceptionOptions)
|
||||
{
|
||||
if (exceptionOptions != null) {
|
||||
|
||||
// clear all existig catchpoints
|
||||
foreach (var cp in _catchpoints) {
|
||||
_session.Breakpoints.Remove(cp);
|
||||
}
|
||||
_catchpoints.Clear();
|
||||
|
||||
var exceptions = exceptionOptions.ToObject<dynamic[]>();
|
||||
for (int i = 0; i < exceptions.Length; i++) {
|
||||
|
||||
var exception = exceptions[i];
|
||||
|
||||
string exName = null;
|
||||
string exBreakMode = exception.breakMode;
|
||||
|
||||
if (exception.path != null) {
|
||||
var paths = exception.path.ToObject<dynamic[]>();
|
||||
var path = paths[0];
|
||||
if (path.names != null) {
|
||||
var names = path.names.ToObject<dynamic[]>();
|
||||
if (names.Length > 0) {
|
||||
exName = names[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (exName != null && exBreakMode == "always") {
|
||||
_catchpoints.Add(_session.Breakpoints.AddCatchpoint(exName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SendOutput(string category, string data) {
|
||||
if (!String.IsNullOrEmpty(data)) {
|
||||
if (data[data.Length-1] != '\n') {
|
||||
|
|
|
@ -6,28 +6,161 @@
|
|||
|
||||
import * as vscode from 'vscode';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { DebugProtocol } from 'vscode-debugprotocol';
|
||||
|
||||
const localize = nls.config(process.env.VSCODE_NLS_CONFIG)();
|
||||
|
||||
const configuration = vscode.workspace.getConfiguration('mono-debug');
|
||||
|
||||
export function activate(context: vscode.ExtensionContext) {
|
||||
context.subscriptions.push(vscode.commands.registerCommand('extension.mono-debug.configureExceptions', () => configureExceptions()));
|
||||
context.subscriptions.push(vscode.commands.registerCommand('extension.mono-debug.startSession', config => startSession(config)));
|
||||
}
|
||||
|
||||
export function deactivate() {
|
||||
}
|
||||
|
||||
//----- configureExceptions ---------------------------------------------------------------------------------------------------
|
||||
|
||||
// we store the exception configuration in the workspace or user settings as
|
||||
type ExceptionConfigurations = { [exception: string]: DebugProtocol.ExceptionBreakMode; };
|
||||
|
||||
// if the user has not configured anything, we populate the exception configurationwith these defaults
|
||||
const DEFAULT_EXCEPTIONS : ExceptionConfigurations = {
|
||||
"System.Exception": "never",
|
||||
"System.SystemException": "never",
|
||||
"System.NullReferenceException": "always",
|
||||
"System.IndexOutOfRangeException": "unhandled",
|
||||
"System.ArithmeticException": "unhandled"
|
||||
};
|
||||
|
||||
class BreakOptionItem implements vscode.QuickPickItem {
|
||||
label: string;
|
||||
description: string;
|
||||
breakMode: DebugProtocol.ExceptionBreakMode
|
||||
}
|
||||
|
||||
// the possible exception options converted into QuickPickItem
|
||||
const OPTIONS = ['never', 'always', 'unhandled', 'userUnhandled'].map<BreakOptionItem>((bm: DebugProtocol.ExceptionBreakMode) => {
|
||||
return {
|
||||
label: translate(bm),
|
||||
description: '',
|
||||
breakMode: bm
|
||||
}
|
||||
});
|
||||
|
||||
class ExceptionItem implements vscode.QuickPickItem {
|
||||
label: string;
|
||||
description: string;
|
||||
model: DebugProtocol.ExceptionOptions
|
||||
}
|
||||
|
||||
function translate(mode: DebugProtocol.ExceptionBreakMode) {
|
||||
switch (mode) {
|
||||
case 'never':
|
||||
return localize('breakmode.never', "Never break");
|
||||
case 'always':
|
||||
return localize('breakmode.always', "Always break");
|
||||
case 'unhandled':
|
||||
return localize('breakmode.unhandled', "Break when exception unhandled");
|
||||
case 'userUnhandled':
|
||||
return localize('breakmode.userUnhandled', "Break if exception is not handled by user code");
|
||||
}
|
||||
}
|
||||
|
||||
function getModel() {
|
||||
|
||||
let model = DEFAULT_EXCEPTIONS;
|
||||
if (configuration) {
|
||||
const exceptionOptions = configuration.get('exceptionOptions');
|
||||
if (exceptionOptions) {
|
||||
model = <ExceptionConfigurations> exceptionOptions;
|
||||
}
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
function configureExceptions() {
|
||||
|
||||
let options : vscode.QuickPickOptions = {
|
||||
placeHolder: localize('select.exception.category', "Select Exception Category"),
|
||||
const options: vscode.QuickPickOptions = {
|
||||
placeHolder: localize('select.exception', "First Select Exception"),
|
||||
matchOnDescription: true,
|
||||
matchOnDetail: true
|
||||
};
|
||||
|
||||
vscode.window.showQuickPick([ "Category 1", "Category 2", "Category 3" ], options).then(item => {
|
||||
if (item) {
|
||||
vscode.window.showInformationMessage(`Selected: ${item}`);
|
||||
const exceptionItems: vscode.QuickPickItem[] = [];
|
||||
const model = getModel();
|
||||
for (var exception in model) {
|
||||
exceptionItems.push({
|
||||
label: exception,
|
||||
description: translate(model[exception])
|
||||
});
|
||||
}
|
||||
|
||||
vscode.window.showQuickPick(exceptionItems, options).then(exceptionItem => {
|
||||
|
||||
if (exceptionItem) {
|
||||
|
||||
const options: vscode.QuickPickOptions = {
|
||||
placeHolder: localize('select.break.option', "Then Select Break Option"),
|
||||
matchOnDescription: true,
|
||||
matchOnDetail: true
|
||||
};
|
||||
|
||||
vscode.window.showQuickPick(OPTIONS, options).then(item => {
|
||||
if (item) {
|
||||
model[exceptionItem.label] = item.breakMode;
|
||||
if (configuration) {
|
||||
configuration.update('exceptionOptions', model);
|
||||
}
|
||||
setExceptionBreakpoints(model);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setExceptionBreakpoints(model: ExceptionConfigurations) : Thenable<DebugProtocol.SetExceptionBreakpointsResponse> {
|
||||
|
||||
const args: DebugProtocol.SetExceptionBreakpointsArguments = {
|
||||
filters: [],
|
||||
exceptionOptions: convertToExceptionOptions(model)
|
||||
}
|
||||
|
||||
return vscode.commands.executeCommand<DebugProtocol.SetExceptionBreakpointsResponse>('workbench.customDebugRequest', 'setExceptionBreakpoints', args);
|
||||
}
|
||||
|
||||
function convertToExceptionOptions(model: ExceptionConfigurations): DebugProtocol.ExceptionOptions[] {
|
||||
|
||||
const exceptionItems: DebugProtocol.ExceptionOptions[] = [];
|
||||
for (var exception in model) {
|
||||
exceptionItems.push({
|
||||
path: [ { names: [ exception ] } ],
|
||||
breakMode: model[exception]
|
||||
});
|
||||
}
|
||||
return exceptionItems;
|
||||
}
|
||||
|
||||
//----- configureExceptions ---------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The result type of the startSession command.
|
||||
*/
|
||||
class StartSessionResult {
|
||||
status: 'ok' | 'initialConfiguration' | 'saveConfiguration';
|
||||
content?: string; // launch.json content for 'save'
|
||||
};
|
||||
|
||||
function startSession(config: any): StartSessionResult {
|
||||
|
||||
if (config && !config.__exceptionOptions) {
|
||||
config.__exceptionOptions = convertToExceptionOptions(getModel());
|
||||
}
|
||||
|
||||
vscode.commands.executeCommand('vscode.startDebug', config);
|
||||
|
||||
return {
|
||||
status: 'ok'
|
||||
};
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче