Browse Source

reimplement tooltips for simple expressions

newNRvisualizers
Siegfried Pammer 13 years ago
parent
commit
c9bea6a597
  1. 5
      src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj
  2. 141
      src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluationVisitor.cs
  3. 20
      src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
  4. 5
      src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs
  5. 24
      src/AddIns/Debugger/Debugger.AddIn/Tooltips/VisualizerPicker.cs
  6. 10
      src/AddIns/Debugger/Debugger.AddIn/TreeModel/ValueNode.cs

5
src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj

@ -144,6 +144,8 @@ @@ -144,6 +144,8 @@
<DependentUpon>EditBreakpointScriptWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Tooltips\DebuggerTooltipControl.xaml.cs" />
<Compile Include="Tooltips\VisualizerPicker.cs" />
<Compile Include="TreeModel\SharpTreeNodeAdapter.cs" />
<Compile Include="TreeModel\TreeNode.cs" />
<EmbeddedResource Include="Service\DebuggeeExceptionForm.resx">
@ -221,9 +223,12 @@ @@ -221,9 +223,12 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Tooltips" />
<Page Include="Options\DebuggingOptionsPanel.xaml" />
<Page Include="Pads\Common\CommonResources.xaml" />
<Page Include="Service\EditBreakpointScriptWindow.xaml" />
<Page Include="Tooltips\DebuggerTooltipControl.xaml" />
<Page Include="Tooltips\VisualizerPicker.xaml" />
<ProjectReference Include="..\..\..\Main\ICSharpCode.Core.WinForms\ICSharpCode.Core.WinForms.csproj">
<Project>{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}</Project>
<Name>ICSharpCode.Core.WinForms</Name>

141
src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluationVisitor.cs

@ -59,8 +59,11 @@ namespace Debugger.AddIn @@ -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 @@ -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 @@ -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 @@ -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,9 +328,8 @@ namespace Debugger.AddIn @@ -321,9 +328,8 @@ 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();
}
@ -351,13 +357,15 @@ namespace Debugger.AddIn @@ -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 @@ -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;
}
}
}

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

@ -13,6 +13,7 @@ using System.Text; @@ -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; @@ -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;
@ -708,7 +710,23 @@ namespace ICSharpCode.SharpDevelop.Services @@ -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)));
}
}
}
}

5
src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs

@ -36,6 +36,11 @@ namespace Debugger.AddIn.Tooltips @@ -36,6 +36,11 @@ namespace Debugger.AddIn.Tooltips
this.Placement = PlacementMode.Absolute;
}
public DebuggerTooltipControl(params TreeNode[] treeNodes)
: this((IEnumerable<TreeNode>)treeNodes)
{
}
private void Expand_Click(object sender, RoutedEventArgs e)
{
var clickedButton = (ToggleButton)e.OriginalSource;

24
src/AddIns/Debugger/Debugger.AddIn/Tooltips/VisualizerPicker.cs

@ -26,23 +26,23 @@ namespace Debugger.AddIn.Tooltips @@ -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<IVisualizerCommand> ItemsSource
{
get { return (IEnumerable<IVisualizerCommand>)base.ItemsSource; }
set { base.ItemsSource = value; }
}
// public new IEnumerable<IVisualizerCommand> ItemsSource
// {
// get { return (IEnumerable<IVisualizerCommand>)base.ItemsSource; }
// set { base.ItemsSource = value; }
// }
}
}

10
src/AddIns/Debugger/Debugger.AddIn/TreeModel/ValueNode.cs

@ -14,6 +14,7 @@ using System.Text; @@ -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,7 +170,7 @@ namespace Debugger.AddIn.TreeModel @@ -169,7 +170,7 @@ 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();
@ -182,7 +183,7 @@ namespace Debugger.AddIn.TreeModel @@ -182,7 +183,7 @@ namespace Debugger.AddIn.TreeModel
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 @@ -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<TreeNode> GetLocalVariables()
{
var stackFrame = GetCurrentStackFrame();

Loading…
Cancel
Save