diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ChildNodesOfObject.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ChildNodesOfObject.cs index 47f50a8c94..476521aac9 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ChildNodesOfObject.cs +++ b/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); if (iListType != null) { 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)) { yield return node; diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs index 97dc0a3aa3..4eff5918ae 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs @@ -33,9 +33,6 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer WindowsDebugger debuggerService; GridViewColumnHider columnHider; - /// Number of items shown initially when visualizing IEnumerable. - static readonly int initialIEnumerableItemsCount = 24; - public GridVisualizerWindow() { InitializeComponent(); @@ -125,23 +122,19 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer // Value is IList DebugType iListType, listItemType; if (val.Type.ResolveIListImplementation(out iListType, out listItemType)) { - var listValuesProvider = new ListValuesProvider(val.ExpressionTree, iListType, listItemType); - var virtCollection = new VirtualizingCollection(listValuesProvider); - this.listView.ItemsSource = virtCollection; - gridValuesProvider = listValuesProvider; + gridValuesProvider = CreateListValuesProvider(val.ExpressionTree, iListType, listItemType); } else { // Value is IEnumerable DebugType iEnumerableType, itemType; if (val.Type.ResolveIEnumerableImplementation(out iEnumerableType, out itemType)) { - var lazyListViewWrapper = new LazyItemsControl(this.listView, initialIEnumerableItemsCount); + // original + /*var lazyListViewWrapper = new LazyItemsControl(this.listView, initialIEnumerableItemsCount); var enumerableValuesProvider = new EnumerableValuesProvider(val.ExpressionTree, iEnumerableType, itemType); lazyListViewWrapper.ItemsSource = new VirtualizingIEnumerable(enumerableValuesProvider.ItemsSource); - gridValuesProvider = enumerableValuesProvider; - - /*var systemObjectType = DebugType.CreateFromType(val.AppDomain, typeof(System.Object)); - var listType = DebugType.CreateFromType(val.AppDomain, typeof(System.Collections.Generic.List<>), systemObjectType); - Value list = Eval.NewObject(listType , val);*/ - + gridValuesProvider = enumerableValuesProvider;*/ + DebugType debugListType; + var debugListExpression = DebuggerHelpers.CreateDebugListExpression(val.ExpressionTree, itemType, out debugListType); + gridValuesProvider = CreateListValuesProvider(debugListExpression, debugListType, itemType); } else { // Value cannot be displayed in GridVisualizer 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(listValuesProvider); + this.listView.ItemsSource = virtCollection; + return listValuesProvider; + } + void InitializeColumns(GridView gridView, IList itemTypeMembers) { gridView.Columns.Clear(); diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/EnumerableValuesProvider.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/EnumerableValuesProvider.cs index 006ac822ce..ef13144f40 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/EnumerableValuesProvider.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/EnumerableValuesProvider.cs @@ -4,13 +4,14 @@ // // $Revision$ // -using Debugger.MetaData; -using Debugger.AddIn.Visualizers.Utils; +using ICSharpCode.Core; using System; using System.Collections; using System.Collections.Generic; -using ICSharpCode.SharpDevelop.Services; +using Debugger.AddIn.Visualizers.Utils; +using Debugger.MetaData; using ICSharpCode.NRefactory.Ast; +using ICSharpCode.SharpDevelop.Services; namespace Debugger.AddIn.Visualizers.GridVisualizer { diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs index 3d628a0e35..18f4d8f5e8 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs +++ b/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) // or targetObject.EvaluateCount(iListType) // or targetObject.EvaluateIListCount() <- calls ResolveIListImplementation - private int evaluateCount() + int evaluateCount() { 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 - Value countValue = targetObject.Evaluate(WindowsDebugger.CurrentProcess).GetPropertyValue(countProperty); - return (int)countValue.PrimitiveValue; - } catch (GetValueException) { - return -1; - } + // Do not get string representation since it can be printed in hex later + Value countValue = targetObject.Evaluate(WindowsDebugger.CurrentProcess).GetPropertyValue(countProperty); + //Value countValue = targetObject.AppendMemberReference(countProperty).Evaluate(WindowsDebugger.CurrentProcess); + return (int)countValue.PrimitiveValue; } } } diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/DebuggerHelpers.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/DebuggerHelpers.cs index e27848a741..4d2df45f0c 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/DebuggerHelpers.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/DebuggerHelpers.cs @@ -5,16 +5,34 @@ // $Revision$ // using System; +using Debugger; using Debugger.MetaData; using Debugger.Wrappers.CorDebug; using ICSharpCode.SharpDevelop.Services; using System.Collections.Generic; -using Expression = ICSharpCode.NRefactory.Ast.Expression; +using ICSharpCode.NRefactory.Ast; namespace Debugger.AddIn.Visualizers.Utils { public static class DebuggerHelpers { + /// + /// Creates an expression which, when evaluated, creates a List<T> in the debugee + /// filled with contents of IEnumerable<T> from the debugee. + /// + /// Expression for IEnumerable variable in the debugee. + /// + /// The generic argument of IEnumerable<T> that implements. + 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, where T is itemType + Expression iEnumerableVariableExplicitCast = new CastExpression(iEnumerableType.ToTypeReference() , iEnumerableVariable, CastType.Cast); + return new ObjectCreateExpression(listType.ToTypeReference(), iEnumerableVariableExplicitCast.ToList()); + } + /// /// Gets underlying address of object in the debuggee. /// diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/ListHelper.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/ListHelper.cs index fea2604718..ded4deeada 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/ListHelper.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Visualizers/Utils/ListHelper.cs @@ -27,5 +27,12 @@ namespace Debugger.AddIn.Visualizers.Utils list.Sort(); return list; } + + public static List ToList(this T singleItem) + { + var newList = new List(); + newList.Add(singleItem); + return newList; + } } } diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs index 53365aacb2..36992cad6a 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs @@ -336,14 +336,9 @@ namespace Debugger #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(constructorArguments)); - } - - public static Value NewObject(DebugType debugType, List constructorArguments) - { - return AsyncNewObject(debugType, constructorArguments).WaitForResult(); + return AsyncNewObject(debugType, constructorArguments, constructorArgumentsTypes).WaitForResult(); } public static Value NewObjectNoConstructor(DebugType debugType) @@ -353,12 +348,14 @@ namespace Debugger #endregion - public static Eval AsyncNewObject(DebugType debugType, List constructorArguments) + public static Eval AsyncNewObject(DebugType debugType, Value[] constructorArguments, DebugType[] constructorArgumentsTypes) { List constructorArgumentsExpressions = SelectExpressions(constructorArguments); - // constructorArgumentsTypes = SelectTypes(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( debugType.AppDomain, "New object: " + debugType.FullName, @@ -383,19 +380,19 @@ namespace Debugger ); } - static ICorDebugValue[] ValuesAsCorDebug(List values) + static ICorDebugValue[] ValuesAsCorDebug(Value[] values) { - ICorDebugValue[] valuesAsCorDebug = new ICorDebugValue[values.Count]; - for(int i = 0; i < values.Count; i++) + ICorDebugValue[] valuesAsCorDebug = new ICorDebugValue[values.Length]; + for(int i = 0; i < values.Length; i++) { valuesAsCorDebug[i] = values[i].CorValue; } return valuesAsCorDebug; } - static List SelectExpressions(List values) + static List SelectExpressions(Value[] values) { - List expressions = new List(values.Count); + List expressions = new List(values.Length); foreach (Value value in values) { expressions.Add(value.ExpressionTree); } diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionEvaluator.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionEvaluator.cs index 96cd4a5e2d..4187d5af26 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionEvaluator.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionEvaluator.cs @@ -336,6 +336,21 @@ namespace Debugger return target.InvokeMethod(method, args.ToArray()); } + public override object VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data) + { + List 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) { Value target = Evaluate(memberReferenceExpression.TargetObject); diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionExtensionMethods.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionExtensionMethods.cs index 52a3a8f212..70856db1c5 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionExtensionMethods.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/ExpressionExtensionMethods.cs @@ -2,7 +2,7 @@ // // // -// $Revision: 4767 $ +// $Revision$ // using ICSharpCode.NRefactory.PrettyPrinter; using System; @@ -102,7 +102,7 @@ namespace Debugger return typedArgs; } - static TypeReference ToTypeReference(this DebugType type) + public static TypeReference ToTypeReference(this DebugType type) { List arrayRanks = new List(); int pointerNest = 0; diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs index f8cf569e5b..9b786928b2 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs @@ -353,7 +353,7 @@ namespace Debugger.MetaData if (module.AppDomain == appDomain) { uint token; 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 { continue; } @@ -363,6 +363,16 @@ namespace Debugger.MetaData throw new DebuggerException("Can not find type " + typeName); } + /// Converts type name to the form suitable for COM API. + 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) { CorTokenType tokenType = (CorTokenType)(token & 0xFF000000);