Skip to content
This repository was archived by the owner on Oct 16, 2020. It is now read-only.

Commit 0759063

Browse files
add ChooseExceptionsDialog for PauseOnHandledException feature
1 parent 8bdceda commit 0759063

10 files changed

Lines changed: 250 additions & 3 deletions

File tree

data/resources/StringResources.resx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8204,4 +8204,16 @@ a line break</value>
82048204
<data name="Dialog.Options.IDEOptions.CodeCompletion.CommitOnTabEnterOnly" xml:space="preserve">
82058205
<value>Only insert selected code completion entry by typing &lt;Tab&gt; or &lt;Enter&gt;.</value>
82068206
</data>
8207+
<data name="Dialog.Options.IDEOptions.Debugging.ExceptionFilterTitle" xml:space="preserve">
8208+
<value>Choose exceptions you want the debugger to break on</value>
8209+
</data>
8210+
<data name="Dialog.Options.IDEOptions.Debugging.ExceptionFilter.ColumnIsActive" xml:space="preserve">
8211+
<value>Break on</value>
8212+
</data>
8213+
<data name="Dialog.Options.IDEOptions.Debugging.ExceptionFilter.ColumnExpression" xml:space="preserve">
8214+
<value>Exception name expression (wildcards are allowed)</value>
8215+
</data>
8216+
<data name="Dialog.Options.IDEOptions.Debugging.ChooseExceptions" xml:space="preserve">
8217+
<value>Choose exceptions</value>
8218+
</data>
82078219
</root>

src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,10 @@
105105
<Compile Include="Breakpoints\CurrentLineBookmark.cs" />
106106
<Compile Include="NRefactory\ExpressionEvaluationVisitor.cs" />
107107
<Compile Include="NRefactory\ExpressionExtensionMethods.cs" />
108+
<Compile Include="Options\ChooseExceptionsDialog.xaml.cs">
109+
<DependentUpon>ChooseExceptionsDialog.xaml</DependentUpon>
110+
<SubType>Code</SubType>
111+
</Compile>
108112
<Compile Include="Options\DebuggingOptionsPanel.xaml.cs">
109113
<DependentUpon>DebuggingOptionsPanel.xaml</DependentUpon>
110114
<SubType>Code</SubType>
@@ -319,6 +323,7 @@
319323
<Folder Include="Visualizers\TextVisualizer" />
320324
<Folder Include="Visualizers\Utils" />
321325
<Page Include="Breakpoints\BreakpointEditorPopup.xaml" />
326+
<Page Include="Options\ChooseExceptionsDialog.xaml" />
322327
<Page Include="Options\DebuggingOptionsPanel.xaml" />
323328
<Page Include="Options\DebuggingSymbolsPanel.xaml" />
324329
<Page Include="Pads\CommonResources.xaml" />
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<Window x:Class="Debugger.AddIn.Options.ChooseExceptionsDialog"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:core="http://icsharpcode.net/sharpdevelop/core"
5+
xmlns:AvalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"
6+
Title="{core:Localize Dialog.Options.IDEOptions.Debugging.ExceptionFilterTitle}" Height="400" Width="600"
7+
Style="{x:Static core:GlobalStyles.DialogWindowStyle}">
8+
9+
<Grid>
10+
<Grid.RowDefinitions>
11+
<RowDefinition />
12+
<RowDefinition Height="30" />
13+
</Grid.RowDefinitions>
14+
<Grid.ColumnDefinitions>
15+
<ColumnDefinition></ColumnDefinition>
16+
<ColumnDefinition Width="70"/>
17+
<ColumnDefinition Width="70"/>
18+
</Grid.ColumnDefinitions>
19+
<core:RestrictDesiredSize Grid.ColumnSpan="3">
20+
<DataGrid
21+
x:Name="dataGrid"
22+
SelectionMode="Single"
23+
CanUserAddRows="True"
24+
CanUserDeleteRows="True"
25+
SelectionUnit="FullRow"
26+
HeadersVisibility="Column"
27+
CanUserResizeRows="False"
28+
AutoGenerateColumns="False">
29+
<DataGrid.Columns>
30+
<DataGridCheckBoxColumn
31+
Header="{core:Localize Dialog.Options.IDEOptions.Debugging.ExceptionFilter.ColumnIsActive}"
32+
Binding="{Binding IsActive}" />
33+
<DataGridTextColumn
34+
Header="{core:Localize Dialog.Options.IDEOptions.Debugging.ExceptionFilter.ColumnExpression}"
35+
Width="*"
36+
Binding="{Binding Expression}" />
37+
</DataGrid.Columns>
38+
</DataGrid>
39+
</core:RestrictDesiredSize>
40+
41+
<Button Margin="0,3,5,3" Grid.Row="1" Grid.Column="1" IsDefault="True" Click="Button_Click" Content="{core:Localize Global.OKButtonText}"></Button>
42+
<Button Margin="0,3,5,3" Grid.Row="1" Grid.Column="2" IsCancel="True" Content="{core:Localize Global.CancelButtonText}"></Button>
43+
44+
</Grid>
45+
</Window>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4+
// software and associated documentation files (the "Software"), to deal in the Software
5+
// without restriction, including without limitation the rights to use, copy, modify, merge,
6+
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7+
// to whom the Software is furnished to do so, subject to the following conditions:
8+
//
9+
// The above copyright notice and this permission notice shall be included in all copies or
10+
// substantial portions of the Software.
11+
//
12+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13+
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14+
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15+
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17+
// DEALINGS IN THE SOFTWARE.
18+
19+
using System;
20+
using System.Collections.Generic;
21+
using System.Collections.ObjectModel;
22+
using System.Windows;
23+
using ICSharpCode.SharpDevelop.Gui;
24+
25+
namespace Debugger.AddIn.Options
26+
{
27+
/// <summary>
28+
/// Interaction logic for ChooseExceptionsDialog.xaml
29+
/// </summary>
30+
public partial class ChooseExceptionsDialog : Window
31+
{
32+
public ChooseExceptionsDialog(IEnumerable<ExceptionFilterEntry> entries)
33+
{
34+
InitializeComponent();
35+
36+
FormLocationHelper.ApplyWindow(this, "Debugger.ChooseExceptionsDialog", true);
37+
38+
ExceptionFilterList = new ObservableCollection<ExceptionFilterEntry>(entries);
39+
dataGrid.ItemsSource = ExceptionFilterList;
40+
}
41+
42+
public IList<ExceptionFilterEntry> ExceptionFilterList { get; set; }
43+
44+
void Button_Click(object sender, RoutedEventArgs e)
45+
{
46+
DialogResult = true;
47+
}
48+
}
49+
}

src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ public override bool PauseOnHandledExceptions {
8585
set { PS.Set<bool>("Debugger.PauseOnHandledExceptions", value); }
8686
}
8787

88+
public override IEnumerable<ExceptionFilterEntry> ExceptionFilterList {
89+
get { return PS.GetList<ExceptionFilterEntry>("Debugger.ExceptionFilterList"); }
90+
set { PS.SetList<ExceptionFilterEntry>("Debugger.ExceptionFilterList", value); }
91+
}
92+
8893
public bool AskForArguments {
8994
get { return PS.Get<bool>("Debugger.AskForArguments", false); }
9095
set { PS.Set<bool>("Debugger.AskForArguments", value); }

src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptionsPanel.xaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,12 @@
1919
<GroupBox Margin="5" Header="{sd:Localize Dialog.Options.IDEOptions.Debugging.Exceptions}">
2020
<widgets:StackPanelWithSpacing SpaceBetweenItems="5">
2121
<CheckBox Content="{sd:Localize Dialog.Options.IDEOptions.Debugging.PauseOnHandledExceptions}"
22+
x:Name="checkPauseOnHandled"
2223
IsChecked="{sd:OptionBinding debugger:DebuggingOptions.PauseOnHandledExceptions}" />
24+
<Button Content="{sd:Localize Dialog.Options.IDEOptions.Debugging.ChooseExceptions}"
25+
Click="ChooseExceptionsClick"
26+
HorizontalAlignment="Left"
27+
IsEnabled="{Binding IsChecked, ElementName=checkPauseOnHandled}" />
2328
</widgets:StackPanelWithSpacing>
2429
</GroupBox>
2530
<GroupBox Margin="5" Header="{sd:Localize Global.Advanced}">

src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptionsPanel.xaml.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
using System.Windows.Input;
2828
using System.Windows.Media;
2929

30+
using ICSharpCode.Core;
3031
using ICSharpCode.SharpDevelop.Gui;
3132
using ICSharpCode.SharpDevelop.Services;
3233

@@ -37,6 +38,8 @@ namespace Debugger.AddIn.Options
3738
/// </summary>
3839
public partial class DebuggingOptionsPanel : OptionPanel
3940
{
41+
IList<ExceptionFilterEntry> exceptionFilterList;
42+
4043
public DebuggingOptionsPanel()
4144
{
4245
InitializeComponent();
@@ -47,7 +50,26 @@ public override bool SaveOptions()
4750
bool result = base.SaveOptions();
4851
if (WindowsDebugger.CurrentDebugger != null)
4952
WindowsDebugger.CurrentDebugger.ReloadOptions();
53+
DebuggingOptions.Instance.ExceptionFilterList = exceptionFilterList;
5054
return result;
5155
}
56+
57+
public override void LoadOptions()
58+
{
59+
base.LoadOptions();
60+
exceptionFilterList = DebuggingOptions.Instance.ExceptionFilterList.ToList();
61+
62+
if (exceptionFilterList.Count == 0) {
63+
exceptionFilterList.Add(new ExceptionFilterEntry("*"));
64+
}
65+
}
66+
67+
void ChooseExceptionsClick(object sender, RoutedEventArgs e)
68+
{
69+
var dialog = new ChooseExceptionsDialog(exceptionFilterList);
70+
if (dialog.ShowDialog() == true) {
71+
exceptionFilterList = dialog.ExceptionFilterList;
72+
}
73+
}
5274
}
5375
}

src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@
1919
using System;
2020
using System.Collections.Generic;
2121
using System.Diagnostics;
22+
using System.Linq;
2223
using System.Runtime.InteropServices;
24+
using System.Text;
25+
using System.Text.RegularExpressions;
26+
using ICSharpCode.NRefactory.TypeSystem;
2327
using Debugger.Interop;
2428
using Debugger.Interop.CorDebug;
2529

@@ -540,19 +544,62 @@ public void Exception2(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, I
540544

541545
ExceptionType exceptionType = (ExceptionType)_exceptionType;
542546
bool pauseOnHandled = !process.Evaluating && process.Options != null && process.Options.PauseOnHandledExceptions;
547+
Thread thread = process.GetThread(pThread);
543548

544-
if (exceptionType == ExceptionType.Unhandled || (pauseOnHandled && exceptionType == ExceptionType.CatchHandlerFound)) {
549+
if (exceptionType == ExceptionType.Unhandled || (pauseOnHandled && exceptionType == ExceptionType.CatchHandlerFound && BreakOnException(thread))) {
545550

546551
// Multiple exceptions can happen at the same time on multiple threads
547552
// (I have managed to create a test application to trigger it)
548-
Thread thread = process.GetThread(pThread);
549553
thread.CurrentExceptionType = exceptionType;
550554
RequestPause(thread).ExceptionsThrown.Add(thread);
551555
}
552556

553557
ExitCallback();
554558
}
559+
560+
Regex filterRegex;
561+
562+
static string ConvertWildcardsToRegex(string searchPattern)
563+
{
564+
if (string.IsNullOrEmpty(searchPattern))
565+
return "";
566+
567+
StringBuilder builder = new StringBuilder();
568+
569+
foreach (char ch in searchPattern) {
570+
switch (ch) {
571+
case '?':
572+
builder.Append(".");
573+
break;
574+
case '*':
575+
builder.Append(".*");
576+
break;
577+
default:
578+
builder.Append(Regex.Escape(ch.ToString()));
579+
break;
580+
}
581+
}
582+
583+
return builder.ToString();
584+
}
555585

586+
bool BreakOnException(Thread thread)
587+
{
588+
IType exceptionType = thread.CurrentException.Type;
589+
590+
if (filterRegex == null) {
591+
var exceptionFilterList = thread.Process.Options.ExceptionFilterList.Where(i => i.IsActive).Select(s => "(" + ConvertWildcardsToRegex(s.Expression) + ")");
592+
filterRegex = new Regex(string.Join("|", exceptionFilterList), RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ExplicitCapture);
593+
}
594+
595+
foreach (var baseType in exceptionType.GetNonInterfaceBaseTypes()) {
596+
if (filterRegex.IsMatch(baseType.ReflectionName))
597+
return true;
598+
}
599+
600+
return false;
601+
}
602+
556603
public void ExceptionUnwind(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, CorDebugExceptionUnwindCallbackType dwEventType, uint dwFlags)
557604
{
558605
EnterCallback("ExceptionUnwind", pThread);

src/AddIns/Debugger/Debugger.Core/Options.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
using System;
2020
using System.Collections.Generic;
21+
using System.ComponentModel;
2122

2223
namespace Debugger
2324
{
@@ -32,5 +33,57 @@ public class Options
3233
public virtual bool StepOverFieldAccessProperties { get; set; }
3334
public virtual IEnumerable<string> SymbolsSearchPaths { get; set; }
3435
public virtual bool PauseOnHandledExceptions { get; set; }
36+
public virtual IEnumerable<ExceptionFilterEntry> ExceptionFilterList { get; set; }
37+
}
38+
39+
[Serializable]
40+
public class ExceptionFilterEntry : INotifyPropertyChanged
41+
{
42+
string expression;
43+
bool isActive;
44+
45+
public ExceptionFilterEntry()
46+
{
47+
this.IsActive = true;
48+
}
49+
50+
public ExceptionFilterEntry(string expression)
51+
{
52+
this.IsActive = true;
53+
this.Expression = expression;
54+
}
55+
56+
public event PropertyChangedEventHandler PropertyChanged;
57+
58+
protected virtual void OnPropertyChanged(string propertyName)
59+
{
60+
var propertyChanged = PropertyChanged;
61+
if (propertyChanged != null)
62+
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
63+
}
64+
65+
public string Expression {
66+
get {
67+
return expression;
68+
}
69+
set {
70+
if (expression != value) {
71+
expression = value;
72+
OnPropertyChanged("Expression");
73+
}
74+
}
75+
}
76+
77+
public bool IsActive {
78+
get {
79+
return isActive;
80+
}
81+
set {
82+
if (isActive != value) {
83+
isActive = value;
84+
OnPropertyChanged("IsActive");
85+
}
86+
}
87+
}
3588
}
3689
}

src/Main/Base/Project/Debugging/IDebuggerService.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
using System.Diagnostics;
2121
using System.Linq;
2222
using ICSharpCode.Core;
23+
using ICSharpCode.NRefactory;
2324
using ICSharpCode.SharpDevelop.Editor;
2425
using ICSharpCode.SharpDevelop.Gui;
2526
using ICSharpCode.SharpDevelop.Project;
@@ -217,11 +218,14 @@ public bool StepOverFieldAccessProperties {
217218
get { return false; }
218219
}
219220
public IEnumerable<string> SymbolsSearchPaths {
220-
get { return Enumerable.Empty<string>(); }
221+
get { return EmptyList<string>.Instance; }
221222
}
222223
public bool PauseOnHandledExceptions {
223224
get { return false; }
224225
}
226+
public IEnumerable<string> ExceptionFilterList {
227+
get { return EmptyList<string>.Instance; }
228+
}
225229

226230
public static readonly DummyDebuggerOptions Instance = new DummyDebuggerOptions();
227231
}

0 commit comments

Comments
 (0)