diff --git a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj index bd536316c0..cb9112ac80 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj +++ b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj @@ -97,6 +97,8 @@ + + DebuggingOptionsPanel.xaml Code @@ -161,7 +163,6 @@ Component - Form @@ -192,11 +193,6 @@ VisualizerPicker.xaml - - - - - @@ -209,7 +205,6 @@ - @@ -253,12 +248,10 @@ - - TextVisualizerWindow.xaml Code @@ -288,8 +281,6 @@ - - @@ -312,9 +303,6 @@ GridVisualizerWindow.xaml Code - - - @@ -324,7 +312,6 @@ - @@ -408,6 +395,7 @@ ICSharpCode.Core.WinForms False + @@ -423,7 +411,6 @@ - diff --git a/src/AddIns/Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs b/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluator.cs similarity index 98% rename from src/AddIns/Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs rename to src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluator.cs index 633d7563ab..84f5ba51fb 100644 --- a/src/AddIns/Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluator.cs @@ -15,8 +15,8 @@ namespace ICSharpCode.NRefactory.Visitors { public class EvaluateException: GetValueException { - public EvaluateException(INode code, string msg):base(code, msg) {} - public EvaluateException(INode code, string msgFmt, params string[] msgArgs):base(code, string.Format(msgFmt, msgArgs)) {} + public EvaluateException(INode code, string msg):base(msg) {} + public EvaluateException(INode code, string msgFmt, params string[] msgArgs):base(string.Format(msgFmt, msgArgs)) {} } class TypedValue @@ -163,13 +163,7 @@ namespace ICSharpCode.NRefactory.Visitors TypedValue Evaluate(INode expression, bool permRef, object data = null) { - // Try to get the value from cache - // (the cache is cleared when the process is resumed) TypedValue val; - if (context.Process.ExpressionsCache.TryGetValue(expression, out val)) { - if (val == null || !val.Value.IsInvalid) - return val; - } System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); @@ -177,11 +171,8 @@ namespace ICSharpCode.NRefactory.Visitors val = (TypedValue)expression.AcceptVisitor(this, data); if (val != null && permRef) val = new TypedValue(val.Value.GetPermanentReference(), val.Type); - } catch (GetValueException e) { - e.Expression = expression; - throw; } catch (NotImplementedException e) { - throw new GetValueException(expression, "Language feature not implemented: " + e.Message); + throw new EvaluateException(expression, "Language feature not implemented: " + e.Message); } finally { watch.Stop(); context.Process.TraceMessage("Evaluated: {0} in {1} ms total", expression.PrettyPrint(), watch.ElapsedMilliseconds); @@ -190,9 +181,6 @@ namespace ICSharpCode.NRefactory.Visitors if (val != null && val.Value.IsInvalid) throw new DebuggerException("Expression \"" + expression.PrettyPrint() + "\" is invalid right after evaluation"); - // Add the result to cache - context.Process.ExpressionsCache[expression] = val; - return val; } diff --git a/src/AddIns/Debugger/Debugger.Core/NRefactory/Ast/ExpressionExtensionMethods.cs b/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionExtensionMethods.cs similarity index 100% rename from src/AddIns/Debugger/Debugger.Core/NRefactory/Ast/ExpressionExtensionMethods.cs rename to src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionExtensionMethods.cs diff --git a/src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs b/src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs index 216aab5df9..17ab1144f6 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs @@ -28,7 +28,6 @@ namespace ICSharpCode.SharpDevelop.Services DebuggeeExceptionWindowState = FormWindowState.Normal; } - public bool ICorDebugVisualizerEnabled { get; set; } public ShowIntegersAs ShowIntegersAs { get; set; } public bool ShowArgumentNames { get; set; } public bool ShowArgumentValues { get; set; } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs index 8faa9a6054..b391df174f 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs @@ -2,18 +2,12 @@ // 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 System.Windows.Forms; - using Debugger.AddIn.Pads; using Debugger.AddIn.Pads.Controls; using Debugger.AddIn.TreeModel; using ICSharpCode.Core; -using ICSharpCode.Core.Presentation; using ICSharpCode.Core.WinForms; -using ICSharpCode.NRefactory; -using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Gui.Pads; using ICSharpCode.SharpDevelop.Project; @@ -41,11 +35,10 @@ namespace Debugger.AddIn string language = ProjectService.CurrentProject.Language; - var text = new TextNode(null, input, - language == "VB" || language == "VBNet" ? SupportedLanguage.VBNet : SupportedLanguage.CSharp).ToSharpTreeNode(); + var text = new TreeNode(input, null).ToSharpTreeNode(); var list = pad.WatchList; - if(!list.WatchItems.Any(n => text.Node.FullName == ((TreeNodeWrapper)n).Node.FullName)) + if(!list.WatchItems.Any(n => text.Node.Name == ((TreeNodeWrapper)n).Node.Name)) list.WatchItems.Add(text); } @@ -108,66 +101,4 @@ namespace Debugger.AddIn } } } - - public class WatchScriptingLanguageMenuBuilder : ISubmenuBuilder, IMenuItemBuilder - { - public ToolStripItem[] BuildSubmenu(Codon codon, object owner) - { - List items = new List(); - - if (owner is WatchPad) { - WatchPad pad = (WatchPad)owner; - - if (pad.WatchList.SelectedNode == null) - return items.ToArray(); - - var node = pad.WatchList.SelectedNode.Node; - - while (node.Parent != null && node.Parent.Parent != null) - { - node = node.Parent; - } - - if (!(node is TextNode)) - return items.ToArray(); - - foreach (string item in SupportedLanguage.GetNames(typeof(SupportedLanguage))) { - items.Add(MakeItem(item, item, node as TextNode, (sender, e) => HandleItem(sender))); - } - } - - return items.ToArray(); - } - - ToolStripMenuItem MakeItem(string title, string name, TextNode tag, EventHandler onClick) - { - ToolStripMenuItem menuItem = new ToolStripMenuItem(StringParser.Parse(title)); - menuItem.Click += onClick; - menuItem.Name = name; - menuItem.Tag = tag; - - if (name == tag.Language.ToString()) - menuItem.Checked = true; - - return menuItem; - } - - - void HandleItem(object sender) - { - ToolStripMenuItem item = null; - if (sender is ToolStripMenuItem) - item = (ToolStripMenuItem)sender; - - if (item != null) { - TextNode node = (TextNode)item.Tag; - node.Language = (SupportedLanguage)SupportedLanguage.Parse(typeof(SupportedLanguage), item.Text); - } - } - - public System.Collections.ICollection BuildItems(Codon codon, object owner) - { - return BuildSubmenu(codon, owner).TranslateToWpf(); - } - } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs index 6c8dd6ac22..3bd353e36c 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs @@ -28,22 +28,22 @@ namespace Debugger.AddIn.Pads.Controls public TreeNode Node { get; private set; } public override object Text { - get { return Node.Name; } + get { return this.Node.Name; } } public override object Icon { - get { return Node.ImageSource; } + get { return this.Node.ImageSource; } } public override bool ShowExpander { - get { return Node.HasChildNodes; } + get { return this.Node.GetChildren != null; } } protected override void LoadChildren() { - if (Node.HasChildNodes) { - ((WindowsDebugger)DebuggerService.CurrentDebugger).DebuggedProcess - .EnqueueWork(Dispatcher.CurrentDispatcher, () => Children.AddRange(Node.ChildNodes.Select(node => node.ToSharpTreeNode()))); + if (this.Node.GetChildren != null) { + var process = ((WindowsDebugger)DebuggerService.CurrentDebugger).DebuggedProcess; + process.EnqueueWork(Dispatcher.CurrentDispatcher, () => Children.AddRange(this.Node.GetChildren().Select(node => node.ToSharpTreeNode()))); } } } @@ -69,12 +69,10 @@ namespace Debugger.AddIn.Pads.Controls string language = ProjectService.CurrentProject.Language; - // FIXME languages - TextNode text = new TextNode(null, e.Data.GetData(DataFormats.StringFormat).ToString(), - language == "VB" || language == "VBNet" ? SupportedLanguage.VBNet : SupportedLanguage.CSharp); + var text = new TreeNode(e.Data.GetData(DataFormats.StringFormat).ToString(), null); var node = text.ToSharpTreeNode(); - if (!WatchPad.Instance.WatchList.WatchItems.Any(n => text.FullName == ((TreeNodeWrapper)n).Node.FullName)) + if (!WatchPad.Instance.WatchList.WatchItems.Any(n => text.Name == ((TreeNodeWrapper)n).Node.Name)) WatchPad.Instance.WatchList.WatchItems.Add(node); WatchPad.Instance.InvalidatePad(); diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs index 3b870d7418..d1fb38c508 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs @@ -71,7 +71,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads debuggedProcess.EnqueueForEach( Dispatcher.CurrentDispatcher, - new StackFrameNode(frame).ChildNodes.ToList(), + Utils.GetLocalVariableNodes(frame).ToList(), n => localVarList.WatchItems.Add(n.ToSharpTreeNode()) ); } catch (Exception ex) { diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs index 77da1ed9f5..99b236f3b1 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs @@ -17,6 +17,7 @@ using Debugger.AddIn.TreeModel; using ICSharpCode.Core; using ICSharpCode.Core.Presentation; using ICSharpCode.NRefactory; +using ICSharpCode.NRefactory.Ast; using ICSharpCode.SharpDevelop.Debugging; using ICSharpCode.SharpDevelop.Project; using Exception = System.Exception; @@ -78,29 +79,26 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads return; foreach (var element in props.Elements) { - watchList.WatchItems.Add(new TextNode(null, element, (SupportedLanguage)Enum.Parse(typeof(SupportedLanguage), props[element])).ToSharpTreeNode()); + watchList.WatchItems.Add(new TreeNode(element, null).ToSharpTreeNode()); } } void OnWatchItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { - if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems.Count > 0) { + var props = GetSavedVariablesProperties(); + if (props == null) return; + + if (e.Action == NotifyCollectionChangedAction.Add) { // add to saved data - var data = e.NewItems.OfType().FirstOrDefault(); - if (data != null) { - var props = GetSavedVariablesProperties(); - if (props == null) return; - props.Set(data.FullName, data.Language.ToString()); + foreach(var data in e.NewItems.OfType()) { + props.Set(data.Name, (object)null); } } if (e.Action == NotifyCollectionChangedAction.Remove) { // remove from saved data - var data = e.OldItems.OfType().FirstOrDefault(); - if (data != null) { - var props = GetSavedVariablesProperties(); - if (props == null) return; - props.Remove(data.FullName); + foreach(var data in e.OldItems.OfType()) { + props.Remove(data.Name); } } } @@ -162,9 +160,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads // rebuild list var nodes = new List(); foreach (var nod in watchList.WatchItems.OfType()) - nodes.Add(new TextNode(null, nod.Node.Name, - language == "VB" || language == "VBNet" ? SupportedLanguage.VBNet : SupportedLanguage.CSharp) - .ToSharpTreeNode()); + nodes.Add(new TreeNode(nod.Node.Name, null).ToSharpTreeNode()); watchList.WatchItems.Clear(); foreach (var nod in nodes) @@ -194,13 +190,13 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads { try { LoggingService.Info("Evaluating: " + (string.IsNullOrEmpty(node.Node.Name) ? "is null or empty!" : node.Node.Name)); - var nodExpression = debugger.GetExpression(node.Node.Name); + //Value val = ExpressionEvaluator.Evaluate(nod.Name, nod.Language, debuggedProcess.SelectedStackFrame); - ExpressionNode valNode = new ExpressionNode(null, null, node.Node.Name, nodExpression); + ExpressionNode valNode = new ExpressionNode(null, node.Node.Name, () => debugger.GetExpression(node.Node.Name).Evaluate(debuggedProcess)); return valNode.ToSharpTreeNode(); } catch (GetValueException) { string error = String.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.Watch.InvalidExpression}"), node.Node.Name); - ErrorInfoNode infoNode = new ErrorInfoNode(node.Node.Name, error); + TreeNode infoNode = new TreeNode("Icons.16x16.Error", node.Node.Name, error, string.Empty, null); return infoNode.ToSharpTreeNode(); } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPadModel.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPadModel.cs deleted file mode 100644 index 2357c06e6b..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPadModel.cs +++ /dev/null @@ -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 System.Text; -using Debugger.AddIn.TreeModel; -using ICSharpCode.NRefactory; -using ICSharpCode.SharpDevelop.Project; - -namespace ICSharpCode.SharpDevelop.Gui.Pads -{ - public class TextNode : TreeNode, ISetText - { - public TextNode(TreeNode parent, string text, SupportedLanguage language) - : base(parent) - { - this.Name = text; - this.Language = language; - } - - public override bool CanSetText { - get { - return true; - } - } - - public override bool SetText(string text) - { - this.Text = text; - return true; - } - - public bool SetName(string name) - { - this.Name = name; - return true; - } - - public SupportedLanguage Language { get; set; } - } - - public class ErrorInfoNode : ICorDebug.InfoNode - { - public ErrorInfoNode(string name, string text) : base(null, name, text) - { - IconImage = DebuggerResourceService.GetImage("Icons.16x16.Error"); - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs b/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs index e498cfc91d..acf29b606b 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs @@ -491,10 +491,7 @@ namespace ICSharpCode.SharpDevelop.Services { try { var tooltipExpression = GetExpression(variableName); - string imageName; - var image = ExpressionNode.GetImageForLocalVariable(out imageName); - ExpressionNode expressionNode = new ExpressionNode(null, image, variableName, tooltipExpression); - expressionNode.ImageName = imageName; + ExpressionNode expressionNode = new ExpressionNode("Icons.16x16.Local", variableName, () => tooltipExpression.Evaluate(this.DebuggedProcess)); return new DebuggerTooltipControl(logicalPosition, expressionNode) { ShowPins = debuggedProcess.GetCurrentExecutingFrame().HasSymbols }; } catch (System.Exception ex) { LoggingService.Error("Error on GetTooltipControl: " + ex.Message); @@ -505,19 +502,7 @@ namespace ICSharpCode.SharpDevelop.Services public ITreeNode GetNode(string variable, string currentImageName = null) { try { - var expression = GetExpression(variable); - string imageName; - IImage image; - if (string.IsNullOrEmpty(currentImageName)) { - image = ExpressionNode.GetImageForLocalVariable(out imageName); - } - else { - image = new ResourceServiceImage(currentImageName); - imageName = currentImageName; - } - ExpressionNode expressionNode = new ExpressionNode(null, image, variable, expression); - expressionNode.ImageName = imageName; - return expressionNode; + return new ExpressionNode(currentImageName ?? "Icons.16x16.Local", variable, () => GetExpression(variable).Evaluate(this.DebuggedProcess)); } catch (GetValueException) { return null; } @@ -827,9 +812,9 @@ namespace ICSharpCode.SharpDevelop.Services { OnIsProcessRunningChanged(EventArgs.Empty); - using(new PrintTimes("Jump to current line")) { - JumpToCurrentLine(); - } + LoggingService.Info("Jump to current line"); + JumpToCurrentLine(); + // TODO update tooltip /*if (currentTooltipRow != null && currentTooltipRow.IsShown) { using(new PrintTimes("Update tooltip")) { diff --git a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs index cd217e85b9..62f76b5141 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; @@ -228,8 +229,8 @@ namespace Debugger.AddIn.Tooltips this.childPopup.IsLeaf = true; this.childPopup.HorizontalOffset = buttonPos.X + ChildPopupOpenXOffet; this.childPopup.VerticalOffset = buttonPos.Y + ChildPopupOpenYOffet; - if (clickedNode.ChildNodes != null) { - this.childPopup.ItemsSource = clickedNode.ChildNodes; + if (clickedNode.GetChildren != null) { + this.childPopup.ItemsSource = clickedNode.GetChildren().ToList(); this.childPopup.Open(); } } else { diff --git a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinDebuggerControl.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinDebuggerControl.xaml.cs index 132d996603..a32e1a5ec9 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinDebuggerControl.xaml.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinDebuggerControl.xaml.cs @@ -4,13 +4,13 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Media.Animation; using System.Windows.Shapes; - using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Bookmarks; using ICSharpCode.SharpDevelop.Debugging; @@ -207,8 +207,8 @@ namespace Debugger.AddIn.Tooltips this.childPopup.IsLeaf = true; this.childPopup.HorizontalOffset = buttonPos.X + ChildPopupOpenXOffet; this.childPopup.VerticalOffset = buttonPos.Y + ChildPopupOpenYOffet; - if (clickedNode.ChildNodes != null) { - this.childPopup.ItemsSource = clickedNode.ChildNodes; + if (clickedNode.GetChildren != null) { + this.childPopup.ItemsSource = clickedNode.GetChildren().ToList(); this.childPopup.Open(); } } else { @@ -300,14 +300,14 @@ namespace Debugger.AddIn.Tooltips // refresh content ITreeNode node = ((FrameworkElement)e.OriginalSource).DataContext as ITreeNode; - var resultNode = currentDebugger.GetNode(node.FullName, node.ImageName); + var resultNode = currentDebugger.GetNode(node.Name, node.ImageName); if (resultNode == null) return; // HACK for updating the pins in tooltip var observable = new ObservableCollection(); var source = lazyGrid.ItemsSource; source.ForEach(item => { - if (item.CompareTo(node) == 0) + if (item.Name == node.Name) observable.Add(resultNode); else observable.Add(item); diff --git a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinningBinding.cs b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinningBinding.cs index 9811669d03..ca3282af2a 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinningBinding.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/PinningBinding.cs @@ -60,12 +60,13 @@ namespace Debugger.AddIn.Tooltips var nodes = new ObservableCollection(); foreach (var tuple in pin.SavedNodes) { - string imageName = !string.IsNullOrEmpty(tuple.Item1) ? tuple.Item1 : "Icons.16x16.Field"; - var node = new Debugger.AddIn.TreeModel.SavedTreeNode( - new ResourceServiceImage(imageName), + var node = new Debugger.AddIn.TreeModel.TreeNode( + !string.IsNullOrEmpty(tuple.Item1) ? tuple.Item1 : "Icons.16x16.Field", tuple.Item2, - tuple.Item3); - node.ImageName = imageName; + tuple.Item3, + string.Empty, + null + ); nodes.Add(node); } @@ -96,7 +97,7 @@ namespace Debugger.AddIn.Tooltips pin.SavedNodes.Add( new Tuple( "Icons.16x16.Field", - node.FullName, + node.Name, node.Text)); } diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ArrayRangeNode.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ArrayRangeNode.cs index 309071608c..15bb0d764f 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ArrayRangeNode.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ArrayRangeNode.cs @@ -10,41 +10,10 @@ using ICSharpCode.SharpDevelop.Debugging; namespace Debugger.AddIn.TreeModel { public partial class Utils - { - public static IEnumerable LazyGetChildNodesOfArray(TreeNode parent, Expression expression, ArrayDimensions dimensions) - { - if (dimensions.TotalElementCount == 0) - return new TreeNode[] { new TreeNode(null, "(empty)", null, null, parent, _ => null) }; - - return new ArrayRangeNode(parent, expression, dimensions, dimensions).ChildNodes; - } - } - - /// This is a partent node for all elements within a given bounds - public class ArrayRangeNode: TreeNode { const int MaxElementCount = 100; - Expression arrayTarget; - ArrayDimensions bounds; - ArrayDimensions originalBounds; - - public ArrayRangeNode(TreeNode parent, Expression arrayTarget, ArrayDimensions bounds, ArrayDimensions originalBounds) - : base(parent) - { - this.arrayTarget = arrayTarget; - this.bounds = bounds; - this.originalBounds = originalBounds; - - this.Name = GetName(); - this.childNodes = LazyGetChildren(); - } - - public override IEnumerable ChildNodes { - get { return base.ChildNodes; } - } - - string GetName() + public static TreeNode GetArrayRangeNode(ExpressionNode expr, ArrayDimensions bounds, ArrayDimensions originalBounds) { StringBuilder name = new StringBuilder(); bool isFirst = true; @@ -56,7 +25,7 @@ namespace Debugger.AddIn.TreeModel ArrayDimension originalDim = originalBounds[i]; if (dim.Count == 0) { - throw new DebuggerException("Empty dimension"); + name.Append("-"); } else if (dim.Count == 1) { name.Append(dim.LowerBound.ToString()); } else if (dim.Equals(originalDim)) { @@ -68,33 +37,32 @@ namespace Debugger.AddIn.TreeModel } } name.Append("]"); - return name.ToString(); + + return new TreeNode(name.ToString(), () => GetChildNodesOfArray(expr, bounds, originalBounds)); } - static string GetName(int[] indices) + public static IEnumerable GetChildNodesOfArray(ExpressionNode arrayTarget, ArrayDimensions bounds, ArrayDimensions originalBounds) { - StringBuilder sb = new StringBuilder(indices.Length * 4); - sb.Append("["); - bool isFirst = true; - foreach(int index in indices) { - if (!isFirst) sb.Append(", "); - sb.Append(index.ToString()); - isFirst = false; + if (bounds.TotalElementCount == 0) + { + yield return new TreeNode("(empty)", null); + yield break; } - sb.Append("]"); - return sb.ToString(); - } - - IEnumerable LazyGetChildren() - { + // The whole array is small - just add all elements as childs if (bounds.TotalElementCount <= MaxElementCount) { foreach(int[] indices in bounds.Indices) { - string imageName; - var image = ExpressionNode.GetImageForArrayIndexer(out imageName); - var expression = new ExpressionNode(this, image, GetName(indices), arrayTarget.AppendIndexer(indices)); - expression.ImageName = imageName; - yield return expression; + StringBuilder sb = new StringBuilder(indices.Length * 4); + sb.Append("["); + bool isFirst = true; + foreach(int index in indices) { + if (!isFirst) sb.Append(", "); + sb.Append(index.ToString()); + isFirst = false; + } + sb.Append("]"); + int[] indicesCopy = indices; + yield return new ExpressionNode("Icons.16x16.Field", sb.ToString(), () => arrayTarget.Evaluate().GetArrayElement(indicesCopy)); } yield break; } @@ -117,7 +85,7 @@ namespace Debugger.AddIn.TreeModel for(int i = splitDim.LowerBound; i <= splitDim.UpperBound; i += elementsPerSegment) { List newDims = new List(bounds); newDims[splitDimensionIndex] = new ArrayDimension(i, Math.Min(i + elementsPerSegment - 1, splitDim.UpperBound)); - yield return new ArrayRangeNode(this, arrayTarget, new ArrayDimensions(newDims), originalBounds); + yield return GetArrayRangeNode(arrayTarget, new ArrayDimensions(newDims), originalBounds); } yield break; } diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ChildNodesOfObject.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ChildNodesOfObject.cs index 7463c29cae..0a9eeff33a 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ChildNodesOfObject.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ChildNodesOfObject.cs @@ -1,10 +1,11 @@ // 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.Reflection; - +using System.Linq; using Debugger.AddIn.Visualizers.Utils; using Debugger.MetaData; using ICSharpCode.Core; @@ -17,7 +18,7 @@ namespace Debugger.AddIn.TreeModel { public partial class Utils { - public static IEnumerable LazyGetChildNodesOfObject(TreeNode current, Expression targetObject, DebugType shownType) + public static IEnumerable GetChildNodesOfObject(ExpressionNode expr, DebugType shownType) { MemberInfo[] publicStatic = shownType.GetFieldsAndNonIndexedProperties(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly); MemberInfo[] publicInstance = shownType.GetFieldsAndNonIndexedProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); @@ -27,116 +28,94 @@ namespace Debugger.AddIn.TreeModel DebugType baseType = (DebugType)shownType.BaseType; if (baseType != null) { yield return new TreeNode( - DebuggerResourceService.GetImage("Icons.16x16.Class"), + "Icons.16x16.Class", StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.BaseClass}"), baseType.Name, baseType.FullName, - current, - newNode => baseType.FullName == "System.Object" ? null : Utils.LazyGetChildNodesOfObject(newNode, targetObject, baseType) + baseType.FullName == "System.Object" ? (Func>) null : () => Utils.GetChildNodesOfObject(expr, baseType) ); } if (nonPublicInstance.Length > 0) { yield return new TreeNode( - null, StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.NonPublicMembers}"), - string.Empty, - string.Empty, - current, - newNode => Utils.LazyGetMembersOfObject(newNode, targetObject, nonPublicInstance) + () => GetMembersOfObject(expr, nonPublicInstance) ); } if (publicStatic.Length > 0 || nonPublicStatic.Length > 0) { yield return new TreeNode( - null, StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.StaticMembers}"), - string.Empty, - string.Empty, - current, - p => { - var children = Utils.LazyGetMembersOfObject(p, targetObject, publicStatic); + () => { + var children = GetMembersOfObject(expr, publicStatic).ToList(); if (nonPublicStatic.Length > 0) { - TreeNode nonPublicStaticNode = new TreeNode( - null, + children.Insert(0, new TreeNode( StringParser.Parse("${res:MainWindow.Windows.Debug.LocalVariables.NonPublicStaticMembers}"), - string.Empty, - string.Empty, - p, - newNode => Utils.LazyGetMembersOfObject(newNode, targetObject, nonPublicStatic) - ); - children = Utils.PrependNode(nonPublicStaticNode, children); + () => GetMembersOfObject(expr, nonPublicStatic) + )); } return children; } ); } - DebugType iListType = (DebugType)shownType.GetInterface(typeof(IList).FullName); - if (iListType != null) { - yield return new IListNode(current, targetObject); + if (shownType.GetInterface(typeof(IList).FullName) != null) { + yield return new TreeNode( + "IList", + () => GetItemsOfIList(() => expr.Evaluate()) + ); } else { - DebugType iEnumerableType, itemType; + DebugType listType, iEnumerableType, itemType; if (shownType.ResolveIEnumerableImplementation(out iEnumerableType, out itemType)) { - yield return new IEnumerableNode(current, targetObject, itemType); + yield return new TreeNode( + null, + "IEnumerable", + "Expanding will enumerate the IEnumerable", + string.Empty, + () => GetItemsOfIList(() => DebuggerHelpers.CreateListFromIEnumeralbe(expr.Evaluate(), itemType, out listType)) + ); } } - foreach(TreeNode node in LazyGetMembersOfObject(current, targetObject, publicInstance)) { + foreach(TreeNode node in GetMembersOfObject(expr, publicInstance)) { yield return node; } } - public static IEnumerable LazyGetMembersOfObject(TreeNode parent, Expression expression, MemberInfo[] members) + public static IEnumerable GetMembersOfObject(ExpressionNode expr, MemberInfo[] members) { - List nodes = new List(); - foreach(MemberInfo memberInfo in members) { - string imageName; - var image = ExpressionNode.GetImageForMember((IDebugMemberInfo)memberInfo, out imageName); - var exp = new ExpressionNode(parent, image, memberInfo.Name, expression.AppendMemberReference((IDebugMemberInfo)memberInfo)); - exp.ImageName = imageName; - nodes.Add(exp); + foreach(MemberInfo memberInfo in members.OrderBy(m => m.Name)) { + var memberInfoCopy = memberInfo; + string imageName = ExpressionNode.GetImageForMember((IDebugMemberInfo)memberInfo); + yield return new ExpressionNode(imageName, memberInfo.Name, () => expr.Evaluate().GetMemberValue(memberInfoCopy)); } - nodes.Sort(); - return nodes; } - - public static IEnumerable LazyGetItemsOfIList(TreeNode parent, Expression targetObject) + public static IEnumerable GetItemsOfIList(Func getValue) { - // Add a cast, so that we are sure the expression has an indexer. - // (The expression can be e.g. of type 'object' but its value is a List. - // Without the cast, evaluating "expr[i]" would fail, because object does not have an indexer). - targetObject = targetObject.CastToIList(); + Value list = null; + DebugType iListType = null; int count = 0; GetValueException error = null; try { - count = targetObject.GetIListCount(); + // We use lambda for the value just so that we can get it in this try-catch block + list = getValue().GetPermanentReference(); + iListType = (DebugType)list.Type.GetInterface(typeof(IList).FullName); + // Do not get string representation since it can be printed in hex + count = (int)list.GetPropertyValue(iListType.GetProperty("Count")).PrimitiveValue; } catch (GetValueException e) { // Cannot yield a value in the body of a catch clause (CS1631) error = e; } if (error != null) { - yield return new TreeNode(null, "(error)", error.Message, null, null, _ => null); + yield return new TreeNode(null, "(error)", error.Message, string.Empty, null); } else if (count == 0) { - yield return new TreeNode(null, "(empty)", null, null, null, _ => null); + yield return new TreeNode("(empty)", null); } else { + PropertyInfo pi = iListType.GetProperty("Item"); for(int i = 0; i < count; i++) { - string imageName; - var image = ExpressionNode.GetImageForArrayIndexer(out imageName); - var itemNode = new ExpressionNode(parent, image, "[" + i + "]", targetObject.AppendIndexer(i)); - itemNode.ImageName = imageName; - yield return itemNode; - } - } - } - - public static IEnumerable PrependNode(TreeNode node, IEnumerable rest) - { - yield return node; - if (rest != null) { - foreach(TreeNode absNode in rest) { - yield return absNode; + int iCopy = i; + yield return new ExpressionNode("Icons.16x16.Field", "[" + i + "]", () => list.GetPropertyValue(pi, Eval.CreateValue(list.AppDomain, iCopy))); } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/DebuggerResourceService.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/DebuggerResourceService.cs deleted file mode 100644 index 1f5e272874..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/DebuggerResourceService.cs +++ /dev/null @@ -1,25 +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; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Debugger.AddIn.TreeModel -{ - /// - /// Gets resources the way suitable for Debugger.AddIn. - /// - public static class DebuggerResourceService - { - /// - /// Gets image with given name from resources. - /// - /// Resource name of the image. - public static IImage GetImage(string resourceName) - { - return new ResourceServiceImage(resourceName); - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ExpressionNode.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ExpressionNode.cs index 91ab606863..2b5fdc4753 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ExpressionNode.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ExpressionNode.cs @@ -4,17 +4,18 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; - using Debugger.AddIn.Visualizers; using Debugger.MetaData; using ICSharpCode.Core; using ICSharpCode.NRefactory.Ast; +using ICSharpCode.NRefactory.Visitors; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Debugging; using ICSharpCode.SharpDevelop.Services; @@ -26,11 +27,12 @@ namespace Debugger.AddIn.TreeModel /// Node in the tree which can be defined by a debugger expression. /// The expression will be lazily evaluated when needed. /// - public class ExpressionNode: TreeNode, ISetText, INotifyPropertyChanged + public class ExpressionNode: TreeNode, INotifyPropertyChanged { bool evaluated; - Expression expression; + Func valueGetter; + Value permanentValue; bool canSetText; GetValueException error; string fullText; @@ -40,10 +42,6 @@ namespace Debugger.AddIn.TreeModel set { evaluated = value; } } - public Expression Expression { - get { return expression; } - } - public override bool CanSetText { get { if (!evaluated) EvaluateExpression(); @@ -75,12 +73,6 @@ namespace Debugger.AddIn.TreeModel } } - public override string FullName { - get { - return this.expression.PrettyPrint() ?? Name.Trim(); - } - } - public override string Type { get { if (!evaluated) EvaluateExpression(); @@ -88,17 +80,13 @@ namespace Debugger.AddIn.TreeModel } } - public override IEnumerable ChildNodes { + public override Func> GetChildren { get { if (!evaluated) EvaluateExpression(); - return base.ChildNodes; + return base.GetChildren; } - } - - public override bool HasChildNodes { - get { - if (!evaluated) EvaluateExpression(); - return base.HasChildNodes; + protected set { + base.GetChildren = value; } } @@ -136,42 +124,47 @@ namespace Debugger.AddIn.TreeModel foreach (var descriptor in VisualizerDescriptors.GetAllDescriptors()) { if (descriptor.IsVisualizerAvailable(this.expressionType)) { - yield return descriptor.CreateVisualizerCommand(this.Expression); + yield return descriptor.CreateVisualizerCommand(this.Name, () => this.Evaluate()); } } } - public ExpressionNode(TreeNode parent, IImage image, string name, Expression expression) - : base(parent) + public ExpressionNode(string imageName, string name, Func valueGetter) + : base(imageName, name, string.Empty, string.Empty, null) { - this.IconImage = image; - this.Name = name; - this.expression = expression; + this.valueGetter = valueGetter; } + /// + /// Get the value of the node and cache it as long-lived reference. + /// We assume that the user will need this value a lot. + /// + public Value Evaluate() + { + if (permanentValue == null) + { + Stopwatch watch = new Stopwatch(); + watch.Start(); + permanentValue = valueGetter().GetPermanentReference(); + LoggingService.InfoFormatted("Evaluated node '{0}' in {1} ms (result cached for future use)", this.Name, watch.ElapsedMilliseconds); + } + return permanentValue; + } + + /// + /// Get the value of the node and update the UI text fields. + /// void EvaluateExpression() { evaluated = true; + Stopwatch watch = new Stopwatch(); + watch.Start(); + Value val; try { - var process = WindowsDebugger.DebuggedProcess; - if (process == null) return; - StackFrame frame = process.GetCurrentExecutingFrame(); - if (frame == null) return; - var debugger = (WindowsDebugger)DebuggerService.CurrentDebugger; - object data = debugger.debuggerDecompilerService.GetLocalVariableIndex(frame.MethodInfo.DeclaringType.MetadataToken, - frame.MethodInfo.MetadataToken, - Name); - - if (expression is MemberReferenceExpression) { - var memberExpression = (MemberReferenceExpression)expression; - memberExpression.TargetObject.UserData = data; - } else { - expression.UserData = data; - } - // evaluate expression - val = expression.Evaluate(process); + // Do not keep permanent reference + val = valueGetter(); } catch (GetValueException e) { error = e; this.Text = e.Message; @@ -188,27 +181,24 @@ namespace Debugger.AddIn.TreeModel if (val.IsNull) { } else if (val.Type.IsPrimitive || val.Type.FullName == typeof(string).FullName) { // Must be before IsClass } else if (val.Type.IsArray) { // Must be before IsClass - if (val.ArrayLength > 0) - this.childNodes = Utils.LazyGetChildNodesOfArray(this, this.Expression, val.ArrayDimensions); + if (val.ArrayLength > 0) { + var dims = val.ArrayDimensions; // Eval now + this.GetChildren = () => Utils.GetChildNodesOfArray(this, dims, dims); + } } else if (val.Type.IsClass || val.Type.IsValueType) { if (val.Type.FullNameWithoutGenericArguments == typeof(List<>).FullName) { if ((int)val.GetMemberValue("_size").PrimitiveValue > 0) - this.childNodes = Utils.LazyGetItemsOfIList(this, this.expression); + this.GetChildren = () => Utils.GetItemsOfIList(() => this.Evaluate()); } else { - this.childNodes = Utils.LazyGetChildNodesOfObject(this, this.Expression, val.Type); + this.GetChildren = () => Utils.GetChildNodesOfObject(this, val.Type); } } else if (val.Type.IsPointer) { Value deRef = val.Dereference(); if (deRef != null) { - this.childNodes = new ExpressionNode [] { new ExpressionNode(this, this.IconImage, "*" + this.Name, this.Expression.AppendDereference()) }; + this.GetChildren = () => new ExpressionNode [] { new ExpressionNode(this.ImageName, "*" + this.Name, () => this.Evaluate().Dereference()) }; } } - if (DebuggingOptions.Instance.ICorDebugVisualizerEnabled) { - TreeNode info = ICorDebug.GetDebugInfoRoot(val.AppDomain, val.CorValue); - this.childNodes = Utils.PrependNode(info, this.ChildNodes); - } - // Do last since it may expire the object if (val.Type.IsInteger) { fullText = FormatInteger(val.PrimitiveValue); @@ -236,6 +226,8 @@ namespace Debugger.AddIn.TreeModel } this.Text = (fullText.Length > 256) ? fullText.Substring(0, 256) + "..." : fullText; + + LoggingService.InfoFormatted("Evaluated node '{0}' in {1} ms", this.Name, watch.ElapsedMilliseconds); } string Escape(string source) @@ -308,11 +300,9 @@ namespace Debugger.AddIn.TreeModel public override bool SetText(string newText) { - string fullName = FullName; - Value val = null; try { - val = this.Expression.Evaluate(WindowsDebugger.DebuggedProcess); + val = this.Evaluate(); if (val.Type.IsInteger && newText.StartsWith("0x")) { try { val.PrimitiveValue = long.Parse(newText.Substring(2), NumberStyles.HexNumber); @@ -339,33 +329,10 @@ namespace Debugger.AddIn.TreeModel return false; } - public static IImage GetImageForThis(out string imageName) - { - imageName = "Icons.16x16.Parameter"; - return DebuggerResourceService.GetImage(imageName); - } - - public static IImage GetImageForParameter(out string imageName) - { - imageName = "Icons.16x16.Parameter"; - return DebuggerResourceService.GetImage(imageName); - } - - public static IImage GetImageForLocalVariable(out string imageName) - { - imageName = "Icons.16x16.Local"; - return DebuggerResourceService.GetImage(imageName); - } - - public static IImage GetImageForArrayIndexer(out string imageName) - { - imageName = "Icons.16x16.Field"; - return DebuggerResourceService.GetImage(imageName); - } - - public static IImage GetImageForMember(IDebugMemberInfo memberInfo, out string imageName) + public static string GetImageForMember(IDebugMemberInfo memberInfo) { string name = string.Empty; + if (memberInfo.IsPublic) { } else if (memberInfo.IsAssembly) { name += "Internal"; @@ -374,6 +341,7 @@ namespace Debugger.AddIn.TreeModel } else if (memberInfo.IsPrivate) { name += "Private"; } + if (memberInfo is FieldInfo) { name += "Field"; } else if (memberInfo is PropertyInfo) { @@ -384,8 +352,7 @@ namespace Debugger.AddIn.TreeModel throw new DebuggerException("Unknown member type " + memberInfo.GetType().FullName); } - imageName = "Icons.16x16." + name; - return DebuggerResourceService.GetImage(imageName); + return "Icons.16x16." + name; } // public ContextMenuStrip GetContextMenu() diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/IContextMenu.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/IContextMenu.cs deleted file mode 100644 index 0830a6d0b9..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/IContextMenu.cs +++ /dev/null @@ -1,12 +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.Windows.Forms; - -namespace Debugger.AddIn.TreeModel -{ - public interface IContextMenu - { - ContextMenuStrip GetContextMenu(); - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ICorDebug.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ICorDebug.cs deleted file mode 100644 index fe054da52d..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ICorDebug.cs +++ /dev/null @@ -1,158 +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 Debugger.Interop.CorDebug; -using System; -using System.Collections.Generic; -using Debugger.MetaData; -using ICSharpCode.SharpDevelop.Debugging; - -namespace Debugger.AddIn.TreeModel -{ - public class ICorDebug - { - public class InfoNode: TreeNode - { - List children; - - public InfoNode(TreeNode parent, string name, string text) - : this(parent, name, text, _ => null) - { - - } - - public InfoNode(TreeNode parent, string name, string text, Func> children) - : base(parent) - { - this.Name = name; - this.Text = text; - this.children = children(this); - } - - public override IEnumerable ChildNodes { - get { return children; } - } - - public void AddChild(string name, string text) - { - if (children == null) { - children = new List(); - } - children.Add(new InfoNode(this, name, text)); - } - - public void AddChild(string name, string text, Func> subChildren) - { - if (children == null) { - children = new List(); - } - children.Add(new InfoNode(this, name, text, p => subChildren(p))); - } - } - - public static InfoNode GetDebugInfoRoot(AppDomain appDomain, ICorDebugValue corValue) - { - return new InfoNode(null, "ICorDebug", "", p => GetDebugInfo(p, appDomain, corValue)); - } - - public static List GetDebugInfo(TreeNode parent, AppDomain appDomain, ICorDebugValue corValue) - { - List items = new List(); - - if (corValue is ICorDebugValue) { - InfoNode info = new InfoNode(parent, "ICorDebugValue", ""); - info.AddChild("Address", corValue.GetAddress().ToString("X8")); - info.AddChild("Type", ((CorElementType)corValue.GetTheType()).ToString()); - info.AddChild("Size", corValue.GetSize().ToString()); - items.Add(info); - } - if (corValue is ICorDebugValue2) { - InfoNode info = new InfoNode(parent, "ICorDebugValue2", ""); - ICorDebugValue2 corValue2 = (ICorDebugValue2)corValue; - string fullname; - try { - fullname = DebugType.CreateFromCorType(appDomain, corValue2.GetExactType()).FullName; - } catch (DebuggerException e) { - fullname = e.Message; - } - info.AddChild("ExactType", fullname); - items.Add(info); - } - if (corValue is ICorDebugGenericValue) { - InfoNode info = new InfoNode(parent, "ICorDebugGenericValue", ""); - try { - byte[] bytes = ((ICorDebugGenericValue)corValue).GetRawValue(); - for(int i = 0; i < bytes.Length; i += 8) { - string val = ""; - for(int j = i; j < bytes.Length && j < i + 8; j++) { - val += bytes[j].ToString("X2") + " "; - } - info.AddChild("Value" + i.ToString("X2"), val); - } - } catch (ArgumentException) { - info.AddChild("Value", "N/A"); - } - items.Add(info); - } - if (corValue is ICorDebugReferenceValue) { - InfoNode info = new InfoNode(parent, "ICorDebugReferenceValue", ""); - ICorDebugReferenceValue refValue = (ICorDebugReferenceValue)corValue; - info.AddChild("IsNull", (refValue.IsNull() != 0).ToString()); - if (refValue.IsNull() == 0) { - info.AddChild("Value", refValue.GetValue().ToString("X8")); - if (refValue.Dereference() != null) { - info.AddChild("Dereference", "", p => GetDebugInfo(p, appDomain, refValue.Dereference())); - } else { - info.AddChild("Dereference", "N/A"); - } - } - items.Add(info); - } - if (corValue is ICorDebugHeapValue) { - InfoNode info = new InfoNode(parent, "ICorDebugHeapValue", ""); - items.Add(info); - } - if (corValue is ICorDebugHeapValue2) { - InfoNode info = new InfoNode(parent, "ICorDebugHeapValue2", ""); - items.Add(info); - } - if (corValue is ICorDebugObjectValue) { - InfoNode info = new InfoNode(parent, "ICorDebugObjectValue", ""); - ICorDebugObjectValue objValue = (ICorDebugObjectValue)corValue; - info.AddChild("Class", objValue.GetClass().GetToken().ToString("X8")); - info.AddChild("IsValueClass", (objValue.IsValueClass() != 0).ToString()); - items.Add(info); - } - if (corValue is ICorDebugObjectValue2) { - InfoNode info = new InfoNode(parent, "ICorDebugObjectValue2", ""); - items.Add(info); - } - if (corValue is ICorDebugBoxValue) { - InfoNode info = new InfoNode(parent, "ICorDebugBoxValue", ""); - ICorDebugBoxValue boxValue = (ICorDebugBoxValue)corValue; - info.AddChild("Object", "", p => GetDebugInfo(p, appDomain, boxValue.GetObject())); - items.Add(info); - } - if (corValue is ICorDebugStringValue) { - InfoNode info = new InfoNode(parent, "ICorDebugStringValue", ""); - ICorDebugStringValue stringValue = (ICorDebugStringValue)corValue; - info.AddChild("Length", stringValue.GetLength().ToString()); - info.AddChild("String", stringValue.GetString()); - items.Add(info); - } - if (corValue is ICorDebugArrayValue) { - InfoNode info = new InfoNode(parent, "ICorDebugArrayValue", ""); - info.AddChild("...", "..."); - items.Add(info); - } - if (corValue is ICorDebugHandleValue) { - InfoNode info = new InfoNode(parent, "ICorDebugHandleValue", ""); - ICorDebugHandleValue handleValue = (ICorDebugHandleValue)corValue; - info.AddChild("HandleType", handleValue.GetHandleType().ToString()); - items.Add(info); - } - - return items; - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/IEnumerableNode.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/IEnumerableNode.cs deleted file mode 100644 index 35845151c9..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/IEnumerableNode.cs +++ /dev/null @@ -1,32 +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.AddIn.Visualizers.Utils; -using Debugger.MetaData; -using ICSharpCode.NRefactory.Ast; -using ICSharpCode.SharpDevelop.Debugging; - -namespace Debugger.AddIn.TreeModel -{ - /// - /// IEnumerable node in the variable tree. - /// - public class IEnumerableNode : TreeNode - { - Expression targetObject; - Expression debugListExpression; - - public IEnumerableNode(TreeNode parent, Expression targetObject, DebugType itemType) - : base(parent) - { - this.targetObject = targetObject; - - this.Name = "IEnumerable"; - this.Text = "Expanding will enumerate the IEnumerable"; - DebugType debugListType; - this.debugListExpression = DebuggerHelpers.CreateDebugListExpression(targetObject, itemType, out debugListType); - this.childNodes = Utils.LazyGetItemsOfIList(this, this.debugListExpression); - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/IListNode.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/IListNode.cs deleted file mode 100644 index 41d21d86ac..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/IListNode.cs +++ /dev/null @@ -1,33 +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 Debugger.AddIn.Visualizers.Utils; -using ICSharpCode.NRefactory.Ast; -using System.Collections; -using System.Collections.Generic; -using Debugger.MetaData; -using ICSharpCode.SharpDevelop.Debugging; -using ICSharpCode.SharpDevelop.Services; - -namespace Debugger.AddIn.TreeModel -{ - public class IListNode : TreeNode - { - Expression targetList; - int listCount; - - public IListNode(TreeNode parent, Expression targetListObject) - : base(parent) - { - this.targetList = targetListObject; - - this.Name = "IList"; - this.listCount = this.targetList.GetIListCount(); - this.childNodes = Utils.LazyGetItemsOfIList(this, this.targetList); - } - - public override bool HasChildNodes { - get { return this.listCount > 0; } - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ISetText.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ISetText.cs deleted file mode 100644 index 99978cd589..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ISetText.cs +++ /dev/null @@ -1,12 +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) - -namespace Debugger.AddIn.TreeModel -{ - public interface ISetText - { - bool CanSetText { get; } - - bool SetText(string text); - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/SavedTreeNode.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/SavedTreeNode.cs deleted file mode 100644 index 40a6e5bb5d..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/SavedTreeNode.cs +++ /dev/null @@ -1,31 +0,0 @@ -// 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 ICSharpCode.SharpDevelop; - -namespace Debugger.AddIn.TreeModel -{ - /// - /// Description of SavedTreeNode. - /// - public class SavedTreeNode : TreeNode - { - public override bool CanSetText { - get { return true; } - } - - public SavedTreeNode(IImage image, string fullname, string text) - : base(null) - { - base.IconImage = image; - FullName = fullname; - Text = text; - } - - public override bool SetText(string newValue) { - Text = newValue; - return false; - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/StackFrameNode.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/StackFrameNode.cs index 176b2d0d26..9c002e1358 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/StackFrameNode.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/StackFrameNode.cs @@ -11,56 +11,32 @@ using ICSharpCode.SharpDevelop.Services; namespace Debugger.AddIn.TreeModel { - public class StackFrameNode: TreeNode + public partial class Utils { - StackFrame stackFrame; - - public StackFrame StackFrame { - get { return stackFrame; } - } - - public StackFrameNode(StackFrame stackFrame) - : base(null) - { - this.stackFrame = stackFrame; - - this.Name = stackFrame.MethodInfo.Name; - this.childNodes = LazyGetChildNodes(); - } - - IEnumerable LazyGetChildNodes() + public static IEnumerable GetLocalVariableNodes(StackFrame stackFrame) { foreach(DebugParameterInfo par in stackFrame.MethodInfo.GetParameters()) { - string imageName; - var image = ExpressionNode.GetImageForParameter(out imageName); - var expression = new ExpressionNode(this, image, par.Name, par.GetExpression()); - expression.ImageName = imageName; - yield return expression; + var parCopy = par; + yield return new ExpressionNode("Icons.16x16.Parameter", par.Name, () => parCopy.GetValue(stackFrame)); } - if (this.stackFrame.HasSymbols) { - foreach(DebugLocalVariableInfo locVar in stackFrame.MethodInfo.GetLocalVariables(this.StackFrame.IP)) { - string imageName; - var image = ExpressionNode.GetImageForLocalVariable(out imageName); - var expression = new ExpressionNode(this, image, locVar.Name, locVar.GetExpression()); - expression.ImageName = imageName; - yield return expression; + if (stackFrame.HasSymbols) { + foreach(DebugLocalVariableInfo locVar in stackFrame.MethodInfo.GetLocalVariables(stackFrame.IP)) { + var locVarCopy = locVar; + yield return new ExpressionNode("Icons.16x16.Local", locVar.Name, () => locVarCopy.GetValue(stackFrame)); } } else { WindowsDebugger debugger = (WindowsDebugger)DebuggerService.CurrentDebugger; if (debugger.debuggerDecompilerService != null) { - int typeToken = this.stackFrame.MethodInfo.DeclaringType.MetadataToken; - int methodToken = this.stackFrame.MethodInfo.MetadataToken; + int typeToken = stackFrame.MethodInfo.DeclaringType.MetadataToken; + int methodToken = stackFrame.MethodInfo.MetadataToken; foreach (var localVar in debugger.debuggerDecompilerService.GetLocalVariables(typeToken, methodToken)) { - string imageName; - var image = ExpressionNode.GetImageForLocalVariable(out imageName); - var expression = new ExpressionNode(this, image, localVar, ExpressionEvaluator.ParseExpression(localVar, SupportedLanguage.CSharp)); - expression.ImageName = imageName; - yield return expression; + int index = ((int[])debugger.debuggerDecompilerService.GetLocalVariableIndex(typeToken, methodToken, localVar))[0]; + yield return new ExpressionNode("Icons.16x16.Local", localVar, () => stackFrame.GetLocalVariableValue((uint)index)); } } } if (stackFrame.Thread.CurrentException != null) { - yield return new ExpressionNode(this, null, "__exception", new IdentifierExpression("__exception")); + yield return new ExpressionNode(null, "$exception", () => stackFrame.Thread.CurrentException.Value); } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/TreeNode.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/TreeNode.cs index d00eb1df01..4bdabbdb65 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/TreeNode.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/TreeNode.cs @@ -15,31 +15,22 @@ namespace Debugger.AddIn.TreeModel { /// /// A node in the variable tree. - /// The node is immutable. /// public class TreeNode : ITreeNode { - IImage iconImage = null; - string name = string.Empty; - string imageName = string.Empty; - string text = string.Empty; - string type = string.Empty; - protected IEnumerable childNodes = null; - - /// - /// The image displayed for this node. - /// - public IImage IconImage { - get { return iconImage; } - protected set { iconImage = value; } - } + public IImage IconImage { get; protected set; } + public string ImageName { get; set; } + public string Name { get; set; } + public virtual string Text { get; set; } + public virtual string Type { get; protected set; } + public virtual Func> GetChildren { get; protected set; } /// /// System.Windows.Media.ImageSource version of . /// public ImageSource ImageSource { get { - return iconImage == null ? null : iconImage.ImageSource; + return this.IconImage == null ? null : this.IconImage.ImageSource; } } @@ -48,54 +39,26 @@ namespace Debugger.AddIn.TreeModel /// public Image Image { get { - return iconImage == null ? null : iconImage.Bitmap; + return this.IconImage == null ? null : this.IconImage.Bitmap; } } - public string Name { - get { return name; } - set { name = value; } - } - - public string ImageName { - get { return imageName; } - set { imageName = value; } - } - - public virtual string FullName { - get { return name; } - set { name = value; } - } - - public virtual string Text - { - get { return text; } - set { text = value; } - } - - public virtual string Type { - get { return type; } - protected set { type = value; } - } - - public virtual TreeNode Parent { get; protected set; } - - public virtual IEnumerable ChildNodes { - get { return childNodes; } + public virtual bool CanSetText { + get { return false; } } - IEnumerable ITreeNode.ChildNodes { - get { return childNodes; } + Func> ITreeNode.GetChildren { + get { + if (this.GetChildren == null) + return null; + return () => this.GetChildren(); + } } public virtual bool HasChildNodes { - get { return childNodes != null; } - } - - public virtual bool CanSetText { - get { return false; } + get { return this.GetChildren != null; } } - + public virtual IEnumerable VisualizerCommands { get { return null; @@ -110,41 +73,21 @@ namespace Debugger.AddIn.TreeModel public bool IsPinned { get; set; } - public TreeNode(TreeNode parent) - { - this.Parent = parent; - } - - public TreeNode(IImage iconImage, string name, string text, string type, TreeNode parent, Func> childNodes) - : this(parent) - { - if (childNodes == null) - throw new ArgumentNullException("childNodes"); - this.iconImage = iconImage; - this.name = name; - this.text = text; - this.type = type; - this.childNodes = childNodes(this); - } - - #region Equals and GetHashCode implementation - public override bool Equals(object obj) + public TreeNode(string name, Func> getChildren) { - TreeNode other = obj as TreeNode; - if (other == null) - return false; - return this.FullName == other.FullName; + this.Name = name; + this.GetChildren = getChildren; } - public override int GetHashCode() - { - return this.FullName.GetHashCode(); - } - #endregion - - public int CompareTo(ITreeNode other) + public TreeNode(string imageName, string name, string text, string type, Func> getChildren) { - return this.FullName.CompareTo(other.FullName); + this.ImageName = imageName; + if (imageName != null) + this.IconImage = new ResourceServiceImage(imageName); + this.Name = name; + this.Text = text; + this.Type = type; + this.GetChildren = getChildren; } public virtual bool SetText(string newValue) { diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/ExpressionVisualizerCommand.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/ExpressionVisualizerCommand.cs index 0a77ff8d44..daf3fffc81 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/ExpressionVisualizerCommand.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/ExpressionVisualizerCommand.cs @@ -16,11 +16,15 @@ namespace Debugger.AddIn.Visualizers // should we make visualizer command available for Expression, or any TreeNode? public abstract class ExpressionVisualizerCommand : IVisualizerCommand { - public Expression Expression { get; private set; } + public string ValueName { get; private set; } + public Func GetValue { get; private set; } - public ExpressionVisualizerCommand(Expression expression) + public ExpressionVisualizerCommand(string valueName, Func getValue) { - this.Expression = expression; + if (getValue == null) + throw new ArgumentNullException("getValue"); + this.ValueName = valueName; + this.GetValue = getValue; } public abstract void Execute(); diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/GridVisualizerCommand.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/GridVisualizerCommand.cs index 5a62f133ee..5387c98922 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/GridVisualizerCommand.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/GridVisualizerCommand.cs @@ -25,9 +25,9 @@ namespace Debugger.AddIn.Visualizers return type.ResolveIEnumerableImplementation(out collectionType, out itemType); } - public IVisualizerCommand CreateVisualizerCommand(Expression expression) + public IVisualizerCommand CreateVisualizerCommand(string valueName, Func getValue) { - return new GridVisualizerCommand(expression); + return new GridVisualizerCommand(valueName, getValue); } } @@ -36,8 +36,7 @@ namespace Debugger.AddIn.Visualizers /// public class GridVisualizerCommand : ExpressionVisualizerCommand { - public GridVisualizerCommand(Expression expression) - :base(expression) + public GridVisualizerCommand(string valueName, Func getValue) : base(valueName, getValue) { } @@ -48,10 +47,8 @@ namespace Debugger.AddIn.Visualizers public override void Execute() { - if (this.Expression == null) - return; - var gridVisualizerWindow = GridVisualizerWindow.EnsureShown(); - gridVisualizerWindow.ShownExpression = this.Expression; + GridVisualizerWindow window = new GridVisualizerWindow(this.ValueName, this.GetValue); + window.ShowDialog(); } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/GridVisualizerMenuCommand.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/GridVisualizerMenuCommand.cs index c4dcbefcbf..2b480fc5c6 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/GridVisualizerMenuCommand.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/GridVisualizerMenuCommand.cs @@ -14,9 +14,7 @@ namespace Debugger.AddIn.Visualizers { public override void Run() { - GridVisualizerWindow window = new GridVisualizerWindow(); - window.Topmost = true; - window.Show(); + } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/IVisualizerDescriptor.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/IVisualizerDescriptor.cs index 3ffb8114f9..b87da05866 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/IVisualizerDescriptor.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/IVisualizerDescriptor.cs @@ -16,6 +16,6 @@ namespace Debugger.AddIn.Visualizers public interface IVisualizerDescriptor { bool IsVisualizerAvailable(DebugType type); - IVisualizerCommand CreateVisualizerCommand(Expression expression); + IVisualizerCommand CreateVisualizerCommand(string valueName, Func getValue); } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/ObjectGraphVisualizerCommand.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/ObjectGraphVisualizerCommand.cs index 877880b5e8..a12f9aeb4e 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/ObjectGraphVisualizerCommand.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/ObjectGraphVisualizerCommand.cs @@ -21,9 +21,9 @@ namespace Debugger.AddIn.Visualizers return !type.IsAtomic() && !type.IsSystemDotObject(); } - public IVisualizerCommand CreateVisualizerCommand(Expression expression) + public IVisualizerCommand CreateVisualizerCommand(string valueName, Func getValue) { - return new ObjectGraphVisualizerCommand(expression); + return new ObjectGraphVisualizerCommand(valueName, getValue); } } @@ -32,8 +32,7 @@ namespace Debugger.AddIn.Visualizers /// public class ObjectGraphVisualizerCommand : ExpressionVisualizerCommand { - public ObjectGraphVisualizerCommand(Expression expression) - :base(expression) + public ObjectGraphVisualizerCommand(string valueName, Func getValue) : base(valueName, getValue) { } @@ -44,10 +43,9 @@ namespace Debugger.AddIn.Visualizers public override void Execute() { - if (this.Expression == null) - return; var objectGraphWindow = ObjectGraphWindow.EnsureShown(); - objectGraphWindow.ShownExpression = this.Expression; + // TODO: This only works on the root level + objectGraphWindow.ShownExpression = new IdentifierExpression(this.ValueName); } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/TextVisualizerCommand.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/TextVisualizerCommand.cs index 7b1747882d..1c31cc2df6 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/TextVisualizerCommand.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/TextVisualizerCommand.cs @@ -20,16 +20,15 @@ namespace Debugger.AddIn.Visualizers return type.FullName == typeof(string).FullName; } - public IVisualizerCommand CreateVisualizerCommand(Expression expression) + public IVisualizerCommand CreateVisualizerCommand(string valueName, Func getValue) { - return new TextVisualizerCommand(expression); + return new TextVisualizerCommand(valueName, getValue); } } public class TextVisualizerCommand : ExpressionVisualizerCommand { - public TextVisualizerCommand(Expression expression) - :base(expression) + public TextVisualizerCommand(string valueName, Func getValue) : base(valueName, getValue) { } @@ -40,10 +39,7 @@ namespace Debugger.AddIn.Visualizers public override void Execute() { - if (this.Expression == null) - return; - string expressionValue = this.Expression.Evaluate(WindowsDebugger.CurrentProcess).AsString(); - var textVisualizerWindow = new TextVisualizerWindow(this.Expression.PrettyPrint(), expressionValue); + var textVisualizerWindow = new TextVisualizerWindow(this.ValueName, this.GetValue().AsString()); textVisualizerWindow.ShowDialog(); } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/XmlVisualizerCommand.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/XmlVisualizerCommand.cs index 77f8ba988e..665e002482 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/XmlVisualizerCommand.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Commands/XmlVisualizerCommand.cs @@ -20,9 +20,9 @@ namespace Debugger.AddIn.Visualizers return type.FullName == typeof(string).FullName; } - public IVisualizerCommand CreateVisualizerCommand(Expression expression) + public IVisualizerCommand CreateVisualizerCommand(string valueName, Func getValue) { - return new XmlVisualizerCommand(expression); + return new XmlVisualizerCommand(valueName, getValue); } } @@ -31,8 +31,7 @@ namespace Debugger.AddIn.Visualizers /// public class XmlVisualizerCommand : ExpressionVisualizerCommand { - public XmlVisualizerCommand(Expression expression) - :base(expression) + public XmlVisualizerCommand(string valueName, Func getValue) : base(valueName, getValue) { } @@ -43,11 +42,7 @@ namespace Debugger.AddIn.Visualizers public override void Execute() { - if (this.Expression == null) - return; - var textVisualizerWindow = new TextVisualizerWindow( - this.Expression.PrettyPrint(), this.Expression.Evaluate(WindowsDebugger.CurrentProcess).AsString()); - textVisualizerWindow.Mode = TextVisualizerMode.Xml; + var textVisualizerWindow = new TextVisualizerWindow(this.ValueName, this.GetValue().AsString(), ".xml"); textVisualizerWindow.ShowDialog(); } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Common/IListValuesProvider.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Common/IListValuesProvider.cs deleted file mode 100644 index d373860ad4..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Common/IListValuesProvider.cs +++ /dev/null @@ -1,16 +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; - -namespace Debugger.AddIn.Visualizers -{ - /// - /// Can provide individial items for a lazy collection, as well as total count of items. - /// - public interface IListValuesProvider - { - int GetCount(); - T GetItemAt(int index); - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Common/VirtualizingCollection.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Common/VirtualizingCollection.cs index 6ec03cb2ab..cb87dcb028 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Common/VirtualizingCollection.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Common/VirtualizingCollection.cs @@ -8,21 +8,23 @@ using System.Collections.Generic; namespace Debugger.AddIn.Visualizers { /// - /// IList<T> with data vitualization - the indexer is lazy, uses IListValuesProvider to obtain values when needed. + /// IList<T> with data vitualization - the indexer is lazy, uses lamda function to obtain values when needed. /// public class VirtualizingCollection : IList, IList { - private IListValuesProvider valueProvider; - private Dictionary itemCache = new Dictionary(); + int count; + Func getItem; + Dictionary itemCache = new Dictionary(); - public VirtualizingCollection(IListValuesProvider valueProvider) + public VirtualizingCollection(int count, Func getItem) { - this.valueProvider = valueProvider; + this.count = count; + this.getItem = getItem; } public int Count { - get { return this.valueProvider.GetCount(); } + get { return count; } } public T this[int index] @@ -32,7 +34,7 @@ namespace Debugger.AddIn.Visualizers T cachedItem; if (!itemCache.TryGetValue(index, out cachedItem)) { - cachedItem = this.valueProvider.GetItemAt(index); + cachedItem = getItem(index); this.itemCache[index] = cachedItem; } return cachedItem; diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/TreeModel/ContentPropertyNode.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/TreeModel/ContentPropertyNode.cs index 53b4a1e2db..53b7b1c643 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/TreeModel/ContentPropertyNode.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/Layout/TreeModel/ContentPropertyNode.cs @@ -6,6 +6,7 @@ using System.ComponentModel; using Debugger.AddIn.TreeModel; using Debugger.AddIn.Visualizers.Graph.Drawing; using Debugger.MetaData; +using ICSharpCode.SharpDevelop; namespace Debugger.AddIn.Visualizers.Graph.Layout { @@ -77,8 +78,7 @@ namespace Debugger.AddIn.Visualizers.Graph.Layout if ((this.Property != null) && (this.Property.ObjectGraphProperty != null)) { var memberInfo = (IDebugMemberInfo)this.Property.ObjectGraphProperty.MemberInfo; if (memberInfo != null) { - string imageName; - var image = ExpressionNode.GetImageForMember(memberInfo, out imageName); + var image = new ResourceServiceImage(ExpressionNode.GetImageForMember(memberInfo)); this.MemberIcon = image.ImageSource; } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml index 664da36dd7..954552e85d 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml @@ -27,9 +27,6 @@ - Expression: - - diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs index 80703cd997..d03a78198a 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs @@ -2,26 +2,16 @@ // 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.Linq; using System.Reflection; -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 Debugger.AddIn.TreeModel; + using Debugger.AddIn.Visualizers.PresentationBindings; using Debugger.AddIn.Visualizers.Utils; using Debugger.MetaData; using ICSharpCode.Core; -using ICSharpCode.NRefactory.Ast; using ICSharpCode.SharpDevelop; -using ICSharpCode.SharpDevelop.Debugging; -using ICSharpCode.SharpDevelop.Services; namespace Debugger.AddIn.Visualizers.GridVisualizer { @@ -30,160 +20,93 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer /// public partial class GridVisualizerWindow : Window { - WindowsDebugger debuggerService; - GridViewColumnHider columnHider; + Func getValue; - public GridVisualizerWindow() + public GridVisualizerWindow(string valueName, Func getValue) { InitializeComponent(); - this.debuggerService = DebuggerService.CurrentDebugger as WindowsDebugger; - if (debuggerService == null) - throw new ApplicationException("Only windows debugger is currently supported"); + this.Title = valueName; + this.getValue = getValue; - instance = this; - this.Deactivated += GridVisualizerWindow_Deactivated; - } - - void GridVisualizerWindow_Deactivated(object sender, EventArgs e) - { - this.Close(); - } - - private ICSharpCode.NRefactory.Ast.Expression shownExpression; - public ICSharpCode.NRefactory.Ast.Expression ShownExpression - { - get { - return shownExpression; - } - set { - if (value == null) { - shownExpression = null; - txtExpression.Text = null; - - Refresh(); - return; - } - if (shownExpression == null || value.PrettyPrint() != shownExpression.PrettyPrint()) { - txtExpression.Text = value.PrettyPrint(); - Refresh(); - } - } - } - - static GridVisualizerWindow instance; - /// When Window is visible, returns reference to the Window. Otherwise returns null. - public static GridVisualizerWindow Instance - { - get { return instance; } - } - - public static GridVisualizerWindow EnsureShown() - { - var window = GridVisualizerWindow.Instance ?? new GridVisualizerWindow(); - window.Topmost = true; - window.Show(); - return window; - } - - protected override void OnClosing(System.ComponentModel.CancelEventArgs e) - { - this.Deactivated -= GridVisualizerWindow_Deactivated; - base.OnClosing(e); - } - - protected override void OnClosed(EventArgs e) - { - base.OnClosed(e); - instance = null; - } - - private void btnInspect_Click(object sender, RoutedEventArgs e) - { Refresh(); } - + public void Refresh() { - try { + try { // clear ListView listView.ItemsSource = null; - ScrollViewer listViewScroller = listView.GetScrollViewer(); - if (listViewScroller != null) { - listViewScroller.ScrollToVerticalOffset(0); - } - Value shownValue = null; - ICSharpCode.NRefactory.Ast.Expression shownExpr = null; - try { - shownExpr = debuggerService.GetExpression(txtExpression.Text); - shownValue = shownExpr.Evaluate(debuggerService.DebuggedProcess); - } catch(GetValueException e) { - MessageService.ShowMessage(e.Message); - } - if (shownValue != null && !shownValue.IsNull) { - GridValuesProvider gridValuesProvider; - // Value is IList - DebugType iListType, listItemType; - if (shownValue.Type.ResolveIListImplementation(out iListType, out listItemType)) { - gridValuesProvider = CreateListValuesProvider(shownExpr.CastToIList(), listItemType); + + Value shownValue = getValue(); + + DebugType iListType, iEnumerableType, itemType; + // Value is IList + if (shownValue.Type.ResolveIListImplementation(out iListType, out itemType)) { + // Ok + } else { + // Value is IEnumerable + if (shownValue.Type.ResolveIEnumerableImplementation(out iEnumerableType, out itemType)) { + shownValue = DebuggerHelpers.CreateListFromIEnumeralbe(shownValue, itemType, out iListType); } else { - // Value is IEnumerable - DebugType iEnumerableType, itemType; - if (shownValue.Type.ResolveIEnumerableImplementation(out iEnumerableType, out itemType)) { - DebugType debugListType; - var debugListExpression = DebuggerHelpers.CreateDebugListExpression(shownExpr, itemType, out debugListType); - gridValuesProvider = CreateListValuesProvider(debugListExpression, itemType); - } else { - // Not IList or IEnumerable - can't be displayed in GridVisualizer - return; - } + // Not IList or IEnumerable - can't be displayed in GridVisualizer + return; } - - IList itemTypeMembers = gridValuesProvider.GetItemTypeMembers(); - InitializeColumns((GridView)this.listView.View, itemTypeMembers); - this.columnHider = new GridViewColumnHider((GridView)this.listView.View); - cmbColumns.ItemsSource = this.columnHider.HideableColumns; } - } catch (GetValueException e) { - MessageService.ShowMessage(e.Message); - } catch (DebuggerVisualizerException e) { + shownValue = shownValue.GetPermanentReference(); + + MemberInfo[] members = itemType.GetFieldsAndNonIndexedProperties(BindingFlags.Public | BindingFlags.Instance); + PropertyInfo itemGetter = iListType.GetProperty("Item"); + int rowCount = (int)shownValue.GetPropertyValue(iListType.GetProperty("Count")).PrimitiveValue; + int columnCount = members.Length + 1; + + var rowCollection = new VirtualizingCollection>( + rowCount, + (rowIndex) => new VirtualizingCollection( + columnCount, + (columnIndex) => { + if (columnIndex == members.Length) + return "[" + rowIndex + "]"; + try { + var rowValue = shownValue.GetPropertyValue(itemGetter, Eval.CreateValue(shownValue.AppDomain, rowIndex)); + return rowValue.GetMemberValue(members[columnIndex]).InvokeToString(); + } catch (GetValueException e) { + return "Exception: " + e.Message; + } + } + ) + ); + this.listView.ItemsSource = rowCollection; + + InitializeColumns((GridView)this.listView.View, members); + + GridViewColumnHider columnHider = new GridViewColumnHider((GridView)this.listView.View); + cmbColumns.ItemsSource = columnHider.HideableColumns; + + } catch(GetValueException e) { MessageService.ShowMessage(e.Message); } } - ListValuesProvider CreateListValuesProvider(ICSharpCode.NRefactory.Ast.Expression targetExpression, DebugType listItemType) - { - var listValuesProvider = new ListValuesProvider(targetExpression, listItemType); - var virtCollection = new VirtualizingCollection(listValuesProvider); - this.listView.ItemsSource = virtCollection; - return listValuesProvider; - } - - void InitializeColumns(GridView gridView, IList itemTypeMembers) + void InitializeColumns(GridView gridView, MemberInfo[] members) { gridView.Columns.Clear(); - AddIndexColumn(gridView); - AddMembersColumns(gridView, itemTypeMembers); - } - - void AddIndexColumn(GridView gridView) - { + + // Index column var indexColumn = new GridViewHideableColumn(); indexColumn.CanBeHidden = false; indexColumn.Width = 36; indexColumn.Header = string.Empty; - indexColumn.DisplayMemberBinding = new Binding("Index"); + indexColumn.DisplayMemberBinding = new Binding("[" + members.Length + "]"); gridView.Columns.Add(indexColumn); - } - - void AddMembersColumns(GridView gridView, IList itemTypeMembers) - { - foreach (var member in itemTypeMembers) { + + // Member columns + for (int i = 0; i < members.Length; i++) { var memberColumn = new GridViewHideableColumn(); memberColumn.CanBeHidden = true; - memberColumn.Header = member.Name; - // "{Binding Path=[Name].Value}" - memberColumn.DisplayMemberBinding = new Binding("[" + member.Name + "].Value"); + memberColumn.Header = members[i].Name; + memberColumn.IsVisibleDefault = ((IDebugMemberInfo)members[i]).IsPublic; + memberColumn.DisplayMemberBinding = new Binding("[" + i + "]"); gridView.Columns.Add(memberColumn); } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ObjectValue.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ObjectValue.cs deleted file mode 100644 index 6663528bca..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ObjectValue.cs +++ /dev/null @@ -1,85 +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.Generic; -using Debugger.AddIn.Visualizers.Utils; -using Debugger.MetaData; -using ICSharpCode.NRefactory.Ast; -using ICSharpCode.SharpDevelop.Services; -using System.Reflection; - -namespace Debugger.AddIn.Visualizers.GridVisualizer -{ - /// - /// Item of a collection in the debugee, with lazy evaluated properties. - /// - public class ObjectValue - { - /// Index of this item in the collection. - public int Index { get; private set; } - - // PermanentReference for one row. - public Value PermanentReference { get; private set; } - - private Dictionary properties = new Dictionary(); - - /// Used to quickly find MemberInfo by member name - DebugType.GetMember(name) uses a loop to search members - private Dictionary memberForNameMap; - - internal ObjectValue(int index, Dictionary memberFromNameMap) - { - this.Index = index; - this.memberForNameMap = memberFromNameMap; - } - - /// - /// Returns property with given name. - /// - public ObjectProperty this[string propertyName] - { - get - { - ObjectProperty property; - // has property with name 'propertyName' already been evaluated? - if(!this.properties.TryGetValue(propertyName, out property)) - { - if (this.PermanentReference == null) { - throw new DebuggerVisualizerException("Cannot get member of this ObjectValue - ObjectValue.PermanentReference is null"); - } - MemberInfo memberInfo = this.memberForNameMap.GetValue(propertyName); - if (memberInfo == null) { - throw new DebuggerVisualizerException("Cannot get member value - no member found with name " + propertyName); - } - property = CreatePropertyFromValue(propertyName, this.PermanentReference.GetMemberValue(memberInfo)); - this.properties.Add(propertyName, property); - } - return property; - } - } - - public static ObjectValue Create(Debugger.Value value, int index, Dictionary memberFromName) - { - ObjectValue result = new ObjectValue(index, memberFromName); - - // remember PermanentReference for expanding IEnumerable - Value permanentReference = value.GetPermanentReference(); - result.PermanentReference = permanentReference; - - return result; - } - - private static ObjectProperty CreatePropertyFromValue(string propertyName, Value value) - { - ObjectProperty property = new ObjectProperty(); - property.Name = propertyName; - // property.Expression = ?.Age - // - cannot use expression, - // if the value is returned from an enumerator, it has no meaningful expression - property.IsAtomic = value.Type.IsPrimitive; - property.IsNull = value.IsNull; - property.Value = value.IsNull ? "" : value.InvokeToString(); - return property; - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/EnumerableValuesProvider.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/EnumerableValuesProvider.cs deleted file mode 100644 index 09b9a5cf9f..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/EnumerableValuesProvider.cs +++ /dev/null @@ -1,50 +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 Debugger.AddIn.Visualizers.Utils; -using Debugger.MetaData; -using ICSharpCode.Core; -using ICSharpCode.NRefactory.Ast; -using ICSharpCode.SharpDevelop.Services; -using System.Reflection; - -namespace Debugger.AddIn.Visualizers.GridVisualizer -{ - /// - /// Provides s for debugee objects implementing IEnumerable. - /// - /*public class EnumerableValuesProvider : GridValuesProvider - { - public EnumerableValuesProvider(Expression targetObject, DebugType iEnumerableType, DebugType itemType) - :base(targetObject, iEnumerableType, itemType) - { - this.itemsSource = enumerateItems(); - } - - private IEnumerable itemsSource; - public IEnumerable ItemsSource - { - get { return this.itemsSource; } - } - - private IEnumerable enumerateItems() - { - MethodInfo enumeratorMethod = collectionType.GetMethod("GetEnumerator"); - Value enumerator = targetObject.Evaluate(WindowsDebugger.CurrentProcess).InvokeMethod(enumeratorMethod, null).GetPermanentReference(); - - MethodInfo moveNextMethod = enumerator.Type.GetMethod("MoveNext"); - PropertyInfo currentproperty = enumerator.Type.GetInterface(typeof(IEnumerator).FullName).GetProperty("Current"); - - int index = 0; - while ((bool)enumerator.InvokeMethod(moveNextMethod, null).PrimitiveValue) - { - Value currentValue = enumerator.GetPropertyValue(currentproperty); - yield return ObjectValue.Create(currentValue, index++, this.memberFromNameMap); - } - } - }*/ -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/GridValuesProvider.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/GridValuesProvider.cs deleted file mode 100644 index f656934db6..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/GridValuesProvider.cs +++ /dev/null @@ -1,42 +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.Generic; -using Debugger.AddIn.Visualizers.Utils; -using Debugger.MetaData; -using ICSharpCode.NRefactory.Ast; -using System.Reflection; - -namespace Debugger.AddIn.Visualizers.GridVisualizer -{ - /// - /// Provides s to be displayed in Grid visualizer. - /// Descandants implement getting values for IList and IEnumerable. - /// - public class GridValuesProvider - { - /// Used to quickly find MemberInfo by member name - DebugType.GetMember(name) uses a loop to search members - protected Dictionary memberFromNameMap; - - protected Expression targetObject; - protected DebugType itemType; - - public GridValuesProvider(Expression targetObject, DebugType itemType) - { - this.targetObject = targetObject; - this.itemType = itemType; - - this.memberFromNameMap = this.GetItemTypeMembers().MakeDictionary(memberInfo => memberInfo.Name); - } - - /// - /// Gets members that will be displayed as columns. - /// - public IList GetItemTypeMembers() - { - var publicPropetiesAndFields = itemType.GetFieldsAndNonIndexedProperties(BindingFlags.Public | BindingFlags.Instance); - return publicPropetiesAndFields; - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs deleted file mode 100644 index 457566d0cf..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs +++ /dev/null @@ -1,59 +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.Generic; -using System.Linq; -using System.Reflection; -using Debugger.AddIn.Visualizers.Utils; -using Debugger.MetaData; -using ICSharpCode.Core; -using ICSharpCode.NRefactory.Ast; -using ICSharpCode.SharpDevelop.Services; - -namespace Debugger.AddIn.Visualizers.GridVisualizer -{ - /// - /// Provides s for debugee objects implementing IList. - /// - public class ListValuesProvider : GridValuesProvider, IListValuesProvider - { - int? listCount = null; - /// - /// After evaluating how many items to clear debugger Expression cache, - /// so that the cache does not keep too many PermanentReferences. - /// - static readonly int ClearCacheThreshold = 50; - - public ListValuesProvider(Expression targetObject, DebugType listItemType) - :base(targetObject, listItemType) - { - } - - public int GetCount() - { - if (this.listCount == null) { - this.listCount = this.targetObject.GetIListCount(); - } - return this.listCount.Value; - } - - /// When this reaches ClearCacheThreshold, the debugger Expression cache is cleared. - int itemClearCacheCounter = 0; - - public ObjectValue GetItemAt(int index) - { - if (itemClearCacheCounter++ > ClearCacheThreshold) { - // clear debugger Expression cache to avoid holding too many PermanentReferences - WindowsDebugger.CurrentProcess.ClearExpressionCache(); - LoggingService.Info("Cleared debugger Expression cache."); - itemClearCacheCounter = 0; - } - return ObjectValue.Create( - targetObject.AppendIndexer(index).Evaluate(WindowsDebugger.CurrentProcess), - //targetObject.AppendIndexer(index), // use Expression instead of value - possible only for IList though - index, - this.memberFromNameMap); - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/TextVisualizer/TextVisualizerMode.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/TextVisualizer/TextVisualizerMode.cs deleted file mode 100644 index f084773b26..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/TextVisualizer/TextVisualizerMode.cs +++ /dev/null @@ -1,12 +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.Collections.Generic; -using System.Linq; -using System; - -public enum TextVisualizerMode -{ - PlainText, - Xml -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/TextVisualizer/TextVisualizerWindow.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/TextVisualizer/TextVisualizerWindow.xaml.cs index 56c8a75dc3..ab35e503ca 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/TextVisualizer/TextVisualizerWindow.xaml.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/TextVisualizer/TextVisualizerWindow.xaml.cs @@ -1,17 +1,9 @@ // 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.AvalonEdit.Highlighting; using System; -using System.Collections.Generic; -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.AvalonEdit.Highlighting; namespace Debugger.AddIn.Visualizers.TextVisualizer { @@ -20,42 +12,14 @@ namespace Debugger.AddIn.Visualizers.TextVisualizer /// public partial class TextVisualizerWindow : Window { - public TextVisualizerWindow() - { - InitializeComponent(); - Mode = TextVisualizerMode.PlainText; - textEditor.IsReadOnly = true; - } - - public TextVisualizerWindow(string title, string text) + public TextVisualizerWindow(string title, string text, string highlighting = null) { InitializeComponent(); - Title= title; - Text = text; - } - - public string Text - { - get { return this.textEditor.Text; } - set { this.textEditor.Text = value; } - } - - private TextVisualizerMode mode; - public TextVisualizerMode Mode - { - get { return mode; } - set { - mode = value; - switch (mode) { - case TextVisualizerMode.PlainText: - textEditor.SyntaxHighlighting = null; - break; - case TextVisualizerMode.Xml: - textEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinitionByExtension(".xml"); - break; - } - } + Title = title; + this.textEditor.Text = text; + if (highlighting != null) + this.textEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinitionByExtension(highlighting); } void CheckBox_CheckedChanged(object sender, RoutedEventArgs e) diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs index c962d91625..ba4e3c4136 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs @@ -33,6 +33,17 @@ namespace Debugger.AddIn.Visualizers.Utils return new ObjectCreateExpression(listType.GetTypeReference(), iEnumerableVariableExplicitCast.SingleItemList()); } + + public static Value CreateListFromIEnumeralbe(Value iEnumerableValue, DebugType itemType, out DebugType listType) + { + listType = DebugType.CreateFromType(iEnumerableValue.AppDomain, typeof(System.Collections.Generic.List<>), itemType); + DebugType iEnumerableType = DebugType.CreateFromType(itemType.AppDomain, typeof(IEnumerable<>), itemType); + ConstructorInfo ctor = listType.GetConstructor(BindingFlags.Default, null, CallingConventions.Any, new System.Type[] { iEnumerableType }, null); + if (ctor == null) + throw new DebuggerException("List constructor not found"); + return (Value)ctor.Invoke(new object[] { iEnumerableValue }); + } + /// /// Gets underlying address of object in the debuggee. /// @@ -120,7 +131,7 @@ namespace Debugger.AddIn.Visualizers.Utils Value list = targetObject.Evaluate(WindowsDebugger.CurrentProcess); var iCollectionType = list.Type.GetInterface(typeof(System.Collections.ICollection).FullName); if (iCollectionType == null) - throw new GetValueException(targetObject, targetObject.PrettyPrint() + " does not implement System.Collections.ICollection"); + throw new GetValueException("Object does not implement System.Collections.ICollection"); // Do not get string representation since it can be printed in hex return (int)list.GetPropertyValue(iCollectionType.GetProperty("Count")).PrimitiveValue; } diff --git a/src/AddIns/Debugger/Debugger.Core/Debugger.Core.csproj b/src/AddIns/Debugger/Debugger.Core/Debugger.Core.csproj index d59af38cff..3b6c2aa1ea 100644 --- a/src/AddIns/Debugger/Debugger.Core/Debugger.Core.csproj +++ b/src/AddIns/Debugger/Debugger.Core/Debugger.Core.csproj @@ -144,8 +144,6 @@ - - @@ -198,17 +196,7 @@ - - - - - - {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195} - NRefactory - False - - \ No newline at end of file diff --git a/src/AddIns/Debugger/Debugger.Core/Eval.cs b/src/AddIns/Debugger/Debugger.Core/Eval.cs index 4c70596375..497d36c378 100644 --- a/src/AddIns/Debugger/Debugger.Core/Eval.cs +++ b/src/AddIns/Debugger/Debugger.Core/Eval.cs @@ -273,24 +273,24 @@ namespace Debugger ); } - public static Value CreateValue(AppDomain appDomain, object value) - { - if (value == null) { + public static Value CreateValue(AppDomain appDomain, object value) + { + if (value == null) { ICorDebugClass corClass = appDomain.ObjectType.CorType.GetClass(); Thread thread = GetEvaluationThread(appDomain); ICorDebugEval corEval = thread.CorThread.CreateEval(); ICorDebugValue corValue = corEval.CreateValue((uint)CorElementType.CLASS, corClass); return new Value(appDomain, corValue); } else if (value is string) { - return Eval.NewString(appDomain, (string)value); + return Eval.NewString(appDomain, (string)value); } else { - if (!value.GetType().IsPrimitive) - throw new DebuggerException("Value must be primitve type. Seen " + value.GetType()); + if (!value.GetType().IsPrimitive) + throw new DebuggerException("Value must be primitve type. Seen " + value.GetType()); Value val = Eval.NewObjectNoConstructor(DebugType.CreateFromType(appDomain.Mscorlib, value.GetType())); val.PrimitiveValue = value; return val; } - } + } /* // The following function create values only for the purpuse of evalutaion diff --git a/src/AddIns/Debugger/Debugger.Core/GetValueException.cs b/src/AddIns/Debugger/Debugger.Core/GetValueException.cs index a1adb2fa4f..0183d9d199 100644 --- a/src/AddIns/Debugger/Debugger.Core/GetValueException.cs +++ b/src/AddIns/Debugger/Debugger.Core/GetValueException.cs @@ -2,55 +2,21 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; -using ICSharpCode.NRefactory.Ast; namespace Debugger { public class GetValueException: DebuggerException { - INode expression; - string error; - - /// Expression that has caused this exception to occur - public INode Expression { - get { return expression; } - set { expression = value; } - } - - public string Error { - get { return error; } - } - - public override string Message { - get { - if (expression == null) { - return error; - } else { - return error; - // return String.Format("Error evaluating \"{0}\": {1}", expression.PrettyPrint(), error); - } - } - } - - public GetValueException(INode expression, string error):base(error) - { - this.expression = expression; - this.error = error; - } - public GetValueException(string error, System.Exception inner):base(error, inner) { - this.error = error; } public GetValueException(string errorFmt, params object[] args):base(string.Format(errorFmt, args)) { - this.error = string.Format(errorFmt, args); } public GetValueException(string error):base(error) { - this.error = error; } } } diff --git a/src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs b/src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs index 1ac7c330b5..d0076d569d 100644 --- a/src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs +++ b/src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs @@ -246,14 +246,14 @@ namespace Debugger public void EvalException(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugEval corEval) { - EnterCallback(PausedReason.EvalComplete, "EvalException", pThread); + EnterCallback(PausedReason.EvalComplete, "EvalException (" + process.ActiveEvals[corEval].Description + ")", pThread); HandleEvalComplete(pAppDomain, pThread, corEval, true); } public void EvalComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugEval corEval) { - EnterCallback(PausedReason.EvalComplete, "EvalComplete", pThread); + EnterCallback(PausedReason.EvalComplete, "EvalComplete (" + process.ActiveEvals[corEval].Description + ")", pThread); HandleEvalComplete(pAppDomain, pThread, corEval, false); } diff --git a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs index 37a0fed063..4e6b8e15d3 100644 --- a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs +++ b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs @@ -639,7 +639,7 @@ namespace Debugger.MetaData { List vars = new List(); foreach (ISymUnmanagedVariable symVar in symScope.GetLocals()) { - ISymUnmanagedVariable symVarCopy = symVar; + uint address = (uint)symVar.GetAddressField1(); int start; SignatureReader sigReader = new SignatureReader(symVar.GetSignature()); LocalVarSig.LocalVariable locVarSig = sigReader.ReadLocalVariable(sigReader.Blob, 0, out start); @@ -654,7 +654,7 @@ namespace Debugger.MetaData (int)symScope.GetStartOffset(), (int)symScope.GetEndOffset(), delegate(StackFrame context) { - return GetLocalVariableValue(context, symVarCopy); + return context.GetLocalVariableValue(address); }, locVarType ); @@ -668,7 +668,7 @@ namespace Debugger.MetaData (int)symScope.GetEndOffset(), locVarType, delegate(StackFrame context) { - return GetLocalVariableValue(context, symVarCopy); + return context.GetLocalVariableValue(address); } ); vars.Add(locVar); @@ -680,18 +680,6 @@ namespace Debugger.MetaData return vars; } - static Value GetLocalVariableValue(StackFrame context, ISymUnmanagedVariable symVar) - { - ICorDebugValue corVal; - try { - corVal = context.CorILFrame.GetLocalVariable((uint)symVar.GetAddressField1()); - } catch (COMException e) { - if ((uint)e.ErrorCode == 0x80131304) throw new GetValueException("Unavailable in optimized code"); - throw; - } - return new Value(context.AppDomain, corVal); - } - /// public override string ToString() { diff --git a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugType.cs b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugType.cs index fa6b205543..a152d02dba 100644 --- a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugType.cs +++ b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugType.cs @@ -9,7 +9,6 @@ using System.Text; using Debugger.Interop.CorDebug; using Debugger.Interop.MetaData; -using ICSharpCode.NRefactory.Ast; using Mono.Cecil.Signatures; namespace Debugger.MetaData diff --git a/src/AddIns/Debugger/Debugger.Core/Process.cs b/src/AddIns/Debugger/Debugger.Core/Process.cs index 3ca68f7a06..933ecdb8f4 100644 --- a/src/AddIns/Debugger/Debugger.Core/Process.cs +++ b/src/AddIns/Debugger/Debugger.Core/Process.cs @@ -7,8 +7,6 @@ using System.Runtime.InteropServices; using Debugger.Interop.CorDebug; using Debugger.Interop.CorSym; -using ICSharpCode.NRefactory.Ast; -using ICSharpCode.NRefactory.Visitors; namespace Debugger { @@ -251,7 +249,6 @@ namespace Debugger internal bool TerminateCommandIssued = false; internal Queue BreakpointHitEventQueue = new Queue(); - internal Dictionary ExpressionsCache = new Dictionary(); #region Events @@ -330,7 +327,6 @@ namespace Debugger if (action == DebuggeeStateAction.Clear) { if (debuggeeState == null) throw new DebuggerException("Debugee state already cleared"); debuggeeState = null; - this.ExpressionsCache.Clear(); } } @@ -557,19 +553,6 @@ namespace Debugger // This is done once ExitProcess callback is received } - /// - /// Clears the internal Expression cache used too speed up Expression evaluation. - /// Use this if your code evaluates expressions in a way which would cause - /// the cache to grow too large. The cache holds PermanentReferences so it - /// shouldn't grow larger than a few hundred items. - /// - public void ClearExpressionCache() - { - if (this.ExpressionsCache != null ){ - this.ExpressionsCache.Clear(); - } - } - void SelectSomeThread() { if (this.SelectedThread != null && !this.SelectedThread.IsInValidState) { diff --git a/src/AddIns/Debugger/Debugger.Core/StackFrame.cs b/src/AddIns/Debugger/Debugger.Core/StackFrame.cs index 0b6cf9e53b..6e96d8dee8 100644 --- a/src/AddIns/Debugger/Debugger.Core/StackFrame.cs +++ b/src/AddIns/Debugger/Debugger.Core/StackFrame.cs @@ -380,6 +380,16 @@ namespace Debugger return loc.GetValue(this); } + public Value GetLocalVariableValue(uint address) + { + try { + return new Value(this.AppDomain, this.CorILFrame.GetLocalVariable(address)); + } catch (COMException e) { + if ((uint)e.ErrorCode == 0x80131304) throw new GetValueException("Unavailable in optimized code"); + throw; + } + } + /// Get instance of 'this'. It works well with delegates and enumerators. [Debugger.Tests.Ignore] public Value GetLocalVariableThis() diff --git a/src/AddIns/Debugger/Debugger.Core/Value.cs b/src/AddIns/Debugger/Debugger.Core/Value.cs index e104f05c19..25b51d861b 100644 --- a/src/AddIns/Debugger/Debugger.Core/Value.cs +++ b/src/AddIns/Debugger/Debugger.Core/Value.cs @@ -613,6 +613,7 @@ namespace Debugger /// Invoke the ToString() method public string InvokeToString(int maxLength = int.MaxValue) { + if (this.IsNull) return AsString(maxLength); if (this.Type.IsPrimitive) return AsString(maxLength); if (this.Type.FullName == typeof(string).FullName) return AsString(maxLength); if (this.Type.IsPointer) return "0x" + this.PointerAddress.ToString("X"); diff --git a/src/AddIns/Debugger/Debugger.Tests/Debugger.Tests.csproj b/src/AddIns/Debugger/Debugger.Tests/Debugger.Tests.csproj index 82684e0616..9c117cdddf 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Debugger.Tests.csproj +++ b/src/AddIns/Debugger/Debugger.Tests/Debugger.Tests.csproj @@ -77,6 +77,10 @@ {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195} NRefactory + + {EC06F96A-AEEC-49D6-B03D-AB87C6EB674C} + Debugger.AddIn + {1D18D788-F7EE-4585-A23B-34DC8EC63CB8} Debugger.Core diff --git a/src/Main/Base/Project/Src/Bookmarks/BookmarkConverter.cs b/src/Main/Base/Project/Src/Bookmarks/BookmarkConverter.cs index 5424a6551d..4df0ee1db7 100644 --- a/src/Main/Base/Project/Src/Bookmarks/BookmarkConverter.cs +++ b/src/Main/Base/Project/Src/Bookmarks/BookmarkConverter.cs @@ -152,7 +152,7 @@ namespace ICSharpCode.SharpDevelop.Bookmarks b.Append('|'); b.Append(node.ImageName); b.Append('|'); - b.Append(node.FullName); + b.Append(node.Name); b.Append('|'); b.Append(node.Text); } diff --git a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/ITreeNode.cs b/src/Main/Base/Project/Src/Services/Debugger/Tooltips/ITreeNode.cs index 59762e5870..6beb519b07 100644 --- a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/ITreeNode.cs +++ b/src/Main/Base/Project/Src/Services/Debugger/Tooltips/ITreeNode.cs @@ -10,14 +10,12 @@ namespace ICSharpCode.SharpDevelop.Debugging /// /// Node that can be bound to . /// - public interface ITreeNode : IComparable + public interface ITreeNode { - string Name { get; } - - string FullName { get; } - string ImageName { get; } + string Name { get; } + string Text { get; } bool CanSetText { get; } @@ -26,9 +24,7 @@ namespace ICSharpCode.SharpDevelop.Debugging ImageSource ImageSource { get; } - IEnumerable ChildNodes { get; } - - bool HasChildNodes { get; } + Func> GetChildren { get; } IEnumerable VisualizerCommands { get; } diff --git a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/PinBookmark.cs b/src/Main/Base/Project/Src/Services/Debugger/Tooltips/PinBookmark.cs index 7a422636a0..a26defcd4b 100644 --- a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/PinBookmark.cs +++ b/src/Main/Base/Project/Src/Services/Debugger/Tooltips/PinBookmark.cs @@ -77,7 +77,7 @@ namespace ICSharpCode.SharpDevelop.Bookmarks throw new ArgumentNullException("Node is null"); foreach (var currentNode in mark.Nodes) { - if (node.FullName == currentNode.FullName) + if (node.Name == currentNode.Name) return true; } @@ -92,7 +92,7 @@ namespace ICSharpCode.SharpDevelop.Bookmarks throw new ArgumentNullException("Node is null"); foreach (var currentNode in mark.Nodes) { - if (node.FullName == currentNode.FullName) { + if (node.Name == currentNode.Name) { mark.Nodes.Remove(currentNode); return; }