// 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.Linq; using Debugger.Interop.CorDebug; using System; using System.Collections.Generic; using System.Reflection; using Debugger; using Debugger.MetaData; using ICSharpCode.NRefactory.Ast; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Services; 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.GetTypeReference() , iEnumerableVariable, CastType.Cast); return new ObjectCreateExpression(listType.GetTypeReference(), iEnumerableVariableExplicitCast.ToList()); } /// /// Gets underlying address of object in the debuggee. /// public static ulong GetObjectAddress(this Value val) { if (val.IsNull) return 0; ICorDebugReferenceValue refVal = val.CorReferenceValue; return refVal.GetValue(); } /// /// Returns true if this type is enum. /// public static bool IsEnum(this DebugType type) { return (type.BaseType != null) && (type.BaseType.FullName == "System.Enum"); } /// /// Returns true is this type is just System.Object. /// public static bool IsSystemDotObject(this DebugType type) { return type.FullName == "System.Object"; } /// /// Evaluates expression and gets underlying address of object in the debuggee. /// public static ulong GetObjectAddress(this Expression expr) { return expr.Evaluate(WindowsDebugger.CurrentProcess).GetObjectAddress(); } /// /// System.Runtime.CompilerServices.GetHashCode method, for obtaining non-overriden hash codes from debuggee. /// private static DebugMethodInfo hashCodeMethod; /// /// Invokes RuntimeHelpers.GetHashCode on given value, that is a default hashCode ignoring user overrides. /// /// Valid value. /// Hash code of the object in the debugee. public static int InvokeDefaultGetHashCode(this Value value) { if (hashCodeMethod == null || hashCodeMethod.Process.HasExited) { DebugType typeRuntimeHelpers = DebugType.CreateFromType(value.AppDomain, typeof(System.Runtime.CompilerServices.RuntimeHelpers)); hashCodeMethod = (DebugMethodInfo)typeRuntimeHelpers.GetMethod("GetHashCode", BindingFlags.Public | BindingFlags.Static); if (hashCodeMethod == null) { throw new DebuggerException("Cannot obtain method System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode"); } } Value defaultHashCode = Eval.InvokeMethod(DebuggerHelpers.hashCodeMethod, null, new Value[]{value}); //MethodInfo method = value.Type.GetMember("GetHashCode", BindingFlags.Method | BindingFlags.IncludeSuperType) as MethodInfo; //string hashCode = value.InvokeMethod(method, null).AsString; return (int)defaultHashCode.PrimitiveValue; } /// /// Formats System.Type to the C# format, that is generic parameters in angle brackets. /// public static string FormatNameCSharp(this Type type) { string typeName = type.Name.CutoffEnd("`"); // get rid of the `n in generic type names if (type.IsGenericType) { return typeName + "<" + string.Join(", ", type.GetGenericArguments().Select(a => FormatNameCSharp(a))) + ">"; } else { return typeName; } } public static Value EvalPermanentReference(this Expression expr) { return expr.Evaluate(WindowsDebugger.CurrentProcess).GetPermanentReference(); } public static bool IsNull(this Expression expr) { return expr.Evaluate(WindowsDebugger.CurrentProcess).IsNull; } public static DebugType GetType(this Expression expr) { return expr.Evaluate(WindowsDebugger.CurrentProcess).Type; } } }