Browse Source

Grid visualizer uses DebuggerHelpers.CreateDebugListExpression to fill a List by IEnumerable inside the debuggee and then display the List.

Implemented ExpressionEvaluator.VisitObjectCreateExpression.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@4821 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Martin Koníček 17 years ago
parent
commit
e56d8c0501
  1. 7
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ChildNodesOfObject.cs
  2. 29
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs
  3. 7
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/EnumerableValuesProvider.cs
  4. 13
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs
  5. 20
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/DebuggerHelpers.cs
  6. 7
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/ListHelper.cs
  7. 27
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs
  8. 15
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionEvaluator.cs
  9. 4
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionExtensionMethods.cs
  10. 12
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs

7
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ChildNodesOfObject.cs

@ -68,7 +68,12 @@ namespace Debugger.AddIn.TreeModel
DebugType iListType = shownType.GetInterface(typeof(IList).FullName); DebugType iListType = shownType.GetInterface(typeof(IList).FullName);
if (iListType != null) { if (iListType != null) {
yield return new IListNode(targetObject, iListType); yield return new IListNode(targetObject, iListType);
} } /*else {
DebugType iEnumerableType = shownType.GetInterface(typeof(IEnumerable).FullName);
if (iEnumerableType != null) {
yield return new IEnumerableNode(targetObject, iEnumerableType);
}
}*/
foreach(TreeNode node in LazyGetMembersOfObject(targetObject, shownType, publicInstanceFlags)) { foreach(TreeNode node in LazyGetMembersOfObject(targetObject, shownType, publicInstanceFlags)) {
yield return node; yield return node;

29
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs

@ -33,9 +33,6 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
WindowsDebugger debuggerService; WindowsDebugger debuggerService;
GridViewColumnHider columnHider; GridViewColumnHider columnHider;
/// <summary> Number of items shown initially when visualizing IEnumerable. </summary>
static readonly int initialIEnumerableItemsCount = 24;
public GridVisualizerWindow() public GridVisualizerWindow()
{ {
InitializeComponent(); InitializeComponent();
@ -125,23 +122,19 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
// Value is IList // Value is IList
DebugType iListType, listItemType; DebugType iListType, listItemType;
if (val.Type.ResolveIListImplementation(out iListType, out listItemType)) { if (val.Type.ResolveIListImplementation(out iListType, out listItemType)) {
var listValuesProvider = new ListValuesProvider(val.ExpressionTree, iListType, listItemType); gridValuesProvider = CreateListValuesProvider(val.ExpressionTree, iListType, listItemType);
var virtCollection = new VirtualizingCollection<ObjectValue>(listValuesProvider);
this.listView.ItemsSource = virtCollection;
gridValuesProvider = listValuesProvider;
} else { } else {
// Value is IEnumerable // Value is IEnumerable
DebugType iEnumerableType, itemType; DebugType iEnumerableType, itemType;
if (val.Type.ResolveIEnumerableImplementation(out iEnumerableType, out itemType)) { if (val.Type.ResolveIEnumerableImplementation(out iEnumerableType, out itemType)) {
var lazyListViewWrapper = new LazyItemsControl<ObjectValue>(this.listView, initialIEnumerableItemsCount); // original
/*var lazyListViewWrapper = new LazyItemsControl<ObjectValue>(this.listView, initialIEnumerableItemsCount);
var enumerableValuesProvider = new EnumerableValuesProvider(val.ExpressionTree, iEnumerableType, itemType); var enumerableValuesProvider = new EnumerableValuesProvider(val.ExpressionTree, iEnumerableType, itemType);
lazyListViewWrapper.ItemsSource = new VirtualizingIEnumerable<ObjectValue>(enumerableValuesProvider.ItemsSource); lazyListViewWrapper.ItemsSource = new VirtualizingIEnumerable<ObjectValue>(enumerableValuesProvider.ItemsSource);
gridValuesProvider = enumerableValuesProvider; gridValuesProvider = enumerableValuesProvider;*/
DebugType debugListType;
/*var systemObjectType = DebugType.CreateFromType(val.AppDomain, typeof(System.Object)); var debugListExpression = DebuggerHelpers.CreateDebugListExpression(val.ExpressionTree, itemType, out debugListType);
var listType = DebugType.CreateFromType(val.AppDomain, typeof(System.Collections.Generic.List<>), systemObjectType); gridValuesProvider = CreateListValuesProvider(debugListExpression, debugListType, itemType);
Value list = Eval.NewObject(listType , val);*/
} else { } else {
// Value cannot be displayed in GridVisualizer // Value cannot be displayed in GridVisualizer
return; return;
@ -155,6 +148,14 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
} }
} }
ListValuesProvider CreateListValuesProvider(ICSharpCode.NRefactory.Ast.Expression targetObject, DebugType iListType, DebugType listItemType)
{
var listValuesProvider = new ListValuesProvider(targetObject, iListType, listItemType);
var virtCollection = new VirtualizingCollection<ObjectValue>(listValuesProvider);
this.listView.ItemsSource = virtCollection;
return listValuesProvider;
}
void InitializeColumns(GridView gridView, IList<MemberInfo> itemTypeMembers) void InitializeColumns(GridView gridView, IList<MemberInfo> itemTypeMembers)
{ {
gridView.Columns.Clear(); gridView.Columns.Clear();

7
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/EnumerableValuesProvider.cs

@ -4,13 +4,14 @@
// <owner name="Martin Koníček" email="martin.konicek@gmail.com"/> // <owner name="Martin Koníček" email="martin.konicek@gmail.com"/>
// <version>$Revision$</version> // <version>$Revision$</version>
// </file> // </file>
using Debugger.MetaData; using ICSharpCode.Core;
using Debugger.AddIn.Visualizers.Utils;
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using ICSharpCode.SharpDevelop.Services; using Debugger.AddIn.Visualizers.Utils;
using Debugger.MetaData;
using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Ast;
using ICSharpCode.SharpDevelop.Services;
namespace Debugger.AddIn.Visualizers.GridVisualizer namespace Debugger.AddIn.Visualizers.GridVisualizer
{ {

13
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs

@ -48,16 +48,13 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
// TODO move to Utils iListType.EvaluateCount(Expression targetObject) // TODO move to Utils iListType.EvaluateCount(Expression targetObject)
// or targetObject.EvaluateCount(iListType) // or targetObject.EvaluateCount(iListType)
// or targetObject.EvaluateIListCount() <- calls ResolveIListImplementation // or targetObject.EvaluateIListCount() <- calls ResolveIListImplementation
private int evaluateCount() int evaluateCount()
{ {
PropertyInfo countProperty = this.collectionType.GetGenericInterface("System.Collections.Generic.ICollection").GetProperty("Count"); PropertyInfo countProperty = this.collectionType.GetGenericInterface("System.Collections.Generic.ICollection").GetProperty("Count");
try { // Do not get string representation since it can be printed in hex later
// Do not get string representation since it can be printed in hex later Value countValue = targetObject.Evaluate(WindowsDebugger.CurrentProcess).GetPropertyValue(countProperty);
Value countValue = targetObject.Evaluate(WindowsDebugger.CurrentProcess).GetPropertyValue(countProperty); //Value countValue = targetObject.AppendMemberReference(countProperty).Evaluate(WindowsDebugger.CurrentProcess);
return (int)countValue.PrimitiveValue; return (int)countValue.PrimitiveValue;
} catch (GetValueException) {
return -1;
}
} }
} }
} }

20
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/DebuggerHelpers.cs

@ -5,16 +5,34 @@
// <version>$Revision$</version> // <version>$Revision$</version>
// </file> // </file>
using System; using System;
using Debugger;
using Debugger.MetaData; using Debugger.MetaData;
using Debugger.Wrappers.CorDebug; using Debugger.Wrappers.CorDebug;
using ICSharpCode.SharpDevelop.Services; using ICSharpCode.SharpDevelop.Services;
using System.Collections.Generic; using System.Collections.Generic;
using Expression = ICSharpCode.NRefactory.Ast.Expression; using ICSharpCode.NRefactory.Ast;
namespace Debugger.AddIn.Visualizers.Utils namespace Debugger.AddIn.Visualizers.Utils
{ {
public static class DebuggerHelpers public static class DebuggerHelpers
{ {
/// <summary>
/// Creates an expression which, when evaluated, creates a List&lt;T&gt; in the debugee
/// filled with contents of IEnumerable&lt;T&gt; from the debugee.
/// </summary>
/// <param name="iEnumerableVariable">Expression for IEnumerable variable in the debugee.</param>
/// <param name="itemType">
/// The generic argument of IEnumerable&lt;T&gt; that <paramref name="iEnumerableVariable"/> implements.</param>
public static Expression CreateDebugListExpression(Expression iEnumerableVariable, DebugType itemType, out DebugType listType)
{
// is using itemType.AppDomain ok?
listType = DebugType.CreateFromType(itemType.AppDomain, typeof(System.Collections.Generic.List<>), itemType);
var iEnumerableType = DebugType.CreateFromType(itemType.AppDomain, typeof(IEnumerable<>), itemType);
// explicitely cast the variable to IEnumerable<T>, where T is itemType
Expression iEnumerableVariableExplicitCast = new CastExpression(iEnumerableType.ToTypeReference() , iEnumerableVariable, CastType.Cast);
return new ObjectCreateExpression(listType.ToTypeReference(), iEnumerableVariableExplicitCast.ToList());
}
/// <summary> /// <summary>
/// Gets underlying address of object in the debuggee. /// Gets underlying address of object in the debuggee.
/// </summary> /// </summary>

7
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/ListHelper.cs

@ -27,5 +27,12 @@ namespace Debugger.AddIn.Visualizers.Utils
list.Sort(); list.Sort();
return list; return list;
} }
public static List<T> ToList<T>(this T singleItem)
{
var newList = new List<T>();
newList.Add(singleItem);
return newList;
}
} }
} }

27
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs

@ -336,14 +336,9 @@ namespace Debugger
#region Convenience methods #region Convenience methods
public static Value NewObject(DebugType debugType, params Value[] constructorArguments) public static Value NewObject(DebugType debugType, Value[] constructorArguments, DebugType[] constructorArgumentsTypes)
{ {
return NewObject(debugType, new List<Value>(constructorArguments)); return AsyncNewObject(debugType, constructorArguments, constructorArgumentsTypes).WaitForResult();
}
public static Value NewObject(DebugType debugType, List<Value> constructorArguments)
{
return AsyncNewObject(debugType, constructorArguments).WaitForResult();
} }
public static Value NewObjectNoConstructor(DebugType debugType) public static Value NewObjectNoConstructor(DebugType debugType)
@ -353,12 +348,14 @@ namespace Debugger
#endregion #endregion
public static Eval AsyncNewObject(DebugType debugType, List<Value> constructorArguments) public static Eval AsyncNewObject(DebugType debugType, Value[] constructorArguments, DebugType[] constructorArgumentsTypes)
{ {
List<Expression> constructorArgumentsExpressions = SelectExpressions(constructorArguments); List<Expression> constructorArgumentsExpressions = SelectExpressions(constructorArguments);
// constructorArgumentsTypes = SelectTypes(constructorArguments);
ICorDebugValue[] constructorArgsCorDebug = ValuesAsCorDebug(constructorArguments); ICorDebugValue[] constructorArgsCorDebug = ValuesAsCorDebug(constructorArguments);
MethodInfo constructor = debugType.GetMethod(".ctor"); // TODO MethodInfo constructor = debugType.GetMethod(".ctor", constructorArgumentsTypes);
if (constructor == null) {
throw new DebuggerException(string.Format("Type {0} has no constructor overload with given argument types.", debugType.FullName));
}
return new Eval( return new Eval(
debugType.AppDomain, debugType.AppDomain,
"New object: " + debugType.FullName, "New object: " + debugType.FullName,
@ -383,19 +380,19 @@ namespace Debugger
); );
} }
static ICorDebugValue[] ValuesAsCorDebug(List<Value> values) static ICorDebugValue[] ValuesAsCorDebug(Value[] values)
{ {
ICorDebugValue[] valuesAsCorDebug = new ICorDebugValue[values.Count]; ICorDebugValue[] valuesAsCorDebug = new ICorDebugValue[values.Length];
for(int i = 0; i < values.Count; i++) for(int i = 0; i < values.Length; i++)
{ {
valuesAsCorDebug[i] = values[i].CorValue; valuesAsCorDebug[i] = values[i].CorValue;
} }
return valuesAsCorDebug; return valuesAsCorDebug;
} }
static List<Expression> SelectExpressions(List<Value> values) static List<Expression> SelectExpressions(Value[] values)
{ {
List<Expression> expressions = new List<Expression>(values.Count); List<Expression> expressions = new List<Expression>(values.Length);
foreach (Value value in values) { foreach (Value value in values) {
expressions.Add(value.ExpressionTree); expressions.Add(value.ExpressionTree);
} }

15
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionEvaluator.cs

@ -336,6 +336,21 @@ namespace Debugger
return target.InvokeMethod(method, args.ToArray()); return target.InvokeMethod(method, args.ToArray());
} }
public override object VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data)
{
List<Expression> constructorParameters = objectCreateExpression.Parameters;
DebugType[] constructorParameterTypes = new DebugType[constructorParameters.Count];
for (int i = 0; i < constructorParameters.Count; i++) {
constructorParameterTypes[i] = GetDebugType(constructorParameters[i]);
}
Value[] constructorParameterValues = new Value[constructorParameters.Count];
for (int i = 0; i < constructorParameters.Count; i++) {
constructorParameterValues[i] = Evaluate(constructorParameters[i]);
}
return Eval.NewObject(DebugType.CreateFromTypeReference(context.AppDomain, objectCreateExpression.CreateType),
constructorParameterValues, constructorParameterTypes);
}
public override object VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data) public override object VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data)
{ {
Value target = Evaluate(memberReferenceExpression.TargetObject); Value target = Evaluate(memberReferenceExpression.TargetObject);

4
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionExtensionMethods.cs

@ -2,7 +2,7 @@
// <copyright see="prj:///doc/copyright.txt"/> // <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/> // <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/> // <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision: 4767 $</version> // <version>$Revision$</version>
// </file> // </file>
using ICSharpCode.NRefactory.PrettyPrinter; using ICSharpCode.NRefactory.PrettyPrinter;
using System; using System;
@ -102,7 +102,7 @@ namespace Debugger
return typedArgs; return typedArgs;
} }
static TypeReference ToTypeReference(this DebugType type) public static TypeReference ToTypeReference(this DebugType type)
{ {
List<int> arrayRanks = new List<int>(); List<int> arrayRanks = new List<int>();
int pointerNest = 0; int pointerNest = 0;

12
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs

@ -353,7 +353,7 @@ namespace Debugger.MetaData
if (module.AppDomain == appDomain) { if (module.AppDomain == appDomain) {
uint token; uint token;
try { try {
token = module.MetaData.FindTypeDefPropsByName(typeName, enclosingType == null ? 0 : enclosingType.Token).Token; token = module.MetaData.FindTypeDefPropsByName(GetQualifiedName(typeName, genericArguments), enclosingType == null ? 0 : enclosingType.Token).Token;
} catch { } catch {
continue; continue;
} }
@ -363,6 +363,16 @@ namespace Debugger.MetaData
throw new DebuggerException("Can not find type " + typeName); throw new DebuggerException("Can not find type " + typeName);
} }
/// <summary> Converts type name to the form suitable for COM API. </summary>
static string GetQualifiedName(string typeName, params DebugType[] genericArguments)
{
if (genericArguments != null && genericArguments.Length > 0 && !typeName.Contains("`")) {
return typeName + "`" + genericArguments.Length;
} else {
return typeName;
}
}
public static DebugType CreateFromTypeSpec(Module module, uint token, DebugType declaringType) public static DebugType CreateFromTypeSpec(Module module, uint token, DebugType declaringType)
{ {
CorTokenType tokenType = (CorTokenType)(token & 0xFF000000); CorTokenType tokenType = (CorTokenType)(token & 0xFF000000);

Loading…
Cancel
Save