Browse Source

Merge pull request #263 from RKlier/bookmarks

Debugger enhancement: windows for breakpoints and callstack
pull/205/merge
Eusebiu Marcu 14 years ago
parent
commit
2dff11fc6a
  1. 28
      Debugger/ILSpy.Debugger/Commands/BreakpointCommand.cs
  2. 2
      Debugger/ILSpy.Debugger/Commands/DebuggerCommands.cs
  3. 120
      Debugger/ILSpy.Debugger/DebuggerSettings.cs
  4. 10
      Debugger/ILSpy.Debugger/ILSpy.Debugger.csproj
  5. 73
      Debugger/ILSpy.Debugger/UI/BreakpointPanel.xaml
  6. 110
      Debugger/ILSpy.Debugger/UI/BreakpointPanel.xaml.cs
  7. 53
      Debugger/ILSpy.Debugger/UI/CallStackPanel.xaml
  8. 275
      Debugger/ILSpy.Debugger/UI/CallStackPanel.xaml.cs
  9. 1
      Debugger/ILSpy.Debugger/UI/DebuggerSettingsPanel.xaml
  10. 38
      Debugger/ILSpy.Debugger/UI/DebuggerSettingsPanel.xaml.cs
  11. 56
      ILSpy.SharpDevelop.LGPL/AvalonEdit/IconBarMargin.cs
  12. 6
      ILSpy.SharpDevelop.LGPL/Bookmarks/BreakpointBookmark.cs
  13. 2
      ILSpy.SharpDevelop.LGPL/Bookmarks/CurrentLineBookmark.cs
  14. 1
      ILSpy.SharpDevelop.LGPL/Images.cs
  15. 13
      ILSpy.SharpDevelop.LGPL/Services/DebuggerService.cs
  16. 1
      ILSpy/ILSpy.csproj
  17. BIN
      ILSpy/Images/DisabledBreakpoint.png

28
Debugger/ILSpy.Debugger/Commands/BreakpointCommand.cs

@ -1,10 +1,15 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using System.Linq;
using System.Windows; using System.Windows;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.AvalonEdit; using ICSharpCode.ILSpy.AvalonEdit;
using ICSharpCode.ILSpy.Bookmarks;
using ICSharpCode.ILSpy.Debugger.Bookmarks;
using ICSharpCode.ILSpy.Debugger.Services; using ICSharpCode.ILSpy.Debugger.Services;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.Debugger.Commands namespace ICSharpCode.ILSpy.Debugger.Commands
{ {
@ -23,8 +28,8 @@ namespace ICSharpCode.ILSpy.Debugger.Commands
// check if the codemappings exists for this line // check if the codemappings exists for this line
var storage = DebugInformation.CodeMappings; var storage = DebugInformation.CodeMappings;
int token = 0; int token = 0;
foreach (var key in storage.Keys) { foreach (var storageEntry in storage) {
var instruction = storage[key].GetInstructionByLineNumber(line, out token); var instruction = storageEntry.Value.GetInstructionByLineNumber(line, out token);
if (instruction == null) { if (instruction == null) {
continue; continue;
@ -48,4 +53,23 @@ namespace ICSharpCode.ILSpy.Debugger.Commands
} }
} }
} }
[ExportBookmarkContextMenuEntry(Header="Disable Breakpoint", Category="Debugger")]
public class DisableBreakpointCommand : IBookmarkContextMenuEntry
{
public bool IsVisible(IBookmark[] bookmarks)
{
return bookmarks.Any(b => b is BreakpointBookmark && (b as BreakpointBookmark).IsEnabled);
}
public bool IsEnabled(IBookmark[] bookmarks)
{
return true;
}
public void Execute(IBookmark[] bookmarks)
{
throw new NotImplementedException();
}
}
} }

2
Debugger/ILSpy.Debugger/Commands/DebuggerCommands.cs

@ -138,7 +138,7 @@ namespace ICSharpCode.ILSpy.Debugger.Commands
foreach (var item in items.First().Items.OfType<MenuItem>()) { foreach (var item in items.First().Items.OfType<MenuItem>()) {
string header = (string)item.Header; string header = (string)item.Header;
if (header.StartsWith("Remove")) continue; if (header.StartsWith("Remove") || header.StartsWith("Show")) continue;
if (header.StartsWith("Attach") || header.StartsWith("Debug")) if (header.StartsWith("Attach") || header.StartsWith("Debug"))
item.IsEnabled = enable; item.IsEnabled = enable;

120
Debugger/ILSpy.Debugger/DebuggerSettings.cs

@ -3,15 +3,73 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Xml.Linq;
namespace ICSharpCode.ILSpy.Debugger namespace ICSharpCode.ILSpy.Debugger
{ {
public class DebuggerSettings : INotifyPropertyChanged public class DebuggerSettings : INotifyPropertyChanged
{ {
bool showWarnings = true; #region members
bool askArguments = true; private static readonly string DEBUGGER_SETTINGS = "DebuggerSettings";
bool debugWholeTypesOnly = false; private static readonly string SHOW_WARNINGS = "showWarnings";
private static readonly string ASK_ARGUMENTS = "askForArguments";
private static readonly string SHOW_BOOKMARKS = "showAllBookmarks";
private static readonly string SHOW_MODULE = "showModuleName";
private static readonly string SHOW_ARGUMENTS = "showArguments";
private static readonly string SHOW_ARGUMENTVALUE = "showArgumentValues";
private bool showWarnings = true;
private bool askArguments = true;
private bool debugWholeTypesOnly = false;
private bool showAllBookmarks = false;
private bool showModuleName = true;
private bool showArguments = false;
private bool showArgumentValues = false;
private static DebuggerSettings s_instance;
#endregion
public static DebuggerSettings Instance
{
get {
if (null == s_instance)
s_instance = new DebuggerSettings();
return s_instance;
}
}
private DebuggerSettings()
{
}
public void Load(ILSpySettings settings)
{
XElement e = settings[DEBUGGER_SETTINGS];
ShowWarnings = (bool?)e.Attribute(SHOW_WARNINGS) ?? ShowWarnings;
AskForArguments = (bool?)e.Attribute(ASK_ARGUMENTS) ?? AskForArguments;
ShowAllBookmarks = (bool?)e.Attribute(SHOW_BOOKMARKS) ?? ShowAllBookmarks;
ShowModuleName = (bool?)e.Attribute(SHOW_MODULE) ?? ShowModuleName;
ShowArguments = (bool?)e.Attribute(SHOW_ARGUMENTS) ?? ShowArguments;
ShowArgumentValues = (bool?)e.Attribute(SHOW_ARGUMENTVALUE) ?? ShowArgumentValues;
}
public void Save(XElement root)
{
XElement section = new XElement(DEBUGGER_SETTINGS);
section.SetAttributeValue(SHOW_WARNINGS, ShowWarnings);
section.SetAttributeValue(ASK_ARGUMENTS, AskForArguments);
section.SetAttributeValue(SHOW_BOOKMARKS, ShowAllBookmarks);
section.SetAttributeValue(SHOW_MODULE, ShowModuleName);
section.SetAttributeValue(SHOW_ARGUMENTS, ShowArguments);
section.SetAttributeValue(SHOW_ARGUMENTVALUE, ShowArgumentValues);
XElement existingElement = root.Element(DEBUGGER_SETTINGS);
if (existingElement != null)
existingElement.ReplaceWith(section);
else
root.Add(section);
}
/// <summary> /// <summary>
/// Show warnings messages. /// Show warnings messages.
/// <remarks>Default value is true.</remarks> /// <remarks>Default value is true.</remarks>
@ -56,6 +114,61 @@ namespace ICSharpCode.ILSpy.Debugger
} }
} }
/// <summary>
/// Show all bookmarks in breakpoints window.
/// </summary>
[DefaultValue(false)]
public bool ShowAllBookmarks {
get { return showAllBookmarks; }
set {
if (showAllBookmarks != value) {
showAllBookmarks = value;
OnPropertyChanged("ShowAllBookmarks");
}
}
}
/// <summary>
/// Show module name in callstack panel.
/// </summary>
[DefaultValue(true)]
public bool ShowModuleName {
get { return showModuleName; }
set {
if (showModuleName != value) {
showModuleName = value;
OnPropertyChanged("ShowModuleName");
}
}
}
/// <summary>
/// Show module name in callstack panel.
/// </summary>
[DefaultValue(false)]
public bool ShowArguments {
get { return showArguments; }
set {
if (showArguments != value) {
showArguments = value;
OnPropertyChanged("ShowArguments");
}
}
}
/// <summary>
/// Show module name in callstack panel.
/// </summary>
[DefaultValue(false)]
public bool ShowArgumentValues {
get { return showArgumentValues; }
set {
if (showArgumentValues != value) {
showArgumentValues = value;
OnPropertyChanged("ShowArgumentValues");
}
}
}
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName) protected virtual void OnPropertyChanged(string propertyName)
@ -64,5 +177,6 @@ namespace ICSharpCode.ILSpy.Debugger
PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
} }
} }
} }
} }

10
Debugger/ILSpy.Debugger/ILSpy.Debugger.csproj

@ -105,6 +105,14 @@
<DependentUpon>AttachToProcessWindow.xaml</DependentUpon> <DependentUpon>AttachToProcessWindow.xaml</DependentUpon>
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="UI\BreakpointPanel.xaml.cs" >
<DependentUpon>BreakpointPanel.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="UI\CallStackPanel.xaml.cs" >
<DependentUpon>CallStackPanel.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="UI\DebuggerSettingsPanel.xaml.cs"> <Compile Include="UI\DebuggerSettingsPanel.xaml.cs">
<DependentUpon>DebuggerSettingsPanel.xaml</DependentUpon> <DependentUpon>DebuggerSettingsPanel.xaml</DependentUpon>
<SubType>Code</SubType> <SubType>Code</SubType>
@ -125,6 +133,8 @@
<Page Include="ToolTips\PinControlsDictionary.xaml" /> <Page Include="ToolTips\PinControlsDictionary.xaml" />
<Page Include="ToolTips\VisualizerPicker.xaml" /> <Page Include="ToolTips\VisualizerPicker.xaml" />
<Page Include="UI\AttachToProcessWindow.xaml" /> <Page Include="UI\AttachToProcessWindow.xaml" />
<Page Include="UI\BreakpointPanel.xaml" />
<Page Include="UI\CallStackPanel.xaml" />
<Page Include="UI\DebuggerSettingsPanel.xaml" /> <Page Include="UI\DebuggerSettingsPanel.xaml" />
<Page Include="UI\ExecuteProcessWindow.xaml" /> <Page Include="UI\ExecuteProcessWindow.xaml" />
</ItemGroup> </ItemGroup>

73
Debugger/ILSpy.Debugger/UI/BreakpointPanel.xaml

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<UserControl
x:Class="ICSharpCode.ILSpy.Debugger.UI.BreakpointPanel" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:bm="clr-namespace:ICSharpCode.ILSpy.Bookmarks">
<Grid>
<ListView
Name="view"
HorizontalContentAlignment="Stretch"
SelectionMode="Single"
MouseDoubleClick="view_MouseDoubleClick"
KeyUp="view_KeyUp">
<ListView.View>
<GridView
AllowsColumnReorder="False">
<GridViewColumn
Header="">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel
Orientation="Horizontal">
<Image
Width="16"
Height="16"
Margin="1,1,1,1"
Source="{Binding Image}"
HorizontalAlignment="Left" />
<CheckBox
Width="16"
Height="16"
Margin="3,3,3,1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
IsEnabled="{Binding CanToggle}"
IsChecked="{Binding IsEnabled}" />
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn
Header="Class">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
Text="{Binding MemberReference.DeclaringType.Name}"
Margin="1,1,1,1" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn
Header="Method">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
Text="{Binding MemberReference.Name}"
Margin="1,1,1,1" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn
Header="Line">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
Text="{Binding LineNumber}"
Margin="1,1,1,1"
HorizontalAlignment="Center" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
</UserControl>

110
Debugger/ILSpy.Debugger/UI/BreakpointPanel.xaml.cs

@ -0,0 +1,110 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.ILSpy;
using ICSharpCode.ILSpy.Bookmarks;
using ICSharpCode.ILSpy.Debugger.Bookmarks;
using ICSharpCode.ILSpy.Options;
namespace ICSharpCode.ILSpy.Debugger.UI
{
/// <summary>
/// Interaction logic for BreakpointPanel.xaml
/// </summary>
public partial class BreakpointPanel : UserControl, IPane
{
static BreakpointPanel s_instance;
public static BreakpointPanel Instance
{
get {
if (null == s_instance)
{
App.Current.VerifyAccess();
s_instance = new BreakpointPanel();
}
return s_instance;
}
}
private BreakpointPanel()
{
InitializeComponent();
}
public void Show()
{
if (!IsVisible)
{
SetItemSource();
MainWindow.Instance.ShowInBottomPane("Breakpoints", this);
BookmarkManager.Added += delegate { SetItemSource(); };
BookmarkManager.Removed += delegate { SetItemSource(); };
DebuggerSettings.Instance.PropertyChanged +=
delegate(object s, PropertyChangedEventArgs e) { if (e.PropertyName == "ShowAllBookmarks") SetItemSource(); };
}
}
private void SetItemSource()
{
view.ItemsSource = null;
if (DebuggerSettings.Instance.ShowAllBookmarks)
view.ItemsSource = BookmarkManager.Bookmarks;
else
view.ItemsSource = BookmarkManager.Bookmarks.Where(b => b is BreakpointBookmark);
}
public void Closed()
{
BookmarkManager.Added -= delegate { SetItemSource(); };
BookmarkManager.Removed -= delegate { SetItemSource(); };
DebuggerSettings.Instance.PropertyChanged -=
delegate(object s, PropertyChangedEventArgs e) { if (e.PropertyName == "ShowAllBookmarks") SetItemSource(); };
}
void view_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if (MouseButton.Left != e.ChangedButton)
return;
var selectedItem = view.SelectedItem as BookmarkBase;
if (null == selectedItem)
return;
MainWindow.Instance.JumpToReference(selectedItem.MemberReference);
MainWindow.Instance.TextView.UnfoldAndScroll(selectedItem.LineNumber);
e.Handled = true;
}
void view_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key != Key.Delete)
return;
var selectedItem = view.SelectedItem as BookmarkBase;
if (null == selectedItem)
return;
BookmarkManager.RemoveMark(selectedItem);
e.Handled = true;
}
}
[ExportMainMenuCommand(Menu="_Debugger", Header="Show _Breakpoints", MenuCategory="View", MenuOrder=8)]
public class BookmarkManagerPanelCommand : SimpleCommand
{
public override void Execute(object parameter)
{
BreakpointPanel.Instance.Show();
}
}
}

53
Debugger/ILSpy.Debugger/UI/CallStackPanel.xaml

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<UserControl
x:Class="ICSharpCode.ILSpy.Debugger.UI.CallStackPanel" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:debugger="clr-namespace:ICSharpCode.ILSpy.Debugger">
<Grid>
<ListView
Name="view"
MouseDoubleClick="view_MouseDoubleClick">
<ListView.View>
<GridView>
<GridViewColumn
Header="Module">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
Text="{Binding ModuleName}"
Foreground="{Binding FontColor}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn
Header="Name">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
Text="{Binding Name}"
Foreground="{Binding FontColor}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
<ListView.ContextMenu>
<ContextMenu>
<MenuItem
Header="Show _module names"
IsChecked="{Binding Path=ShowModuleName, Source={x:Static debugger:DebuggerSettings.Instance}, Mode=TwoWay}"
Click="SwitchIsChecked"
/>
<MenuItem
Header="Show _argument names"
IsChecked="{Binding Path=ShowArguments, Source={x:Static debugger:DebuggerSettings.Instance}, Mode=TwoWay}"
Click="SwitchIsChecked"
/>
<MenuItem
Header="Show argument _values"
IsChecked="{Binding Path=ShowArgumentValues, Source={x:Static debugger:DebuggerSettings.Instance}, Mode=TwoWay}"
Click="SwitchIsChecked"
/>
</ContextMenu>
</ListView.ContextMenu>
</ListView>
</Grid>
</UserControl>

275
Debugger/ILSpy.Debugger/UI/CallStackPanel.xaml.cs

@ -0,0 +1,275 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Xml.Linq;
using Debugger;
using ICSharpCode.ILSpy;
using ICSharpCode.ILSpy.Debugger.Models.TreeModel;
using ICSharpCode.ILSpy.Debugger.Services;
using ICSharpCode.ILSpy.XmlDoc;
using Mono.Cecil;
using Mono.CSharp;
namespace ICSharpCode.ILSpy.Debugger.UI
{
/// <summary>
/// Interaction logic for CallStackPanel.xaml
/// </summary>
public partial class CallStackPanel : UserControl, IPane
{
static CallStackPanel s_instance;
IDebugger m_currentDebugger;
public static CallStackPanel Instance
{
get {
if (null == s_instance)
{
App.Current.VerifyAccess();
s_instance = new CallStackPanel();
}
return s_instance;
}
}
private CallStackPanel()
{
InitializeComponent();
}
public void Show()
{
if (!IsVisible)
{
// load debugger settings (to update context menu)
ILSpySettings settings = ILSpySettings.Load();
DebuggerSettings.Instance.Load(settings);
DebuggerSettings.Instance.PropertyChanged += new PropertyChangedEventHandler(OnDebuggerSettingChanged);
SwitchModuleColumn();
MainWindow.Instance.ShowInBottomPane("Callstack", this);
DebuggerService.DebugStarted += new EventHandler(OnDebugStarted);
DebuggerService.DebugStopped += new EventHandler(OnDebugStopped);
if (DebuggerService.IsDebuggerStarted)
OnDebugStarted(null, EventArgs.Empty);
}
}
public void Closed()
{
DebuggerService.DebugStarted -= new EventHandler(OnDebugStarted);
DebuggerService.DebugStopped -= new EventHandler(OnDebugStopped);
if (null != m_currentDebugger)
OnDebugStopped(null, EventArgs.Empty);
// save settings
DebuggerSettings.Instance.PropertyChanged -= new PropertyChangedEventHandler(OnDebuggerSettingChanged);
ILSpySettings.Update(
delegate (XElement root) {
DebuggerSettings.Instance.Save(root);
});
}
void OnDebuggerSettingChanged(object sender, PropertyChangedEventArgs args)
{
if (args.PropertyName == "ShowModuleName") {
SwitchModuleColumn();
}
else if (args.PropertyName == "ShowArguments"
|| args.PropertyName == "ShowArgumentValues") {
RefreshPad();
}
}
void OnDebugStarted(object sender, EventArgs args)
{
m_currentDebugger = DebuggerService.CurrentDebugger;
m_currentDebugger.IsProcessRunningChanged += new EventHandler(OnProcessRunningChanged);
OnProcessRunningChanged(null, EventArgs.Empty);
}
void OnDebugStopped(object sender, EventArgs args)
{
m_currentDebugger.IsProcessRunningChanged -= new EventHandler(OnProcessRunningChanged);
m_currentDebugger = null;
view.ItemsSource = null;
}
void OnProcessRunningChanged(object sender, EventArgs args)
{
if (m_currentDebugger.IsProcessRunning)
return;
RefreshPad();
}
void SwitchModuleColumn()
{
foreach (GridViewColumn c in ((GridView)view.View).Columns) {
if ((string)c.Header == "Module") {
c.Width = DebuggerSettings.Instance.ShowModuleName ? double.NaN : 0d;
}
}
}
void RefreshPad()
{
Process debuggedProcess = ((WindowsDebugger)m_currentDebugger).DebuggedProcess;
if (debuggedProcess == null || debuggedProcess.IsRunning || debuggedProcess.SelectedThread == null) {
view.ItemsSource = null;
return;
}
IList<CallStackItem> items = null;
StackFrame activeFrame = null;
try {
Utils.DoEvents(debuggedProcess);
items = CreateItems(debuggedProcess);
activeFrame = debuggedProcess.SelectedThread.SelectedStackFrame;
} catch(AbortedBecauseDebuggeeResumedException) {
} catch(System.Exception) {
if (debuggedProcess == null || debuggedProcess.HasExited) {
// Process unexpectedly exited
} else {
throw;
}
}
view.ItemsSource = items;
view.SelectedItem = items != null ? items.FirstOrDefault(item => object.Equals(activeFrame, item.Frame)) : null;
}
IList<CallStackItem> CreateItems(Process debuggedProcess)
{
List<CallStackItem> items = new List<CallStackItem>();
foreach (StackFrame frame in debuggedProcess.SelectedThread.GetCallstack(100)) {
CallStackItem item;
// show modules names
string moduleName = frame.MethodInfo.DebugModule.ToString();
item = new CallStackItem() {
Name = GetFullName(frame), ModuleName = moduleName
};
item.Frame = frame;
items.Add(item);
Utils.DoEvents(debuggedProcess);
}
return items;
}
internal static string GetFullName(StackFrame frame)
{
// disabled by default, my be switched if options / context menu is added
bool showArgumentNames = DebuggerSettings.Instance.ShowArguments;
bool showArgumentValues = DebuggerSettings.Instance.ShowArgumentValues;
StringBuilder name = new StringBuilder();
name.Append(frame.MethodInfo.DeclaringType.FullName);
name.Append('.');
name.Append(frame.MethodInfo.Name);
if (showArgumentNames || showArgumentValues) {
name.Append("(");
for (int i = 0; i < frame.ArgumentCount; i++) {
string parameterName = null;
string argValue = null;
if (showArgumentNames) {
try {
parameterName = frame.MethodInfo.GetParameters()[i].Name;
} catch { }
if (parameterName == "") parameterName = null;
}
if (showArgumentValues) {
try {
argValue = frame.GetArgumentValue(i).AsString(100);
} catch { }
}
if (parameterName != null && argValue != null) {
name.Append(parameterName);
name.Append("=");
name.Append(argValue);
}
if (parameterName != null && argValue == null) {
name.Append(parameterName);
}
if (parameterName == null && argValue != null) {
name.Append(argValue);
}
if (parameterName == null && argValue == null) {
name.Append("Global.NA");
}
if (i < frame.ArgumentCount - 1) {
name.Append(", ");
}
}
name.Append(")");
}
return name.ToString();
}
void view_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if (MouseButton.Left != e.ChangedButton)
return;
var selectedItem = view.SelectedItem as CallStackItem;
if (null == selectedItem)
return;
var foundAssembly = MainWindow.Instance.CurrentAssemblyList.OpenAssembly(selectedItem.Frame.MethodInfo.DebugModule.FullPath);
if (null == foundAssembly || null == foundAssembly.AssemblyDefinition)
return;
MemberReference mr = XmlDocKeyProvider.FindMemberByKey(foundAssembly.AssemblyDefinition.MainModule, "M:" + selectedItem.Name);
if (mr == null)
return;
MainWindow.Instance.JumpToReference(mr);
// TODO: jump to associated line
// MainWindow.Instance.TextView.UnfoldAndScroll(selectedItem.LineNumber);
e.Handled = true;
}
void SwitchIsChecked(object sender, EventArgs args)
{
if (sender is MenuItem) {
var mi = (MenuItem)sender;
mi.IsChecked = !mi.IsChecked;
}
}
}
public class CallStackItem
{
public string Name { get; set; }
public string Language { get; set; }
public StackFrame Frame { get; set; }
public string Line { get; set; }
public string ModuleName { get; set; }
public Brush FontColor {
get { return Brushes.Black; }
}
}
[ExportMainMenuCommand(Menu="_Debugger", Header="Show _Callstack", MenuCategory="View", MenuOrder=9)]
public class CallstackPanelcommand : SimpleCommand
{
public override void Execute(object parameter)
{
CallStackPanel.Instance.Show();
}
}
}

1
Debugger/ILSpy.Debugger/UI/DebuggerSettingsPanel.xaml

@ -6,6 +6,7 @@
<StackPanel Margin="10"> <StackPanel Margin="10">
<CheckBox IsChecked="{Binding ShowWarnings}">Show warning messages</CheckBox> <CheckBox IsChecked="{Binding ShowWarnings}">Show warning messages</CheckBox>
<CheckBox IsChecked="{Binding AskForArguments}">Ask for arguments and working directory before executing a process</CheckBox> <CheckBox IsChecked="{Binding AskForArguments}">Ask for arguments and working directory before executing a process</CheckBox>
<CheckBox IsChecked="{Binding ShowAllBookmarks}">Show all bookmarks in breakpoints window</CheckBox>
</StackPanel> </StackPanel>
</Grid> </Grid>
</UserControl> </UserControl>

38
Debugger/ILSpy.Debugger/UI/DebuggerSettingsPanel.xaml.cs

@ -19,10 +19,6 @@ namespace ICSharpCode.ILSpy.Options
[ExportOptionPage(Title = "Debugger", Order = 2)] [ExportOptionPage(Title = "Debugger", Order = 2)]
partial class DebuggerSettingsPanel : UserControl, IOptionPage partial class DebuggerSettingsPanel : UserControl, IOptionPage
{ {
private const string DEBUGGER_SETTINGS = "DebuggerSettings";
private const string SHOW_WARNINGS = "showWarnings";
private const string ASK_ARGUMENTS = "askForArguments";
public DebuggerSettingsPanel() public DebuggerSettingsPanel()
{ {
InitializeComponent(); InitializeComponent();
@ -30,41 +26,15 @@ namespace ICSharpCode.ILSpy.Options
public void Load(ILSpySettings settings) public void Load(ILSpySettings settings)
{ {
this.DataContext = LoadDebuggerSettings(settings); var s = DebuggerSettings.Instance;
} s.Load(settings);
this.DataContext = s;
static DebuggerSettings currentDebuggerSettings;
public static DebuggerSettings CurrentDebuggerSettings {
get {
return currentDebuggerSettings ?? (currentDebuggerSettings = LoadDebuggerSettings(ILSpySettings.Load()));
}
}
public static DebuggerSettings LoadDebuggerSettings(ILSpySettings settings)
{
XElement e = settings[DEBUGGER_SETTINGS];
DebuggerSettings s = new DebuggerSettings();
s.ShowWarnings = (bool?)e.Attribute(SHOW_WARNINGS) ?? s.ShowWarnings;
s.AskForArguments = (bool?)e.Attribute(ASK_ARGUMENTS) ?? s.AskForArguments;
return s;
} }
public void Save(XElement root) public void Save(XElement root)
{ {
var s = (DebuggerSettings)this.DataContext; var s = (DebuggerSettings)this.DataContext;
XElement section = new XElement(DEBUGGER_SETTINGS); s.Save(root);
section.SetAttributeValue(SHOW_WARNINGS, s.ShowWarnings);
section.SetAttributeValue(ASK_ARGUMENTS, s.AskForArguments);
XElement existingElement = root.Element(DEBUGGER_SETTINGS);
if (existingElement != null)
existingElement.ReplaceWith(section);
else
root.Add(section);
currentDebuggerSettings = null; // invalidate cached settings
} }
} }
} }

56
ILSpy.SharpDevelop.LGPL/AvalonEdit/IconBarMargin.cs

@ -27,8 +27,8 @@ namespace ICSharpCode.ILSpy.AvalonEdit
public IconBarMargin(IconBarManager manager) public IconBarMargin(IconBarManager manager)
{ {
BookmarkManager.Added += delegate { InvalidateVisual(); }; BookmarkManager.Added += new BookmarkEventHandler(OnBookmarkAdded);
BookmarkManager.Removed += delegate { InvalidateVisual(); }; BookmarkManager.Removed += new BookmarkEventHandler(OnBookmarkRemoved);
this.manager = manager; this.manager = manager;
} }
@ -248,6 +248,39 @@ namespace ICSharpCode.ILSpy.AvalonEdit
} }
} }
public void OnBookmarkAdded(object sender, BookmarkEventArgs args)
{
var breakpoint = args.Bookmark as BreakpointBookmark;
if (null == breakpoint)
return;
var storage = DebugInformation.CodeMappings;
if (storage == null || storage.Count == 0)
return;
var key = breakpoint.MemberReference.MetadataToken.ToInt32();
if (storage.ContainsKey(key))
{
// register to show enabled/disabled state
breakpoint.ImageChanged += delegate { InvalidateVisual(); };
InvalidateVisual();
}
}
public void OnBookmarkRemoved(object sender, BookmarkEventArgs args)
{
var breakpoint = args.Bookmark as BreakpointBookmark;
if (null == breakpoint)
return;
var storage = DebugInformation.CodeMappings;
if (storage == null || storage.Count == 0)
return;
var key = breakpoint.MemberReference.MetadataToken.ToInt32();
if (storage.ContainsKey(key))
{
breakpoint.ImageChanged -= delegate { InvalidateVisual(); };
InvalidateVisual();
}
}
public void SyncBookmarks() public void SyncBookmarks()
{ {
var storage = DebugInformation.CodeMappings; var storage = DebugInformation.CodeMappings;
@ -256,6 +289,8 @@ namespace ICSharpCode.ILSpy.AvalonEdit
// TODO: handle other types of bookmarks // TODO: handle other types of bookmarks
// remove existing bookmarks and create new ones // remove existing bookmarks and create new ones
// update of existing bookmarks for new position does not update TextMarker
// this is only done in TextMarkerService handlers for BookmarkManager.Added/Removed
List<BreakpointBookmark> newBookmarks = new List<BreakpointBookmark>(); List<BreakpointBookmark> newBookmarks = new List<BreakpointBookmark>();
for (int i = BookmarkManager.Bookmarks.Count - 1; i >= 0; --i) { for (int i = BookmarkManager.Bookmarks.Count - 1; i >= 0; --i) {
var breakpoint = BookmarkManager.Bookmarks[i] as BreakpointBookmark; var breakpoint = BookmarkManager.Bookmarks[i] as BreakpointBookmark;
@ -264,22 +299,25 @@ namespace ICSharpCode.ILSpy.AvalonEdit
var key = breakpoint.FunctionToken; var key = breakpoint.FunctionToken;
if (!storage.ContainsKey(key)) if (!storage.ContainsKey(key))
continue; {
continue;
}
bool isMatch; bool isMatch;
SourceCodeMapping map = storage[key].GetInstructionByTokenAndOffset(key, breakpoint.ILRange.From, out isMatch); SourceCodeMapping map = storage[key].GetInstructionByTokenAndOffset(key, breakpoint.ILRange.From, out isMatch);
if (map != null) { if (map != null) {
newBookmarks.Add(new BreakpointBookmark( BreakpointBookmark newBookmark = new BreakpointBookmark(
breakpoint.MemberReference, new AstLocation(map.SourceCodeLine, 0), breakpoint.FunctionToken, breakpoint.MemberReference, new AstLocation(map.SourceCodeLine, 0), breakpoint.FunctionToken,
map.ILInstructionOffset, BreakpointAction.Break, DebugInformation.Language)); map.ILInstructionOffset, BreakpointAction.Break, DebugInformation.Language);
newBookmark.IsEnabled = breakpoint.IsEnabled;
BookmarkManager.RemoveMark(breakpoint);
newBookmarks.Add(newBookmark);
BookmarkManager.RemoveMark(breakpoint);
} }
} }
newBookmarks.ForEach(m => BookmarkManager.AddMark(m)); newBookmarks.ForEach(m => BookmarkManager.AddMark(m));
SyncCurrentLineBookmark(); SyncCurrentLineBookmark();
} }

6
ILSpy.SharpDevelop.LGPL/Bookmarks/BreakpointBookmark.cs

@ -72,6 +72,8 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
isEnabled = value; isEnabled = value;
if (IsEnabledChanged != null) if (IsEnabledChanged != null)
IsEnabledChanged(this, EventArgs.Empty); IsEnabledChanged(this, EventArgs.Empty);
if (ImageChanged != null)
ImageChanged(this, EventArgs.Empty); // Image property reflects IsEnabled property
Redraw(); Redraw();
} }
} }
@ -93,10 +95,12 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
public override ImageSource Image { public override ImageSource Image {
get { get {
return Images.Breakpoint; return IsEnabled ? Images.Breakpoint : Images.DisabledBreakpoint;
} }
} }
public event EventHandler ImageChanged;
public override ITextMarker CreateMarker(ITextMarkerService markerService, int offset, int length) public override ITextMarker CreateMarker(ITextMarkerService markerService, int offset, int length)
{ {
ITextMarker marker = markerService.Create(offset, length); ITextMarker marker = markerService.Create(offset, length);

2
ILSpy.SharpDevelop.LGPL/Bookmarks/CurrentLineBookmark.cs

@ -53,7 +53,7 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
get { return 100; } get { return 100; }
} }
public CurrentLineBookmark(MemberReference member, AstLocation location, int ilOffset) : base(member, location) private CurrentLineBookmark(MemberReference member, AstLocation location, int ilOffset) : base(member, location)
{ {
this.ILOffset = ilOffset; this.ILOffset = ilOffset;
} }

1
ILSpy.SharpDevelop.LGPL/Images.cs

@ -25,6 +25,7 @@ namespace ICSharpCode.ILSpy.SharpDevelop
} }
public static readonly BitmapImage Breakpoint = LoadBitmap("Breakpoint"); public static readonly BitmapImage Breakpoint = LoadBitmap("Breakpoint");
public static readonly BitmapImage DisabledBreakpoint = LoadBitmap("DisabledBreakpoint");
public static readonly BitmapImage CurrentLine = LoadBitmap("CurrentLine"); public static readonly BitmapImage CurrentLine = LoadBitmap("CurrentLine");
public static ImageSource GetImage(string imageName) public static ImageSource GetImage(string imageName)

13
ILSpy.SharpDevelop.LGPL/Services/DebuggerService.cs

@ -6,6 +6,7 @@ using System.Collections.Generic;
using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.ILAst; using ICSharpCode.Decompiler.ILAst;
using ICSharpCode.ILSpy;
using ICSharpCode.ILSpy.Bookmarks; using ICSharpCode.ILSpy.Bookmarks;
using ICSharpCode.ILSpy.Debugger.Bookmarks; using ICSharpCode.ILSpy.Debugger.Bookmarks;
using ICSharpCode.ILSpy.Debugger.Tooltips; using ICSharpCode.ILSpy.Debugger.Tooltips;
@ -389,7 +390,19 @@ namespace ICSharpCode.ILSpy.Debugger.Services
public static void SetDebugger(Lazy<IDebugger> debugger) public static void SetDebugger(Lazy<IDebugger> debugger)
{ {
if (currentDebugger != null)
{
currentDebugger.DebugStarting -= new EventHandler(OnDebugStarting);
currentDebugger.DebugStarted -= new EventHandler(OnDebugStarted);
currentDebugger.DebugStopped -= new EventHandler(OnDebugStopped);
}
currentDebugger = debugger.Value; currentDebugger = debugger.Value;
if (currentDebugger != null)
{
currentDebugger.DebugStarting += new EventHandler(OnDebugStarting);
currentDebugger.DebugStarted += new EventHandler(OnDebugStarted);
currentDebugger.DebugStopped += new EventHandler(OnDebugStopped);
}
} }
} }
} }

1
ILSpy/ILSpy.csproj

@ -226,6 +226,7 @@
<None Include="app.config" /> <None Include="app.config" />
<Resource Include="Images\Breakpoint.png" /> <Resource Include="Images\Breakpoint.png" />
<Resource Include="Images\CurrentLine.png" /> <Resource Include="Images\CurrentLine.png" />
<Resource Include="Images\DisabledBreakpoint.png" />
<None Include="Properties\AssemblyInfo.template.cs" /> <None Include="Properties\AssemblyInfo.template.cs" />
<Compile Include="Properties\WPFAssemblyInfo.cs" /> <Compile Include="Properties\WPFAssemblyInfo.cs" />
<Compile Include="MainWindow.xaml.cs"> <Compile Include="MainWindow.xaml.cs">

BIN
ILSpy/Images/DisabledBreakpoint.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 B

Loading…
Cancel
Save