Browse Source

Refactored breakpoints; Ensure multiple (conditional) breakpoints on the same line are handled.

newNRvisualizers
David Srbecký 13 years ago
parent
commit
0022f6db3f
  1. 94
      src/AddIns/Debugger/Debugger.AddIn/BreakpointChangeMenuBuilder.cs
  2. 9
      src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin
  3. 6
      src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj
  4. 43
      src/AddIns/Debugger/Debugger.AddIn/DisableBreakpointMenuCommand.cs
  5. 43
      src/AddIns/Debugger/Debugger.AddIn/EnableBreakpointMenuCommand.cs
  6. 51
      src/AddIns/Debugger/Debugger.AddIn/IsActiveBreakpointCondition.cs
  7. 43
      src/AddIns/Debugger/Debugger.AddIn/IsBreakpointCondition.cs
  8. 49
      src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/SelectLanguageCommand.cs
  9. 75
      src/AddIns/Debugger/Debugger.AddIn/Service/BreakpointCommands.cs
  10. 7
      src/AddIns/Debugger/Debugger.AddIn/Service/EditBreakpointScriptWindow.xaml
  11. 43
      src/AddIns/Debugger/Debugger.AddIn/Service/EditBreakpointScriptWindow.xaml.cs
  12. 54
      src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
  13. 61
      src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs
  14. 24
      src/AddIns/Debugger/Debugger.Core/NDebugger.cs
  15. 13
      src/AddIns/Debugger/Debugger.Core/Process.cs
  16. 2
      src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs
  17. 37
      src/Main/Base/Project/Src/Services/Debugger/BreakpointBookmark.cs
  18. 60
      src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs
  19. 4
      src/Main/Base/Project/Src/Services/Debugger/DecompiledBreakpointBookmark.cs

94
src/AddIns/Debugger/Debugger.AddIn/BreakpointChangeMenuBuilder.cs

@ -1,94 +0,0 @@ @@ -1,94 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Controls;
using Debugger.AddIn.Service;
using ICSharpCode.Core;
using ICSharpCode.Core.Presentation;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Gui.Pads;
namespace Debugger.AddIn
{
public class BreakpointChangeMenuBuilder : ISubmenuBuilder, IMenuItemBuilder
{
public ToolStripItem[] BuildSubmenu(Codon codon, object owner)
{
List<ToolStripItem> items = new List<ToolStripItem>();
ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveWorkbenchWindow.ActiveViewContent as ITextEditorProvider;
BreakpointBookmark point = null;
foreach (BreakpointBookmark breakpoint in DebuggerService.Breakpoints) {
if ((breakpoint.FileName == provider.TextEditor.FileName) &&
(breakpoint.LineNumber == provider.TextEditor.Caret.Line)) {
point = breakpoint;
break;
}
}
if (point != null) {
foreach (string item in BreakpointAction.GetNames(typeof(BreakpointAction))) {
items.Add(MakeItem("${res:MainWindow.Windows.Debug.Conditional.Breakpoints." + item + "}", item, point, point.Action.ToString(), delegate(object sender, EventArgs e) {HandleItem(sender);}));
}
}
return items.ToArray();
}
public ICollection BuildItems(Codon codon, object owner)
{
return BuildSubmenu(codon, owner).TranslateToWpf();
}
void HandleItem(object sender)
{
MenuItem item = null;
if (sender is MenuItem)
item = (MenuItem)sender;
if (item != null) {
BreakpointBookmark bookmark = (BreakpointBookmark)item.Tag;
switch (item.Name) {
case "Break":
bookmark.Action = BreakpointAction.Break;
break;
case "Condition":
EditBreakpointScriptWindow window = new EditBreakpointScriptWindow(bookmark) {
Owner = WorkbenchSingleton.MainWindow
};
if (window.ShowDialog() ?? false) {
bookmark = window.Data;
}
break;
case "Trace":
bookmark.Action = BreakpointAction.Trace;
break;
}
}
}
ToolStripMenuItem MakeItem(string title, string name, BreakpointBookmark tag, string data, EventHandler onClick)
{
ToolStripMenuItem menuItem = new ToolStripMenuItem(StringParser.Parse(title));
menuItem.Click += onClick;
menuItem.Name = name;
menuItem.Tag = tag;
if (name == tag.Action.ToString())
menuItem.Checked = true;
return menuItem;
}
}
}

9
src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin

@ -61,10 +61,9 @@ @@ -61,10 +61,9 @@
class="Debugger.AddIn.EnableBreakpointMenuCommand"
label= "${res:MainWindow.Windows.Debug.Conditional.Breakpoints.EnableBreakpoint}" />
</ComplexCondition>
<!--
<MenuItem id="BreakpointSeparator" type = "Separator" />
<MenuItem id="MenuBuilder" type="Builder" class="Debugger.AddIn.BreakpointChangeMenuBuilder" />
-->
<MenuItem id="EditCondition"
class="Debugger.AddIn.EditBreakpointMenuCommand"
label= "${res:MainWindow.Windows.Debug.Conditional.Breakpoints.EditCondition}" />
</Condition>
</MenuItem>
</Path>
@ -148,8 +147,6 @@ @@ -148,8 +147,6 @@
<Path name="/SharpDevelop/Pads/ConsolePad/ToolBar">
<Include id="StandardCommands" path="/SharpDevelop/Pads/CommonConsole/ToolBar" />
<ToolbarItem class="ICSharpCode.SharpDevelop.Gui.Pads.SelectLanguageCommand"
type="ComboBox" id="SelectLanguageCommand" />
</Path>
<Path name="/SharpDevelop/Pads/ParallelStacksPad/ToolBar">

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

@ -106,14 +106,9 @@ @@ -106,14 +106,9 @@
<Compile Include="Pads\CallStackPad.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Pads\Commands\SelectLanguageCommand.cs" />
<Compile Include="Pads\Commands\WatchPadCommands.cs" />
<Compile Include="Pads\Common\AutoCompleteTextBox.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="DisableBreakpointMenuCommand.cs" />
<Compile Include="EnableBreakpointMenuCommand.cs" />
<Compile Include="IsActiveBreakpointCondition.cs" />
<Compile Include="IsBreakpointCondition.cs" />
<Compile Include="Options\DebuggingOptions.cs" />
<Compile Include="Options\DebuggingSymbolsPanel.cs">
<SubType>UserControl</SubType>
@ -134,6 +129,7 @@ @@ -134,6 +129,7 @@
<Compile Include="Service\AttachToProcessForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Service\BreakpointCommands.cs" />
<Compile Include="Service\DebuggeeExceptionForm.cs">
<SubType>Form</SubType>
</Compile>

43
src/AddIns/Debugger/Debugger.AddIn/DisableBreakpointMenuCommand.cs

@ -1,43 +0,0 @@ @@ -1,43 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
using ICSharpCode.SharpDevelop.Gui.Pads;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using Debugger.AddIn.Service;
using ICSharpCode.Core;
using ICSharpCode.Core.Presentation;
using ICSharpCode.Core.WinForms;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui;
namespace Debugger.AddIn
{
public class DisableBreakpointMenuCommand : AbstractMenuCommand
{
public override void Run()
{
ITextEditor editor = SD.GetActiveViewContentService<ITextEditor>();
if (editor == null)
return;
BreakpointBookmark point = null;
foreach (BreakpointBookmark breakpoint in DebuggerService.Breakpoints) {
if ((breakpoint.FileName == editor.FileName) &&
(breakpoint.LineNumber == editor.Caret.Line)) {
point = breakpoint;
break;
}
}
if (point != null) {
point.IsEnabled = false;
}
}
}
}

43
src/AddIns/Debugger/Debugger.AddIn/EnableBreakpointMenuCommand.cs

@ -1,43 +0,0 @@ @@ -1,43 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
using ICSharpCode.SharpDevelop.Gui.Pads;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using Debugger.AddIn.Service;
using ICSharpCode.Core;
using ICSharpCode.Core.Presentation;
using ICSharpCode.Core.WinForms;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui;
namespace Debugger.AddIn
{
public class EnableBreakpointMenuCommand : AbstractMenuCommand
{
public override void Run()
{
ITextEditor editor = SD.GetActiveViewContentService<ITextEditor>();
if (editor == null)
return;
BreakpointBookmark point = null;
foreach (BreakpointBookmark breakpoint in DebuggerService.Breakpoints) {
if ((breakpoint.FileName == editor.FileName) &&
(breakpoint.LineNumber == editor.Caret.Line)) {
point = breakpoint;
break;
}
}
if (point != null) {
point.IsEnabled = true;
}
}
}
}

51
src/AddIns/Debugger/Debugger.AddIn/IsActiveBreakpointCondition.cs

@ -1,51 +0,0 @@ @@ -1,51 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
using ICSharpCode.SharpDevelop.Gui.Pads;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using Debugger.AddIn.Service;
using ICSharpCode.Core;
using ICSharpCode.Core.Presentation;
using ICSharpCode.Core.WinForms;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui;
namespace Debugger.AddIn
{
public class IsActiveBreakpointCondition : IConditionEvaluator
{
public IsActiveBreakpointCondition()
{
}
public bool IsValid(object caller, Condition condition)
{
ITextEditor editor = SD.GetActiveViewContentService<ITextEditor>();
if (editor == null)
return false;
if (string.IsNullOrEmpty(editor.FileName))
return false;
BreakpointBookmark point = null;
foreach (BreakpointBookmark breakpoint in DebuggerService.Breakpoints) {
if ((breakpoint.FileName == editor.FileName) &&
(breakpoint.LineNumber == editor.Caret.Line)) {
point = breakpoint;
break;
}
}
if (point != null) {
return point.IsEnabled;
}
return false;
}
}
}

43
src/AddIns/Debugger/Debugger.AddIn/IsBreakpointCondition.cs

@ -1,43 +0,0 @@ @@ -1,43 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
using ICSharpCode.SharpDevelop.Gui.Pads;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using Debugger.AddIn.Service;
using ICSharpCode.Core;
using ICSharpCode.Core.Presentation;
using ICSharpCode.Core.WinForms;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui;
namespace Debugger.AddIn
{
public class IsBreakpointCondition : IConditionEvaluator
{
public IsBreakpointCondition()
{
}
public bool IsValid(object caller, Condition condition)
{
ITextEditor editor = SD.GetActiveViewContentService<ITextEditor>();
if (editor == null)
return false;
if (string.IsNullOrEmpty(editor.FileName))
return false;
foreach (BreakpointBookmark mark in DebuggerService.Breakpoints) {
if ((mark.FileName == editor.FileName) &&
(mark.LineNumber == editor.Caret.Line))
return true;
}
return false;
}
}
}

49
src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/SelectLanguageCommand.cs

@ -1,49 +0,0 @@ @@ -1,49 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
using System;
using Debugger;
using Debugger.AddIn;
using ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Services;
using System.Windows.Controls;
namespace ICSharpCode.SharpDevelop.Gui.Pads
{
#warning AbstractComboBoxCommand
/*
class SelectLanguageCommand : AbstractComboBoxCommand
{
ConsolePad pad;
ComboBox box;
protected override void OnOwnerChanged(EventArgs e)
{
this.pad = this.Owner as ConsolePad;
if (this.pad == null)
return;
box = this.ComboBox as ComboBox;
if (this.box == null)
return;
foreach (var name in Enum.GetNames(typeof(SupportedLanguage)))
box.Items.Add(name);
box.SelectedIndex = 0;
base.OnOwnerChanged(e);
}
public override void Run()
{
if (this.pad != null && this.box != null) {
pad.SelectedLanguage = (SupportedLanguage)Enum.Parse(typeof(SupportedLanguage), box.SelectedValue.ToString());
}
base.Run();
}
}*/
}

75
src/AddIns/Debugger/Debugger.AddIn/Service/BreakpointCommands.cs

@ -0,0 +1,75 @@ @@ -0,0 +1,75 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Editor;
namespace Debugger.AddIn
{
public static class BreakpointUtil
{
public static IEnumerable<BreakpointBookmark> BreakpointsOnCaret {
get {
ITextEditor editor = SD.GetActiveViewContentService<ITextEditor>();
if (editor == null)
return new BreakpointBookmark[0];
return SD.BookmarkManager.Bookmarks.OfType<BreakpointBookmark>().Where(bp => bp.FileName == editor.FileName && bp.LineNumber == editor.Caret.Line);
}
}
}
public class EnableBreakpointMenuCommand : AbstractMenuCommand
{
public override void Run()
{
foreach (BreakpointBookmark bp in BreakpointUtil.BreakpointsOnCaret) {
bp.IsEnabled = true;
}
}
}
public class DisableBreakpointMenuCommand : AbstractMenuCommand
{
public override void Run()
{
foreach (BreakpointBookmark bp in BreakpointUtil.BreakpointsOnCaret) {
bp.IsEnabled = false;
}
}
}
public class EditBreakpointMenuCommand : AbstractMenuCommand
{
public override void Run()
{
foreach (BreakpointBookmark bp in BreakpointUtil.BreakpointsOnCaret) {
EditBreakpointScriptWindow window = new EditBreakpointScriptWindow(bp) {
Owner = SD.Workbench.MainWindow
};
window.ShowDialog();
}
}
}
public class IsActiveBreakpointCondition : IConditionEvaluator
{
public bool IsValid(object caller, Condition condition)
{
return BreakpointUtil.BreakpointsOnCaret.Any(bp => bp.IsEnabled);
}
}
public class IsBreakpointCondition : IConditionEvaluator
{
public bool IsValid(object caller, Condition condition)
{
return BreakpointUtil.BreakpointsOnCaret.Any();
}
}
}

7
src/AddIns/Debugger/Debugger.AddIn/Service/EditBreakpointScriptWindow.xaml

@ -1,11 +1,6 @@ @@ -1,11 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Window x:Class="Debugger.AddIn.Service.EditBreakpointScriptWindow" xmlns:sd="http://icsharpcode.net/sharpdevelop/core" xmlns:widgets="http://icsharpcode.net/sharpdevelop/widgets" xmlns:avalonedit="http://icsharpcode.net/sharpdevelop/avalonedit" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="{sd:Localize MainWindow.Windows.Debug.Conditional.Breakpoints.ScriptingWindow.Title}" Width="500" Style="{x:Static sd:GlobalStyles.DialogWindowStyle}" WindowStartupLocation="CenterScreen" Height="400">
<Window x:Class="Debugger.AddIn.EditBreakpointScriptWindow" xmlns:sd="http://icsharpcode.net/sharpdevelop/core" xmlns:widgets="http://icsharpcode.net/sharpdevelop/widgets" xmlns:avalonedit="http://icsharpcode.net/sharpdevelop/avalonedit" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="{sd:Localize MainWindow.Windows.Debug.Conditional.Breakpoints.ScriptingWindow.Title}" Width="500" Style="{x:Static sd:GlobalStyles.DialogWindowStyle}" WindowStartupLocation="CenterScreen" Height="400">
<DockPanel>
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<Label Margin="3" Content="{sd:Localize MainWindow.Windows.Debug.Conditional.Breakpoints.ScriptingWindow.ScriptingLanguage}" />
<ComboBox Margin="3" Name="cmbLanguage" SelectionChanged="CmbLanguageSelectionChanged" />
<Button Margin="3" Name="btnCheckSyntax" Click="BtnCheckSyntaxClick" Content="{sd:Localize MainWindow.Windows.Debug.Conditional.Breakpoints.ScriptingWindow.CheckSyntax}" />
</StackPanel>
<widgets:UniformGridWithSpacing DockPanel.Dock="Bottom" Columns="2" HorizontalAlignment="Center" Margin="3">
<Button Name="btnOK" Content="{sd:Localize Global.OKButtonText}" Click="BtnOKClick" IsDefault="True" Style="{x:Static sd:GlobalStyles.ButtonStyle}" />
<Button Name="btnCancel" Content="{sd:Localize Global.CancelButtonText}" Click="BtnCancelClick" IsCancel="True" Style="{x:Static sd:GlobalStyles.ButtonStyle}" />

43
src/AddIns/Debugger/Debugger.AddIn/Service/EditBreakpointScriptWindow.xaml.cs

@ -17,7 +17,7 @@ using ICSharpCode.Core; @@ -17,7 +17,7 @@ using ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop.Debugging;
namespace Debugger.AddIn.Service
namespace Debugger.AddIn
{
/// <summary>
/// Interaction logic for EditBreakpointScriptWindow.xaml
@ -26,38 +26,15 @@ namespace Debugger.AddIn.Service @@ -26,38 +26,15 @@ namespace Debugger.AddIn.Service
{
BreakpointBookmark data;
public BreakpointBookmark Data {
get { return data; }
}
public EditBreakpointScriptWindow(BreakpointBookmark data)
{
InitializeComponent();
this.data = data;
this.data.Action = BreakpointAction.Condition;
foreach (var name in Enum.GetNames(typeof(SupportedLanguage)))
cmbLanguage.Items.Add(name);
string language = "CSharp";
if (ProjectService.CurrentProject != null)
language = ProjectService.CurrentProject.Language.Replace("#", "Sharp");
this.cmbLanguage.SelectedIndex =
(!string.IsNullOrEmpty(data.ScriptLanguage)) ?
this.cmbLanguage.Items.IndexOf(data.ScriptLanguage) :
this.cmbLanguage.Items.IndexOf(language);
this.codeEditor.Document.Text = data.Condition;
UpdateHighlighting();
}
void UpdateHighlighting()
{
codeEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition(this.cmbLanguage.SelectedItem.ToString().Replace("Sharp", "#"));
string language = ProjectService.CurrentProject != null ? ProjectService.CurrentProject.Language : "C#";
this.codeEditor.Document.Text = data.Condition ?? string.Empty;
this.codeEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition(language);
}
bool CheckSyntax()
@ -79,6 +56,7 @@ namespace Debugger.AddIn.Service @@ -79,6 +56,7 @@ namespace Debugger.AddIn.Service
{
if (!this.CheckSyntax())
return;
this.data.Condition = this.codeEditor.Document.Text;
DialogResult = true;
}
@ -87,16 +65,5 @@ namespace Debugger.AddIn.Service @@ -87,16 +65,5 @@ namespace Debugger.AddIn.Service
{
DialogResult = false;
}
void CmbLanguageSelectionChanged(object sender, SelectionChangedEventArgs e)
{
this.data.ScriptLanguage = this.cmbLanguage.SelectedValue.ToString();
UpdateHighlighting();
}
void BtnCheckSyntaxClick(object sender, RoutedEventArgs e)
{
CheckSyntax();
}
}
}

54
src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs

@ -364,19 +364,22 @@ namespace ICSharpCode.SharpDevelop.Services @@ -364,19 +364,22 @@ namespace ICSharpCode.SharpDevelop.Services
CurrentDebugger = new NDebugger();
CurrentDebugger.Options = DebuggingOptions.Instance;
DebuggerService.BreakPointAdded += delegate (object sender, BreakpointBookmarkEventArgs e) {
AddBreakpoint(e.BreakpointBookmark);
};
foreach (BreakpointBookmark b in DebuggerService.Breakpoints) {
foreach (BreakpointBookmark b in SD.BookmarkManager.Bookmarks.OfType<BreakpointBookmark>()) {
AddBreakpoint(b);
}
SD.BookmarkManager.BookmarkAdded += (sender, e) => {
BreakpointBookmark bm = e.Bookmark as BreakpointBookmark;
if (bm != null) {
AddBreakpoint(bm);
}
};
SD.BookmarkManager.BookmarkRemoved += (sender, e) => {
BreakpointBookmark bm = e.Bookmark as BreakpointBookmark;
if (bm != null) {
Breakpoint bp = bm.InternalBreakpointObject as Breakpoint;
bp.IsEnabled = false;
CurrentDebugger.RemoveBreakpoint(bp);
}
};
@ -501,7 +504,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -501,7 +504,7 @@ namespace ICSharpCode.SharpDevelop.Services
RefreshPads();
}
void debuggedProcess_DebuggingPaused(object sender, DebuggerEventArgs e)
void debuggedProcess_DebuggingPaused(object sender, DebuggerPausedEventArgs e)
{
OnIsProcessRunningChanged(EventArgs.Empty);
@ -509,33 +512,34 @@ namespace ICSharpCode.SharpDevelop.Services @@ -509,33 +512,34 @@ namespace ICSharpCode.SharpDevelop.Services
CurrentThread = e.Thread;
CurrentStackFrame = CurrentThread != null ? CurrentThread.MostRecentUserStackFrame : null;
LoggingService.Info("Jump to current line");
JumpToCurrentLine();
if (e.ExceptionThrown != null) {
HandleException(e);
return;
}
bool breakpointHit = false;
foreach (Breakpoint breakpoint in e.BreakpointsHit) {
var bookmark = SD.BookmarkManager.Bookmarks.OfType<BreakpointBookmark>().First(bm => bm.InternalBreakpointObject == breakpoint);
LoggingService.Debug(bookmark.Action + " " + bookmark.ScriptLanguage + " " + bookmark.Condition);
switch (bookmark.Action) {
case BreakpointAction.Break:
break;
case BreakpointAction.Condition:
if (EvaluateCondition(bookmark.Condition))
if (string.IsNullOrEmpty(bookmark.Condition)) {
breakpointHit = true;
} else {
if (EvaluateCondition(bookmark.Condition)) {
breakpointHit = true;
DebuggerService.PrintDebugMessage(string.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.Conditional.Breakpoints.BreakpointHitAtBecause}") + "\n", bookmark.LineNumber, bookmark.FileName, bookmark.Condition));
else
CurrentProcess.AsyncContinue();
break;
case BreakpointAction.Trace:
DebuggerService.PrintDebugMessage(string.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.Conditional.Breakpoints.BreakpointHitAt}") + "\n", bookmark.LineNumber, bookmark.FileName));
break;
}
}
}
// We can have several, potentially conditional, breakpoints at the same time
// ... as well as stepper happening on the same line
if (e.Break || breakpointHit) {
LoggingService.Info("Jump to current line");
JumpToCurrentLine();
} else {
e.Process.AsyncContinue();
}
RefreshPads();
}
@ -550,7 +554,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -550,7 +554,7 @@ namespace ICSharpCode.SharpDevelop.Services
RefreshPads();
}
void HandleException(DebuggerEventArgs e)
void HandleException(DebuggerPausedEventArgs e)
{
JumpToCurrentLine();
@ -583,6 +587,8 @@ namespace ICSharpCode.SharpDevelop.Services @@ -583,6 +587,8 @@ namespace ICSharpCode.SharpDevelop.Services
Bitmap icon = WinFormsResourceService.GetBitmap(e.ExceptionThrown.IsUnhandled ? "Icons.32x32.Error" : "Icons.32x32.Warning");
DebuggeeExceptionForm.Show(e.Process, title, message, stacktraceBuilder.ToString(), icon, e.ExceptionThrown.IsUnhandled, e.ExceptionThrown);
RefreshPads();
}
public bool BreakAndInterceptHandledException(Debugger.Exception exception)

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

@ -23,12 +23,10 @@ namespace Debugger @@ -23,12 +23,10 @@ namespace Debugger
{
Process process;
bool pauseOnNextExit;
bool raiseEventsOnNextExit;
bool isInCallback;
DebuggerPausedEventArgs pausedEventArgs;
Thread threadToReport;
List<Breakpoint> breakpointsHit = new List<Breakpoint>();
Exception exceptionThrown;
Thread threadToReport; // TODO: Remove
[Debugger.Tests.Ignore]
public Process Process {
@ -44,6 +42,20 @@ namespace Debugger @@ -44,6 +42,20 @@ namespace Debugger
this.process = process;
}
// Calling this will prepare the paused event.
// The reason for the accumulation is that several pause callbacks
// can happen "at the same time" in the debugee.
// The event will be raised as soon as the callback queue is drained.
DebuggerPausedEventArgs GetPausedEventArgs()
{
if (pausedEventArgs == null) {
pausedEventArgs = new DebuggerPausedEventArgs();
pausedEventArgs.Process = process;
pausedEventArgs.BreakpointsHit = new List<Breakpoint>();
}
return pausedEventArgs;
}
void EnterCallback(string name, ICorDebugProcess pProcess)
{
isInCallback = true;
@ -86,7 +98,8 @@ namespace Debugger @@ -86,7 +98,8 @@ namespace Debugger
if (hasQueuedCallbacks)
process.TraceMessage("Process has queued callbacks");
if (hasQueuedCallbacks && exceptionThrown == null) {
// TODO: Can we drain the queue?
if (hasQueuedCallbacks && (pausedEventArgs == null || pausedEventArgs.ExceptionThrown == null)) {
// Process queued callbacks if no exception occurred
process.AsyncContinue(DebuggeeStateAction.Keep, null, null);
} else if (process.Evaluating) {
@ -97,23 +110,18 @@ namespace Debugger @@ -97,23 +110,18 @@ namespace Debugger
process.TraceMessage("Callback exit: Paused");
process.DisableAllSteppers();
if (raiseEventsOnNextExit) {
DebuggerEventArgs e = new DebuggerEventArgs();
e.Process = process;
e.Thread = threadToReport;
e.BreakpointsHit = breakpointsHit.ToArray();
e.ExceptionThrown = exceptionThrown;
if (pausedEventArgs != null) {
pausedEventArgs.Thread = threadToReport;
threadToReport = null;
breakpointsHit.Clear();
exceptionThrown = null;
// Raise the pause event outside the callback
// Warning: Make sure that process in not resumed in the meantime
DebuggerPausedEventArgs e = pausedEventArgs; // Copy for capture
process.Debugger.MTA2STA.AsyncCall(delegate { process.OnPaused(e); });
}
pauseOnNextExit = false;
raiseEventsOnNextExit = false;
pausedEventArgs = null;
} else {
process.AsyncContinue(DebuggeeStateAction.Keep, null, null);
}
@ -157,7 +165,7 @@ namespace Debugger @@ -157,7 +165,7 @@ namespace Debugger
} else {
// User-code method
pauseOnNextExit = true;
raiseEventsOnNextExit = true;
GetPausedEventArgs().Break = true;
process.TraceMessage(" - pausing in user code");
}
@ -170,13 +178,15 @@ namespace Debugger @@ -170,13 +178,15 @@ namespace Debugger
EnterCallback("Breakpoint", pThread);
Breakpoint breakpoint = process.Debugger.GetBreakpoint(corBreakpoint);
// Could be tempBreakpoint
// Could be one of Process.tempBreakpoints
// The breakpoint might have just been removed
if (breakpoint != null) {
breakpointsHit.Add(breakpoint);
GetPausedEventArgs().BreakpointsHit.Add(breakpoint);
} else {
GetPausedEventArgs().Break = true;
}
pauseOnNextExit = true;
raiseEventsOnNextExit = true;
ExitCallback();
}
@ -193,7 +203,7 @@ namespace Debugger @@ -193,7 +203,7 @@ namespace Debugger
EnterCallback("Break", pThread);
pauseOnNextExit = true;
raiseEventsOnNextExit = true;
GetPausedEventArgs().Break = true;
ExitCallback();
}
@ -202,7 +212,7 @@ namespace Debugger @@ -202,7 +212,7 @@ namespace Debugger
EnterCallback("ControlCTrap", pProcess);
pauseOnNextExit = true;
raiseEventsOnNextExit = true;
GetPausedEventArgs().Break = true;
ExitCallback();
}
@ -293,7 +303,7 @@ namespace Debugger @@ -293,7 +303,7 @@ namespace Debugger
try {
pauseOnNextExit = true;
raiseEventsOnNextExit = true;
GetPausedEventArgs().Break = true;
ExitCallback();
} catch (COMException) {
} catch (InvalidComObjectException) {
@ -524,14 +534,13 @@ namespace Debugger @@ -524,14 +534,13 @@ namespace Debugger
bool pauseOnHandled = !process.Evaluating && process.Options != null && process.Options.PauseOnHandledExceptions;
if (exceptionType == ExceptionType.Unhandled || (pauseOnHandled && exceptionType == ExceptionType.CatchHandlerFound)) {
// sanity check: we can only handle one exception after another
// TODO : create Exception queue if CLR throws multiple exceptions
Debug.Assert(exceptionThrown == null);
Value value = new Value(process.GetAppDomain(pAppDomain), pThread.GetCurrentException()).GetPermanentReferenceOfHeapValue();
exceptionThrown = new Exception(value, exceptionType);
if (GetPausedEventArgs().ExceptionThrown != null)
throw new DebuggerException("Exception is already being processed");
GetPausedEventArgs().ExceptionThrown = new Exception(value, exceptionType);
pauseOnNextExit = true;
raiseEventsOnNextExit = true;
}
ExitCallback();

24
src/AddIns/Debugger/Debugger.Core/NDebugger.cs

@ -188,6 +188,12 @@ namespace Debugger @@ -188,6 +188,12 @@ namespace Debugger
}
}
public void RemoveBreakpoint(Breakpoint breakpoint)
{
breakpoint.IsEnabled = false;
this.breakpoints.Remove(breakpoint);
}
internal Breakpoint GetBreakpoint(ICorDebugBreakpoint corBreakpoint)
{
foreach (Breakpoint breakpoint in this.Breakpoints) {
@ -299,10 +305,26 @@ namespace Debugger @@ -299,10 +305,26 @@ namespace Debugger
{
/// <summary> The process on which the event occured. Can be null. </summary>
public Process Process { get; set; }
}
/// <summary>
/// This event occurs when the debuggee stops.
/// Note that several events can happen at the same time.
/// </summary>
[Serializable]
public class DebuggerPausedEventArgs: DebuggerEventArgs
{
/// <summary> The thread on which the event occured. Can be null if the event was not thread specific. </summary>
public Thread Thread { get; set; }
public Breakpoint[] BreakpointsHit { get; set; }
/// <summary> Breakpoints hit </summary>
public List<Breakpoint> BreakpointsHit { get; set; }
/// <summary> Exception thrown </summary>
public Exception ExceptionThrown { get; set; }
/// <summary> Break, stepper or any other pause reason. </summary>
public bool Break { get; set; }
}
[Serializable]

13
src/AddIns/Debugger/Debugger.Core/Process.cs

@ -54,7 +54,7 @@ namespace Debugger @@ -54,7 +54,7 @@ namespace Debugger
public event EventHandler<MessageEventArgs> LogMessage;
public event EventHandler<ModuleEventArgs> ModuleLoaded;
public event EventHandler<ModuleEventArgs> ModuleUnloaded;
public event EventHandler<DebuggerEventArgs> Paused;
public event EventHandler<DebuggerPausedEventArgs> Paused;
public event EventHandler<DebuggerEventArgs> Resumed;
public event EventHandler<DebuggerEventArgs> Exited;
@ -256,7 +256,7 @@ namespace Debugger @@ -256,7 +256,7 @@ namespace Debugger
#region Events
internal void OnPaused(DebuggerEventArgs e)
internal void OnPaused(DebuggerPausedEventArgs e)
{
AssertPaused();
DisableAllSteppers();
@ -270,7 +270,7 @@ namespace Debugger @@ -270,7 +270,7 @@ namespace Debugger
if (callbackInterface.IsInCallback) throw new DebuggerException("Can not raise event within callback.");
TraceMessage ("Debugger event: OnPaused()");
if (Paused != null) {
foreach(EventHandler<DebuggerEventArgs> d in Paused.GetInvocationList()) {
foreach(EventHandler<DebuggerPausedEventArgs> d in Paused.GetInvocationList()) {
if (IsRunning) {
TraceMessage ("Skipping OnPaused delegate because process has resumed");
break;
@ -402,7 +402,7 @@ namespace Debugger @@ -402,7 +402,7 @@ namespace Debugger
corProcess.Stop(uint.MaxValue); // Infinite; ignored anyway
NotifyPaused();
OnPaused(new DebuggerEventArgs() { Process = this });
OnPaused(new DebuggerPausedEventArgs() { Process = this });
}
public void Detach()
@ -619,11 +619,6 @@ namespace Debugger @@ -619,11 +619,6 @@ namespace Debugger
internal void OnModuleLoaded(Module module)
{
module.OrderOfLoading = lastAssignedModuleOrderOfLoading++;
foreach (Breakpoint b in this.Debugger.Breakpoints) {
b.SetBreakpoint(module);
}
module.AppDomain.InvalidateCompilation();
if (this.BreakInMain) {

2
src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs

@ -205,7 +205,7 @@ namespace Debugger.Tests @@ -205,7 +205,7 @@ namespace Debugger.Tests
process.ModuleLoaded += delegate(object sender, ModuleEventArgs e) {
LogEvent("ModuleLoaded", e.Module.Name + (e.Module.HasSymbols ? " (Has symbols)" : " (No symbols)"));
};
process.Paused += delegate(object sender, DebuggerEventArgs e) {
process.Paused += delegate(object sender, DebuggerPausedEventArgs e) {
this.CurrentThread = e.Thread;
if (e.Thread != null && e.Thread.IsInValidState) {
this.CurrentStackFrame = e.Thread.MostRecentStackFrame;

37
src/Main/Base/Project/Src/Services/Debugger/BreakpointBookmark.cs

@ -14,36 +14,20 @@ using ICSharpCode.SharpDevelop.Editor; @@ -14,36 +14,20 @@ using ICSharpCode.SharpDevelop.Editor;
namespace ICSharpCode.SharpDevelop.Debugging
{
public enum BreakpointAction
{
Break,
Trace,
Condition
}
public class BreakpointBookmark : SDMarkerBookmark
{
bool isHealthy = true;
bool isEnabled = true;
string tooltip;
BreakpointAction action = BreakpointAction.Break;
string condition;
string scriptLanguage;
public event EventHandler<EventArgs> ConditionChanged;
public string ScriptLanguage {
get { return scriptLanguage; }
set { scriptLanguage = value; }
}
public string Condition {
get { return condition; }
set {
if (condition != value) {
condition = value;
this.Action = string.IsNullOrEmpty(condition) ? BreakpointAction.Break : BreakpointAction.Condition;
if (ConditionChanged != null)
ConditionChanged(this, EventArgs.Empty);
Redraw();
@ -51,18 +35,6 @@ namespace ICSharpCode.SharpDevelop.Debugging @@ -51,18 +35,6 @@ namespace ICSharpCode.SharpDevelop.Debugging
}
}
public BreakpointAction Action {
get {
return action;
}
set {
if (action != value) {
action = value;
Redraw();
}
}
}
public object InternalBreakpointObject { get; set; }
public virtual bool IsHealthy {
@ -105,13 +77,10 @@ namespace ICSharpCode.SharpDevelop.Debugging @@ -105,13 +77,10 @@ namespace ICSharpCode.SharpDevelop.Debugging
{
}
public BreakpointBookmark(FileName fileName, TextLocation location, BreakpointAction action, string scriptLanguage, string script)
public BreakpointBookmark(FileName fileName, TextLocation location)
{
this.Location = location;
this.FileName = fileName;
this.action = action;
this.scriptLanguage = scriptLanguage;
this.condition = script;
}
public const string BreakpointMarker = "Breakpoint";
@ -140,9 +109,9 @@ namespace ICSharpCode.SharpDevelop.Debugging @@ -140,9 +109,9 @@ namespace ICSharpCode.SharpDevelop.Debugging
if (!this.IsEnabled)
return DisabledBreakpointImage;
else if (this.IsHealthy)
return this.Action == BreakpointAction.Break ? BreakpointImage : BreakpointConditionalImage;
return string.IsNullOrEmpty(this.Condition) ? BreakpointImage : BreakpointConditionalImage;
else
return this.Action == BreakpointAction.Break ? UnhealthyBreakpointImage : UnhealthyBreakpointConditionalImage;
return string.IsNullOrEmpty(this.Condition) ? UnhealthyBreakpointImage : UnhealthyBreakpointConditionalImage;
}
}

60
src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs

@ -26,9 +26,6 @@ namespace ICSharpCode.SharpDevelop.Debugging @@ -26,9 +26,6 @@ namespace ICSharpCode.SharpDevelop.Debugging
};
ProjectService.BeforeSolutionClosing += OnBeforeSolutionClosing;
SD.BookmarkManager.BookmarkAdded += BookmarkAdded;
SD.BookmarkManager.BookmarkRemoved += BookmarkRemoved;
}
static void GetDescriptors()
@ -155,63 +152,6 @@ namespace ICSharpCode.SharpDevelop.Debugging @@ -155,63 +152,6 @@ namespace ICSharpCode.SharpDevelop.Debugging
debugCategory.AppendText(msg);
}
public static event EventHandler<BreakpointBookmarkEventArgs> BreakPointChanged;
public static event EventHandler<BreakpointBookmarkEventArgs> BreakPointAdded;
public static event EventHandler<BreakpointBookmarkEventArgs> BreakPointRemoved;
static void OnBreakPointChanged(BreakpointBookmarkEventArgs e)
{
if (BreakPointChanged != null) {
BreakPointChanged(null, e);
}
}
static void OnBreakPointAdded(BreakpointBookmarkEventArgs e)
{
if (BreakPointAdded != null) {
BreakPointAdded(null, e);
}
}
static void OnBreakPointRemoved(BreakpointBookmarkEventArgs e)
{
if (BreakPointRemoved != null) {
BreakPointRemoved(null, e);
}
}
public static IEnumerable<BreakpointBookmark> Breakpoints {
get {
return SD.BookmarkManager.Bookmarks.OfType<BreakpointBookmark>();
}
}
static void BookmarkAdded(object sender, BookmarkEventArgs e)
{
BreakpointBookmark bb = e.Bookmark as BreakpointBookmark;
if (bb != null) {
bb.LineNumberChanged += BookmarkChanged;
OnBreakPointAdded(new BreakpointBookmarkEventArgs(bb));
}
}
static void BookmarkRemoved(object sender, BookmarkEventArgs e)
{
BreakpointBookmark bb = e.Bookmark as BreakpointBookmark;
if (bb != null) {
bb.RemoveMarker();
OnBreakPointRemoved(new BreakpointBookmarkEventArgs(bb));
}
}
static void BookmarkChanged(object sender, EventArgs e)
{
BreakpointBookmark bb = sender as BreakpointBookmark;
if (bb != null) {
OnBreakPointChanged(new BreakpointBookmarkEventArgs(bb));
}
}
static void OnBeforeSolutionClosing(object sender, SolutionCancelEventArgs e)
{
if (currentDebugger == null)

4
src/Main/Base/Project/Src/Services/Debugger/DecompiledBreakpointBookmark.cs

@ -15,8 +15,8 @@ namespace ICSharpCode.SharpDevelop.Editor.Bookmarks @@ -15,8 +15,8 @@ namespace ICSharpCode.SharpDevelop.Editor.Bookmarks
MemberReference memberReference;
string assemblyFile;
public DecompiledBreakpointBookmark(FileName fileName, TextLocation location, BreakpointAction action, string scriptLanguage, string script)
: base(fileName, location, action, scriptLanguage, script)
public DecompiledBreakpointBookmark(FileName fileName, TextLocation location)
: base(fileName, location)
{
}

Loading…
Cancel
Save