diff --git a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj
index ee5543a4f4..7e53f03c4b 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj
+++ b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj
@@ -144,6 +144,8 @@
EditBreakpointScriptWindow.xaml
Code
+
+
@@ -221,9 +223,12 @@
+
+
+
{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}
ICSharpCode.Core.WinForms
diff --git a/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluationVisitor.cs b/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluationVisitor.cs
index 21650d1229..6977997b31 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluationVisitor.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluationVisitor.cs
@@ -59,8 +59,11 @@ namespace Debugger.AddIn
StackFrame context;
ICompilation debuggerTypeSystem;
Thread evalThread;
+ bool allowMethodInvoke;
+ bool allowSetValue;
- public ExpressionEvaluationVisitor(StackFrame context, Thread evalThread, ICompilation debuggerTypeSystem)
+ public ExpressionEvaluationVisitor(StackFrame context, Thread evalThread, ICompilation debuggerTypeSystem,
+ bool allowMethodInvoke = false, bool allowSetValue = false)
{
if (evalThread == null)
throw new ArgumentNullException("evalThread");
@@ -71,6 +74,8 @@ namespace Debugger.AddIn
this.context = context;
this.debuggerTypeSystem = debuggerTypeSystem;
this.evalThread = evalThread;
+ this.allowMethodInvoke = allowMethodInvoke;
+ this.allowSetValue = allowSetValue;
}
public Value Convert(ResolveResult result)
@@ -121,6 +126,8 @@ namespace Debugger.AddIn
{
switch (result.OperatorType) {
case ExpressionType.Assign:
+ if (!allowSetValue)
+ throw new InvalidOperationException("Setting values is not allowed in the current context!");
Debug.Assert(result.Operands.Count == 2);
return VisitAssignment((dynamic)result.Operands[0], (dynamic)result.Operands[1]);
case ExpressionType.Add:
@@ -300,7 +307,7 @@ namespace Debugger.AddIn
Value Visit(ArrayAccessResolveResult result)
{
- var val = Convert(result.Array);
+ var val = Convert(result.Array).GetPermanentReference(evalThread);
return val.GetArrayElement(result.Indexes.Select(rr => (int)Convert(rr).PrimitiveValue).ToArray());
}
@@ -321,10 +328,9 @@ namespace Debugger.AddIn
return Eval.CreateValue(evalThread, convVal);
} else if (result.Conversion.IsUserDefined)
return InvokeMethod(null, result.Conversion.Method, val);
- else if (result.Conversion.IsReferenceConversion && result.Conversion.IsImplicit) {
+ else if (result.Conversion.IsReferenceConversion && result.Conversion.IsImplicit)
return val;
- } else
- throw new NotImplementedException();
+ throw new NotImplementedException();
}
Value Visit(LocalResolveResult result)
@@ -351,13 +357,15 @@ namespace Debugger.AddIn
throw new GetValueException("Indexer does not have a getter.");
usedMethod = prop.Getter;
} else if (importedMember is IMethod) {
+ if (!allowMethodInvoke)
+ throw new InvalidOperationException("Method invocation not allowed in the current context!");
usedMethod = (IMethod)importedMember;
} else
throw new GetValueException("Invoked member must be a method or property");
Value target = null;
if (!usedMethod.IsStatic)
- target = Convert(result.TargetResult);
- return InvokeMethod(target, usedMethod, result.Arguments.Select(rr => Convert(rr)).ToArray());
+ target = Convert(result.TargetResult).GetPermanentReference(evalThread);
+ return InvokeMethod(target, usedMethod, result.Arguments.Select(rr => Convert(rr).GetPermanentReference(evalThread)).ToArray());
}
Value Visit(NamespaceResolveResult result)
@@ -416,4 +424,125 @@ namespace Debugger.AddIn
}
}
+
+ public class ResolveResultPrettyPrinter
+ {
+ public ResolveResultPrettyPrinter()
+ {
+
+ }
+
+ public string Print(ResolveResult result)
+ {
+ if (result == null)
+ return "";
+ if (result.IsError)
+ return "{Error}";
+ return Visit((dynamic)result);
+ }
+
+ string Visit(ResolveResult result)
+ {
+ return "Not supported: " + result.GetType().Name;
+ }
+
+// string Visit(ValueResolveResult result)
+// {
+// throw new NotImplementedException();
+// }
+
+ string Visit(ThisResolveResult result)
+ {
+ return "this";
+ }
+
+ string Visit(MemberResolveResult result)
+ {
+ return Print(result.TargetResult) + "." + result.Member.Name;
+ }
+
+ string Visit(OperatorResolveResult result)
+ {
+ throw new NotImplementedException();
+ }
+
+ string Visit(TypeIsResolveResult result)
+ {
+ throw new NotImplementedException();
+ }
+
+ string Visit(TypeOfResolveResult result)
+ {
+ throw new NotImplementedException();
+ }
+
+ string Visit(TypeResolveResult result)
+ {
+ throw new NotImplementedException();
+ }
+
+ string Visit(UnknownMemberResolveResult result)
+ {
+ return result.MemberName;
+ }
+
+ string Visit(UnknownIdentifierResolveResult result)
+ {
+ return result.Identifier;
+ }
+
+ string Visit(ArrayAccessResolveResult result)
+ {
+ throw new NotImplementedException();
+ }
+
+ string Visit(ArrayCreateResolveResult result)
+ {
+ throw new NotImplementedException();
+ }
+
+ string Visit(ConversionResolveResult result)
+ {
+ throw new NotImplementedException();
+ }
+
+ string Visit(LocalResolveResult result)
+ {
+ if (result.IsParameter)
+ return result.Variable.Name;
+ return result.Variable.Name;
+ }
+
+ string Visit(AmbiguousMemberResolveResult result)
+ {
+ throw new NotImplementedException();
+ }
+
+ string Visit(InvocationResolveResult result)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.Append(Print(result.TargetResult));
+ sb.Append('.');
+ sb.Append(result.Member.Name);
+
+ sb.Append(result.Member is IProperty ? "[" : "(");
+
+ bool first = true;
+ foreach (var p in result.Member.Parameters) {
+ if (first) first = false;
+ else sb.Append(", ");
+ sb.Append(p.Name);
+ }
+
+ sb.Append(result.Member is IProperty ? "]" : ")");
+
+ return sb.ToString();
+ }
+
+ string Visit(NamespaceResolveResult result)
+ {
+ return "namespace " + result.NamespaceName;
+ }
+ }
}
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs b/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
index d15ccfa6de..9c3d436a37 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
@@ -13,6 +13,7 @@ using System.Text;
using System.Windows.Forms;
using Debugger;
using Debugger.AddIn;
+using Debugger.AddIn.Tooltips;
using Debugger.AddIn.TreeModel;
using Debugger.Interop.CorPublish;
using Debugger.MetaData;
@@ -20,6 +21,7 @@ using ICSharpCode.Core;
using ICSharpCode.Core.WinForms;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp;
+using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.SharpDevelop.Bookmarks;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Editor;
@@ -613,11 +615,11 @@ namespace ICSharpCode.SharpDevelop.Services
WorkbenchSingleton.MainWindow.Activate();
// if (debuggedProcess.IsSelectedFrameForced()) {
- if (CurrentThread != null && CurrentStackFrame.HasSymbols) {
- JumpToSourceCode();
- } else {
- #warning JumpToDecompiledCode(CurrentStackFrame);
- }
+ if (CurrentThread != null && CurrentStackFrame.HasSymbols) {
+ JumpToSourceCode();
+ } else {
+ #warning JumpToDecompiledCode(CurrentStackFrame);
+ }
// } else {
// var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
// // other pause reasons
@@ -686,7 +688,7 @@ namespace ICSharpCode.SharpDevelop.Services
}
}
- */
+ */
StopAttachedProcessDialogResult ShowStopAttachedProcessDialog()
{
@@ -708,7 +710,23 @@ namespace ICSharpCode.SharpDevelop.Services
public void HandleToolTipRequest(ToolTipRequestEventArgs e)
{
-// throw new NotImplementedException();
+ if (e.ResolveResult == null)
+ return;
+ if (e.ResolveResult is LocalResolveResult || e.ResolveResult is MemberResolveResult || e.ResolveResult is InvocationResolveResult) {
+ Value result;
+ string text;
+ try {
+ ExpressionEvaluationVisitor eval = new ExpressionEvaluationVisitor(CurrentStackFrame, EvalThread, CurrentStackFrame.AppDomain.Compilation);
+ result = eval.Convert(e.ResolveResult);
+ text = new ResolveResultPrettyPrinter().Print(e.ResolveResult);
+ } catch (GetValueException ex) {
+ text = ex.Message;
+ result = null;
+ } catch (InvalidOperationException) {
+ return;
+ }
+ e.SetToolTip(new DebuggerTooltipControl(ValueNode.GetTooltipFor(text, result)));
+ }
}
}
}
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs
index 9785ef6763..995387b0e7 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs
@@ -36,6 +36,11 @@ namespace Debugger.AddIn.Tooltips
this.Placement = PlacementMode.Absolute;
}
+ public DebuggerTooltipControl(params TreeNode[] treeNodes)
+ : this((IEnumerable)treeNodes)
+ {
+ }
+
private void Expand_Click(object sender, RoutedEventArgs e)
{
var clickedButton = (ToggleButton)e.OriginalSource;
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/VisualizerPicker.cs b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/VisualizerPicker.cs
index 82606236aa..d36e7d9003 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Tooltips/VisualizerPicker.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Tooltips/VisualizerPicker.cs
@@ -26,23 +26,23 @@ namespace Debugger.AddIn.Tooltips
if (this.SelectedItem == null) {
return;
}
- var clickedCommand = this.SelectedItem as IVisualizerCommand;
- if (clickedCommand == null) {
- throw new InvalidOperationException(
- string.Format("{0} clicked, only instances of {1} must be present in {2}.",
- this.SelectedItem.GetType().ToString(), typeof(IVisualizerCommand).Name, typeof(VisualizerPicker).Name));
- }
+// var clickedCommand = this.SelectedItem as IVisualizerCommand;
+// if (clickedCommand == null) {
+// throw new InvalidOperationException(
+// string.Format("{0} clicked, only instances of {1} must be present in {2}.",
+// this.SelectedItem.GetType().ToString(), typeof(IVisualizerCommand).Name, typeof(VisualizerPicker).Name));
+// }
- clickedCommand.Execute();
+// clickedCommand.Execute();
// Make no item selected, so that multiple selections of the same item always execute the command.
// This triggers VisualizerPicker_SelectionChanged again, which returns immediately.
this.SelectedIndex = -1;
}
- public new IEnumerable ItemsSource
- {
- get { return (IEnumerable)base.ItemsSource; }
- set { base.ItemsSource = value; }
- }
+// public new IEnumerable ItemsSource
+// {
+// get { return (IEnumerable)base.ItemsSource; }
+// set { base.ItemsSource = value; }
+// }
}
}
diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ValueNode.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ValueNode.cs
index 82e7e35092..51ef3ac74f 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ValueNode.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ValueNode.cs
@@ -14,6 +14,7 @@ using System.Text;
using System.Windows.Forms;
using Debugger.MetaData;
using ICSharpCode.Core;
+using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Gui.Pads;
@@ -169,20 +170,20 @@ namespace Debugger.AddIn.TreeModel
this.Type = val.Type.Name;
if (!val.IsNull) {
-#warning this.VisualizerCommands = VisualizerDescriptors.GetAllDescriptors()
+ #warning this.VisualizerCommands = VisualizerDescriptors.GetAllDescriptors()
// .Where(descriptor => descriptor.IsVisualizerAvailable(val.Type))
// .Select(descriptor => descriptor.CreateVisualizerCommand(this.Name, this.GetValue))
// .ToList();
}
LoggingService.InfoFormatted("Evaluated node '{0}' in {1} ms", this.Name, watch.ElapsedMilliseconds);
-
+
} catch (GetValueException e) {
error = e;
this.Value = e.Message;
this.Type = string.Empty;
this.GetChildren = null;
-#warning this.VisualizerCommands = null;
+ #warning this.VisualizerCommands = null;
return;
}
}
@@ -276,6 +277,11 @@ namespace Debugger.AddIn.TreeModel
return WindowsDebugger.CurrentStackFrame;
}
+ public static TreeNode GetTooltipFor(string text, Value value)
+ {
+ return new ValueNode("Icons.16x16.Local", text, () => value);
+ }
+
public static IEnumerable GetLocalVariables()
{
var stackFrame = GetCurrentStackFrame();
@@ -306,7 +312,7 @@ namespace Debugger.AddIn.TreeModel
});
}
}
- */
+ */
}
}