diff --git a/Debugger/ILSpy.Debugger/Commands/DebuggerCommands.cs b/Debugger/ILSpy.Debugger/Commands/DebuggerCommands.cs index c3bbff34d..d69c8867e 100644 --- a/Debugger/ILSpy.Debugger/Commands/DebuggerCommands.cs +++ b/Debugger/ILSpy.Debugger/Commands/DebuggerCommands.cs @@ -138,7 +138,7 @@ namespace ICSharpCode.ILSpy.Debugger.Commands foreach (var item in items.First().Items.OfType()) { 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")) item.IsEnabled = enable; diff --git a/Debugger/ILSpy.Debugger/DebuggerSettings.cs b/Debugger/ILSpy.Debugger/DebuggerSettings.cs index 7072d3901..ab9f7e6d9 100644 --- a/Debugger/ILSpy.Debugger/DebuggerSettings.cs +++ b/Debugger/ILSpy.Debugger/DebuggerSettings.cs @@ -3,16 +3,73 @@ using System; using System.ComponentModel; +using System.Xml.Linq; namespace ICSharpCode.ILSpy.Debugger { public class DebuggerSettings : INotifyPropertyChanged { - bool showWarnings = true; - bool askArguments = true; - bool debugWholeTypesOnly = false; - bool showAllBookmarks = false; + #region members + private static readonly string DEBUGGER_SETTINGS = "DebuggerSettings"; + 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); + } + /// /// Show warnings messages. /// Default value is true. @@ -71,6 +128,47 @@ namespace ICSharpCode.ILSpy.Debugger } } + /// + /// Show module name in callstack panel. + /// + [DefaultValue(true)] + public bool ShowModuleName { + get { return showModuleName; } + set { + if (showModuleName != value) { + showModuleName = value; + OnPropertyChanged("ShowModuleName"); + } + } + } + + /// + /// Show module name in callstack panel. + /// + [DefaultValue(false)] + public bool ShowArguments { + get { return showArguments; } + set { + if (showArguments != value) { + showArguments = value; + OnPropertyChanged("ShowArguments"); + } + } + } + /// + /// Show module name in callstack panel. + /// + [DefaultValue(false)] + public bool ShowArgumentValues { + get { return showArgumentValues; } + set { + if (showArgumentValues != value) { + showArgumentValues = value; + OnPropertyChanged("ShowArgumentValues"); + } + } + } + public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) @@ -79,5 +177,6 @@ namespace ICSharpCode.ILSpy.Debugger PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } + } } diff --git a/Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs b/Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs index 8aa104bdd..6d3b37163 100644 --- a/Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs +++ b/Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs @@ -796,7 +796,8 @@ namespace ICSharpCode.ILSpy.Debugger.Services int line; MemberReference memberReference; - if (DebugInformation.CodeMappings.ContainsKey(token) && + if (null != DebugInformation.CodeMappings && + DebugInformation.CodeMappings.ContainsKey(token) && DebugInformation.CodeMappings[token].GetInstructionByTokenAndOffset(token, ilOffset, out memberReference, out line)) { DebugInformation.DebugStepInformation = null; // we do not need to step into/out DebuggerService.RemoveCurrentLineMarker(); diff --git a/Debugger/ILSpy.Debugger/UI/BreakpointPanel.xaml b/Debugger/ILSpy.Debugger/UI/BreakpointPanel.xaml index 8ee9f32c6..e04647066 100644 --- a/Debugger/ILSpy.Debugger/UI/BreakpointPanel.xaml +++ b/Debugger/ILSpy.Debugger/UI/BreakpointPanel.xaml @@ -1,6 +1,6 @@  + 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"> /// Interaction logic for BreakpointPanel.xaml @@ -41,23 +41,27 @@ namespace ILSpyPlugin private BreakpointPanel() { InitializeComponent(); - SetItemSource(); - BookmarkManager.Added += delegate { SetItemSource(); }; - BookmarkManager.Removed += delegate { SetItemSource(); }; - DebuggerSettingsPanel.CurrentDebuggerSettings.PropertyChanged += - delegate(object s, PropertyChangedEventArgs e) { if (e.PropertyName == "ShowAllBookmarks") SetItemSource(); }; } public void Show() { if (!IsVisible) - MainWindow.Instance.ShowInBottomPane("Breakpoints", this); + { + 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 (DebuggerSettingsPanel.CurrentDebuggerSettings.ShowAllBookmarks) + if (DebuggerSettings.Instance.ShowAllBookmarks) view.ItemsSource = BookmarkManager.Bookmarks; else view.ItemsSource = BookmarkManager.Bookmarks.Where(b => b is BreakpointBookmark); @@ -67,7 +71,7 @@ namespace ILSpyPlugin { BookmarkManager.Added -= delegate { SetItemSource(); }; BookmarkManager.Removed -= delegate { SetItemSource(); }; - DebuggerSettingsPanel.CurrentDebuggerSettings.PropertyChanged -= + DebuggerSettings.Instance.PropertyChanged -= delegate(object s, PropertyChangedEventArgs e) { if (e.PropertyName == "ShowAllBookmarks") SetItemSource(); }; } diff --git a/Debugger/ILSpy.Debugger/UI/CallStackPanel.xaml b/Debugger/ILSpy.Debugger/UI/CallStackPanel.xaml index 7e6665431..675b63af8 100644 --- a/Debugger/ILSpy.Debugger/UI/CallStackPanel.xaml +++ b/Debugger/ILSpy.Debugger/UI/CallStackPanel.xaml @@ -1,7 +1,6 @@  + 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"> + + + + + + + \ No newline at end of file diff --git a/Debugger/ILSpy.Debugger/UI/CallStackPanel.xaml.cs b/Debugger/ILSpy.Debugger/UI/CallStackPanel.xaml.cs index d7594d730..2b743841c 100644 --- a/Debugger/ILSpy.Debugger/UI/CallStackPanel.xaml.cs +++ b/Debugger/ILSpy.Debugger/UI/CallStackPanel.xaml.cs @@ -2,6 +2,7 @@ // 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; @@ -10,6 +11,7 @@ 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; @@ -17,17 +19,17 @@ using ICSharpCode.ILSpy.Debugger.Models.TreeModel; using ICSharpCode.ILSpy.Debugger.Services; using ICSharpCode.ILSpy.XmlDoc; using Mono.Cecil; +using Mono.CSharp; -namespace ILSpyPlugin +namespace ICSharpCode.ILSpy.Debugger.UI { /// /// Interaction logic for CallStackPanel.xaml /// - public partial class CallStackPanel : UserControl + public partial class CallStackPanel : UserControl, IPane { static CallStackPanel s_instance; IDebugger m_currentDebugger; - Process debuggedProcess; public static CallStackPanel Instance { @@ -44,24 +46,59 @@ namespace ILSpyPlugin private CallStackPanel() { InitializeComponent(); - - DebuggerService.DebugStarted += new EventHandler(OnDebugStarted); - DebuggerService.DebugStopped += new EventHandler(OnDebugStopped); - if (DebuggerService.IsDebuggerStarted) - OnDebugStarted(null, EventArgs.Empty); } public void Show() { if (!IsVisible) - MainWindow.Instance.ShowInBottomPane("Callstack", this); + { + // 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); - debuggedProcess = ((WindowsDebugger)m_currentDebugger).DebuggedProcess; + OnProcessRunningChanged(null, EventArgs.Empty); } @@ -69,7 +106,7 @@ namespace ILSpyPlugin { m_currentDebugger.IsProcessRunningChanged -= new EventHandler(OnProcessRunningChanged); m_currentDebugger = null; - debuggedProcess = null; + view.ItemsSource = null; } void OnProcessRunningChanged(object sender, EventArgs args) @@ -79,18 +116,28 @@ namespace ILSpyPlugin 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; } - List items = null; + IList items = null; StackFrame activeFrame = null; try { Utils.DoEvents(debuggedProcess); - items = CreateItems().ToList(); + items = CreateItems(debuggedProcess); activeFrame = debuggedProcess.SelectedThread.SelectedStackFrame; } catch(AbortedBecauseDebuggeeResumedException) { } catch(System.Exception) { @@ -104,8 +151,9 @@ namespace ILSpyPlugin view.SelectedItem = items != null ? items.FirstOrDefault(item => object.Equals(activeFrame, item.Frame)) : null; } - IEnumerable CreateItems() + IList CreateItems(Process debuggedProcess) { + List items = new List(); foreach (StackFrame frame in debuggedProcess.SelectedThread.GetCallstack(100)) { CallStackItem item; @@ -116,16 +164,17 @@ namespace ILSpyPlugin Name = GetFullName(frame), ModuleName = moduleName }; item.Frame = frame; - yield return item; + 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 = false; - bool showArgumentValues = false; + bool showArgumentNames = DebuggerSettings.Instance.ShowArguments; + bool showArgumentValues = DebuggerSettings.Instance.ShowArgumentValues; StringBuilder name = new StringBuilder(); name.Append(frame.MethodInfo.DeclaringType.FullName); @@ -179,6 +228,7 @@ namespace ILSpyPlugin 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; @@ -191,6 +241,14 @@ namespace ILSpyPlugin // 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 diff --git a/Debugger/ILSpy.Debugger/UI/DebuggerSettingsPanel.xaml.cs b/Debugger/ILSpy.Debugger/UI/DebuggerSettingsPanel.xaml.cs index 2f01e5ed9..690a2a5ce 100644 --- a/Debugger/ILSpy.Debugger/UI/DebuggerSettingsPanel.xaml.cs +++ b/Debugger/ILSpy.Debugger/UI/DebuggerSettingsPanel.xaml.cs @@ -19,11 +19,6 @@ namespace ICSharpCode.ILSpy.Options [ExportOptionPage(Title = "Debugger", Order = 2)] partial class DebuggerSettingsPanel : UserControl, IOptionPage { - private static readonly string DEBUGGER_SETTINGS = "DebuggerSettings"; - private static readonly string SHOW_WARNINGS = "showWarnings"; - private static readonly string ASK_ARGUMENTS = "askForArguments"; - private static readonly string SHOW_BOOKMARKS = "showAllBookmarks"; - public DebuggerSettingsPanel() { InitializeComponent(); @@ -31,40 +26,15 @@ namespace ICSharpCode.ILSpy.Options public void Load(ILSpySettings settings) { - this.DataContext = CurrentDebuggerSettings; - } - - 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; - s.ShowAllBookmarks = (bool?)e.Attribute(SHOW_BOOKMARKS) ?? s.ShowAllBookmarks; - return s; + var s = DebuggerSettings.Instance; + s.Load(settings); + this.DataContext = s; } public void Save(XElement root) { var s = (DebuggerSettings)this.DataContext; - XElement section = new XElement(DEBUGGER_SETTINGS); - section.SetAttributeValue(SHOW_WARNINGS, s.ShowWarnings); - section.SetAttributeValue(ASK_ARGUMENTS, s.AskForArguments); - section.SetAttributeValue(SHOW_BOOKMARKS, s.ShowAllBookmarks); - - XElement existingElement = root.Element(DEBUGGER_SETTINGS); - if (existingElement != null) - existingElement.ReplaceWith(section); - else - root.Add(section); + s.Save(root); } } } \ No newline at end of file