Browse Source

add ChooseExceptionsDialog for PauseOnHandledException feature

pull/517/head
Siegfried Pammer 11 years ago
parent
commit
0759063d55
  1. 12
      data/resources/StringResources.resx
  2. 5
      src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj
  3. 45
      src/AddIns/Debugger/Debugger.AddIn/Options/ChooseExceptionsDialog.xaml
  4. 49
      src/AddIns/Debugger/Debugger.AddIn/Options/ChooseExceptionsDialog.xaml.cs
  5. 5
      src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs
  6. 5
      src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptionsPanel.xaml
  7. 22
      src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptionsPanel.xaml.cs
  8. 51
      src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs
  9. 53
      src/AddIns/Debugger/Debugger.Core/Options.cs
  10. 6
      src/Main/Base/Project/Debugging/IDebuggerService.cs

12
data/resources/StringResources.resx

@ -8204,4 +8204,16 @@ a line break</value> @@ -8204,4 +8204,16 @@ a line break</value>
<data name="Dialog.Options.IDEOptions.CodeCompletion.CommitOnTabEnterOnly" xml:space="preserve">
<value>Only insert selected code completion entry by typing &lt;Tab&gt; or &lt;Enter&gt;.</value>
</data>
<data name="Dialog.Options.IDEOptions.Debugging.ExceptionFilterTitle" xml:space="preserve">
<value>Choose exceptions you want the debugger to break on</value>
</data>
<data name="Dialog.Options.IDEOptions.Debugging.ExceptionFilter.ColumnIsActive" xml:space="preserve">
<value>Break on</value>
</data>
<data name="Dialog.Options.IDEOptions.Debugging.ExceptionFilter.ColumnExpression" xml:space="preserve">
<value>Exception name expression (wildcards are allowed)</value>
</data>
<data name="Dialog.Options.IDEOptions.Debugging.ChooseExceptions" xml:space="preserve">
<value>Choose exceptions</value>
</data>
</root>

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

@ -105,6 +105,10 @@ @@ -105,6 +105,10 @@
<Compile Include="Breakpoints\CurrentLineBookmark.cs" />
<Compile Include="NRefactory\ExpressionEvaluationVisitor.cs" />
<Compile Include="NRefactory\ExpressionExtensionMethods.cs" />
<Compile Include="Options\ChooseExceptionsDialog.xaml.cs">
<DependentUpon>ChooseExceptionsDialog.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Options\DebuggingOptionsPanel.xaml.cs">
<DependentUpon>DebuggingOptionsPanel.xaml</DependentUpon>
<SubType>Code</SubType>
@ -319,6 +323,7 @@ @@ -319,6 +323,7 @@
<Folder Include="Visualizers\TextVisualizer" />
<Folder Include="Visualizers\Utils" />
<Page Include="Breakpoints\BreakpointEditorPopup.xaml" />
<Page Include="Options\ChooseExceptionsDialog.xaml" />
<Page Include="Options\DebuggingOptionsPanel.xaml" />
<Page Include="Options\DebuggingSymbolsPanel.xaml" />
<Page Include="Pads\CommonResources.xaml" />

45
src/AddIns/Debugger/Debugger.AddIn/Options/ChooseExceptionsDialog.xaml

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
<Window x:Class="Debugger.AddIn.Options.ChooseExceptionsDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:core="http://icsharpcode.net/sharpdevelop/core"
xmlns:AvalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit"
Title="{core:Localize Dialog.Options.IDEOptions.Debugging.ExceptionFilterTitle}" Height="400" Width="600"
Style="{x:Static core:GlobalStyles.DialogWindowStyle}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="70"/>
</Grid.ColumnDefinitions>
<core:RestrictDesiredSize Grid.ColumnSpan="3">
<DataGrid
x:Name="dataGrid"
SelectionMode="Single"
CanUserAddRows="True"
CanUserDeleteRows="True"
SelectionUnit="FullRow"
HeadersVisibility="Column"
CanUserResizeRows="False"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridCheckBoxColumn
Header="{core:Localize Dialog.Options.IDEOptions.Debugging.ExceptionFilter.ColumnIsActive}"
Binding="{Binding IsActive}" />
<DataGridTextColumn
Header="{core:Localize Dialog.Options.IDEOptions.Debugging.ExceptionFilter.ColumnExpression}"
Width="*"
Binding="{Binding Expression}" />
</DataGrid.Columns>
</DataGrid>
</core:RestrictDesiredSize>
<Button Margin="0,3,5,3" Grid.Row="1" Grid.Column="1" IsDefault="True" Click="Button_Click" Content="{core:Localize Global.OKButtonText}"></Button>
<Button Margin="0,3,5,3" Grid.Row="1" Grid.Column="2" IsCancel="True" Content="{core:Localize Global.CancelButtonText}"></Button>
</Grid>
</Window>

49
src/AddIns/Debugger/Debugger.AddIn/Options/ChooseExceptionsDialog.xaml.cs

@ -0,0 +1,49 @@ @@ -0,0 +1,49 @@
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
using ICSharpCode.SharpDevelop.Gui;
namespace Debugger.AddIn.Options
{
/// <summary>
/// Interaction logic for ChooseExceptionsDialog.xaml
/// </summary>
public partial class ChooseExceptionsDialog : Window
{
public ChooseExceptionsDialog(IEnumerable<ExceptionFilterEntry> entries)
{
InitializeComponent();
FormLocationHelper.ApplyWindow(this, "Debugger.ChooseExceptionsDialog", true);
ExceptionFilterList = new ObservableCollection<ExceptionFilterEntry>(entries);
dataGrid.ItemsSource = ExceptionFilterList;
}
public IList<ExceptionFilterEntry> ExceptionFilterList { get; set; }
void Button_Click(object sender, RoutedEventArgs e)
{
DialogResult = true;
}
}
}

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

@ -85,6 +85,11 @@ namespace ICSharpCode.SharpDevelop.Services @@ -85,6 +85,11 @@ namespace ICSharpCode.SharpDevelop.Services
set { PS.Set<bool>("Debugger.PauseOnHandledExceptions", value); }
}
public override IEnumerable<ExceptionFilterEntry> ExceptionFilterList {
get { return PS.GetList<ExceptionFilterEntry>("Debugger.ExceptionFilterList"); }
set { PS.SetList<ExceptionFilterEntry>("Debugger.ExceptionFilterList", value); }
}
public bool AskForArguments {
get { return PS.Get<bool>("Debugger.AskForArguments", false); }
set { PS.Set<bool>("Debugger.AskForArguments", value); }

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

@ -19,7 +19,12 @@ @@ -19,7 +19,12 @@
<GroupBox Margin="5" Header="{sd:Localize Dialog.Options.IDEOptions.Debugging.Exceptions}">
<widgets:StackPanelWithSpacing SpaceBetweenItems="5">
<CheckBox Content="{sd:Localize Dialog.Options.IDEOptions.Debugging.PauseOnHandledExceptions}"
x:Name="checkPauseOnHandled"
IsChecked="{sd:OptionBinding debugger:DebuggingOptions.PauseOnHandledExceptions}" />
<Button Content="{sd:Localize Dialog.Options.IDEOptions.Debugging.ChooseExceptions}"
Click="ChooseExceptionsClick"
HorizontalAlignment="Left"
IsEnabled="{Binding IsChecked, ElementName=checkPauseOnHandled}" />
</widgets:StackPanelWithSpacing>
</GroupBox>
<GroupBox Margin="5" Header="{sd:Localize Global.Advanced}">

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

@ -27,6 +27,7 @@ using System.Windows.Documents; @@ -27,6 +27,7 @@ using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Services;
@ -37,6 +38,8 @@ namespace Debugger.AddIn.Options @@ -37,6 +38,8 @@ namespace Debugger.AddIn.Options
/// </summary>
public partial class DebuggingOptionsPanel : OptionPanel
{
IList<ExceptionFilterEntry> exceptionFilterList;
public DebuggingOptionsPanel()
{
InitializeComponent();
@ -47,7 +50,26 @@ namespace Debugger.AddIn.Options @@ -47,7 +50,26 @@ namespace Debugger.AddIn.Options
bool result = base.SaveOptions();
if (WindowsDebugger.CurrentDebugger != null)
WindowsDebugger.CurrentDebugger.ReloadOptions();
DebuggingOptions.Instance.ExceptionFilterList = exceptionFilterList;
return result;
}
public override void LoadOptions()
{
base.LoadOptions();
exceptionFilterList = DebuggingOptions.Instance.ExceptionFilterList.ToList();
if (exceptionFilterList.Count == 0) {
exceptionFilterList.Add(new ExceptionFilterEntry("*"));
}
}
void ChooseExceptionsClick(object sender, RoutedEventArgs e)
{
var dialog = new ChooseExceptionsDialog(exceptionFilterList);
if (dialog.ShowDialog() == true) {
exceptionFilterList = dialog.ExceptionFilterList;
}
}
}
}

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

@ -19,7 +19,11 @@ @@ -19,7 +19,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using ICSharpCode.NRefactory.TypeSystem;
using Debugger.Interop;
using Debugger.Interop.CorDebug;
@ -540,12 +544,12 @@ namespace Debugger @@ -540,12 +544,12 @@ namespace Debugger
ExceptionType exceptionType = (ExceptionType)_exceptionType;
bool pauseOnHandled = !process.Evaluating && process.Options != null && process.Options.PauseOnHandledExceptions;
Thread thread = process.GetThread(pThread);
if (exceptionType == ExceptionType.Unhandled || (pauseOnHandled && exceptionType == ExceptionType.CatchHandlerFound)) {
if (exceptionType == ExceptionType.Unhandled || (pauseOnHandled && exceptionType == ExceptionType.CatchHandlerFound && BreakOnException(thread))) {
// Multiple exceptions can happen at the same time on multiple threads
// (I have managed to create a test application to trigger it)
Thread thread = process.GetThread(pThread);
thread.CurrentExceptionType = exceptionType;
RequestPause(thread).ExceptionsThrown.Add(thread);
}
@ -553,6 +557,49 @@ namespace Debugger @@ -553,6 +557,49 @@ namespace Debugger
ExitCallback();
}
Regex filterRegex;
static string ConvertWildcardsToRegex(string searchPattern)
{
if (string.IsNullOrEmpty(searchPattern))
return "";
StringBuilder builder = new StringBuilder();
foreach (char ch in searchPattern) {
switch (ch) {
case '?':
builder.Append(".");
break;
case '*':
builder.Append(".*");
break;
default:
builder.Append(Regex.Escape(ch.ToString()));
break;
}
}
return builder.ToString();
}
bool BreakOnException(Thread thread)
{
IType exceptionType = thread.CurrentException.Type;
if (filterRegex == null) {
var exceptionFilterList = thread.Process.Options.ExceptionFilterList.Where(i => i.IsActive).Select(s => "(" + ConvertWildcardsToRegex(s.Expression) + ")");
filterRegex = new Regex(string.Join("|", exceptionFilterList), RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ExplicitCapture);
}
foreach (var baseType in exceptionType.GetNonInterfaceBaseTypes()) {
if (filterRegex.IsMatch(baseType.ReflectionName))
return true;
}
return false;
}
public void ExceptionUnwind(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, CorDebugExceptionUnwindCallbackType dwEventType, uint dwFlags)
{
EnterCallback("ExceptionUnwind", pThread);

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

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace Debugger
{
@ -32,5 +33,57 @@ namespace Debugger @@ -32,5 +33,57 @@ namespace Debugger
public virtual bool StepOverFieldAccessProperties { get; set; }
public virtual IEnumerable<string> SymbolsSearchPaths { get; set; }
public virtual bool PauseOnHandledExceptions { get; set; }
public virtual IEnumerable<ExceptionFilterEntry> ExceptionFilterList { get; set; }
}
[Serializable]
public class ExceptionFilterEntry : INotifyPropertyChanged
{
string expression;
bool isActive;
public ExceptionFilterEntry()
{
this.IsActive = true;
}
public ExceptionFilterEntry(string expression)
{
this.IsActive = true;
this.Expression = expression;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
var propertyChanged = PropertyChanged;
if (propertyChanged != null)
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public string Expression {
get {
return expression;
}
set {
if (expression != value) {
expression = value;
OnPropertyChanged("Expression");
}
}
}
public bool IsActive {
get {
return isActive;
}
set {
if (isActive != value) {
isActive = value;
OnPropertyChanged("IsActive");
}
}
}
}
}

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

@ -20,6 +20,7 @@ using System.Collections.Generic; @@ -20,6 +20,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
@ -217,11 +218,14 @@ namespace ICSharpCode.SharpDevelop.Debugging @@ -217,11 +218,14 @@ namespace ICSharpCode.SharpDevelop.Debugging
get { return false; }
}
public IEnumerable<string> SymbolsSearchPaths {
get { return Enumerable.Empty<string>(); }
get { return EmptyList<string>.Instance; }
}
public bool PauseOnHandledExceptions {
get { return false; }
}
public IEnumerable<string> ExceptionFilterList {
get { return EmptyList<string>.Instance; }
}
public static readonly DummyDebuggerOptions Instance = new DummyDebuggerOptions();
}

Loading…
Cancel
Save