Beispiel #1
0
        /// <summary>
        /// Returns an enumerable debug view. These types are located in System.Core / System.Linq. If <paramref name="enumerableType"/>
        /// is <see cref="System.Collections.IEnumerable"/>, then <c>System.Linq.SystemCore_EnumerableDebugView</c>'s constructor
        /// is returned, else if <paramref name="enumerableType"/> is <see cref="IEnumerable{T}"/>, then
        /// <c>System.Linq.SystemCore_EnumerableDebugView`1</c>'s constructor is returned.
        /// </summary>
        /// <param name="enumerableType">Enumerable type, must be one of <see cref="System.Collections.IEnumerable"/>, <see cref="IEnumerable{T}"/></param>
        /// <returns></returns>
        public static DmdConstructorInfo GetEnumerableDebugViewConstructor(DmdType enumerableType)
        {
            Debug.Assert(enumerableType == enumerableType.AppDomain.System_Collections_IEnumerable ||
                         (enumerableType.IsConstructedGenericType && enumerableType.GetGenericTypeDefinition() == enumerableType.AppDomain.System_Collections_Generic_IEnumerable_T));

            var appDomain = enumerableType.AppDomain;

            var wellKnownType = enumerableType.IsConstructedGenericType ?
                                DmdWellKnownType.System_Linq_SystemCore_EnumerableDebugView_T :
                                DmdWellKnownType.System_Linq_SystemCore_EnumerableDebugView;
            var debugViewType = appDomain.GetWellKnownType(wellKnownType, isOptional: true);

            // If this fails, System.Core (.NET Framework) / System.Linq (.NET Core) hasn't been loaded yet
            if ((object)debugViewType == null)
            {
                return(null);
            }

            if (enumerableType.IsConstructedGenericType)
            {
                var genericArgs = enumerableType.GetGenericArguments();
                if (debugViewType.GetGenericArguments().Count != genericArgs.Count)
                {
                    return(null);
                }
                debugViewType = debugViewType.MakeGenericType(genericArgs);
            }

            var ctor = debugViewType.GetConstructor(DmdBindingFlags.Public | DmdBindingFlags.NonPublic | DmdBindingFlags.Instance, DmdCallingConventions.Standard | DmdCallingConventions.HasThis, new[] { enumerableType });

            Debug.Assert((object)ctor != null);
            return(ctor);
        }
Beispiel #2
0
 public static bool IsKeyValuePair(DmdType type)
 {
     if (!type.IsConstructedGenericType)
     {
         return(false);
     }
     type = type.GetGenericTypeDefinition();
     return(type == type.AppDomain.GetWellKnownType(DmdWellKnownType.System_Collections_Generic_KeyValuePair_T2));
 }
Beispiel #3
0
        public void Add(DmdType type)
        {
            if (recursionCounter > 100)
            {
                return;
            }
            recursionCounter++;

            while (type.GetElementType() is DmdType etype)
            {
                type = etype;
            }
            switch (type.TypeSignatureKind)
            {
            case DmdTypeSignatureKind.Type:
                modules.Add(type.Module);
                break;

            case DmdTypeSignatureKind.Pointer:
            case DmdTypeSignatureKind.ByRef:
            case DmdTypeSignatureKind.TypeGenericParameter:
            case DmdTypeSignatureKind.MethodGenericParameter:
            case DmdTypeSignatureKind.SZArray:
            case DmdTypeSignatureKind.MDArray:
                break;

            case DmdTypeSignatureKind.GenericInstance:
                modules.Add(type.GetGenericTypeDefinition().Module);
                foreach (var ga in type.GetGenericArguments())
                {
                    Add(ga);
                }
                break;

            case DmdTypeSignatureKind.FunctionPointer:
                var sig = type.GetFunctionPointerMethodSignature();
                Add(sig.ReturnType);
                foreach (var t in sig.GetParameterTypes())
                {
                    Add(t);
                }
                foreach (var t in sig.GetVarArgsParameterTypes())
                {
                    Add(t);
                }
                break;

            default:
                Debug.Fail($"Unknown kind: {type.TypeSignatureKind}");
                break;
            }

            recursionCounter--;
        }
Beispiel #4
0
 public static bool IsKeyValuePair(DmdType type)
 {
     if (type.MetadataName != "KeyValuePair`2" || type.MetadataNamespace != "System.Collections.Generic")
     {
         return(false);
     }
     if (!type.IsConstructedGenericType)
     {
         return(false);
     }
     type = type.GetGenericTypeDefinition();
     return(type == type.AppDomain.GetWellKnownType(DmdWellKnownType.System_Collections_Generic_KeyValuePair_T2, isOptional: true));
 }
Beispiel #5
0
        public static (DmdConstructorInfo ctor, DmdMethodInfo toArrayMethod) GetListEnumerableMethods(DmdType objType, DmdType enumerableType)
        {
            Debug.Assert(enumerableType == enumerableType.AppDomain.System_Collections_IEnumerable ||
                         (enumerableType.IsConstructedGenericType && enumerableType.GetGenericTypeDefinition() == enumerableType.AppDomain.System_Collections_Generic_IEnumerable_T));

            var appDomain = enumerableType.AppDomain;

            if (enumerableType.IsConstructedGenericType)
            {
                var genArgs = enumerableType.GetGenericArguments();
                Debug.Assert(genArgs.Count == 1);
                if (genArgs.Count != 1)
                {
                    return(default);
 static EnumerableTypeKind GetEnumerableTypeKind(DmdType type, DmdType enumerableType, DmdType enumerableOfTType)
 {
     if (type == enumerableType)
     {
         return(EnumerableTypeKind.Enumerable);
     }
     if (type.IsConstructedGenericType && type.GetGenericArguments().Count == 1)
     {
         if (type.GetGenericTypeDefinition() == enumerableOfTType)
         {
             return(EnumerableTypeKind.EnumerableOfT);
         }
     }
     return(EnumerableTypeKind.None);
 }
 static bool ShouldIgnoreDebuggerDisplayAttribute(DmdType type)
 {
     // We have special support for formatting KeyValuePair<K, V> and DictionaryEntry, so ignore all DebuggerDisplayAttributes.
     // (Only Unity and older Mono versions have a DebuggerDisplayAttribute on them)
     if (type.IsConstructedGenericType)
     {
         if (type.MetadataName == "KeyValuePair`2" && type.MetadataNamespace == "System.Collections.Generic")
         {
             return(type.GetGenericTypeDefinition() == type.AppDomain.GetWellKnownType(DmdWellKnownType.System_Collections_Generic_KeyValuePair_T2, isOptional: true));
         }
         return(false);
     }
     else
     {
         if (type.MetadataName == "DictionaryEntry" && type.MetadataNamespace == "System.Collections")
         {
             return(type == type.AppDomain.GetWellKnownType(DmdWellKnownType.System_Collections_DictionaryEntry, isOptional: true));
         }
         return(false);
     }
 }
        TypeMirror TryResolveType(TypeMirror monoType, DmdType realType)
        {
            var fullName = realType.FullName;

            if (fullName == null && realType.IsGenericType)
            {
                fullName = realType.GetGenericTypeDefinition().FullName;
            }
            if (string.IsNullOrEmpty(fullName))
            {
                return(null);
            }
            // This fails if fullName is a generic instantiated type and at least one generic argument
            // is a type in another assembly, eg. List<MyType>.
            var result = monoType.Module.Assembly.GetType(fullName);

            if (result != null)
            {
                return(result);
            }
            return(monoTypeLoader?.Load(monoType.Assembly, fullName));
        }
        (DisplayPart[] nameParts, DisplayPart[] valueParts, DisplayPart[] typeParts) GetDisplayParts(DmdType type)
        {
            var ddaType = type.AppDomain.GetWellKnownType(DmdWellKnownType.System_Diagnostics_DebuggerDisplayAttribute, isOptional: true);

            Debug.Assert((object)ddaType != null);

            // We have special support for formatting KeyValuePair<K, V>, so ignore all DebuggerDisplayAttributes.
            // (Only Unity and older Mono versions have a DebuggerDisplayAttribute on it)
            bool   forceNoAttr = type.IsConstructedGenericType && type.GetGenericTypeDefinition() == type.AppDomain.GetWellKnownType(DmdWellKnownType.System_Collections_Generic_KeyValuePair_T2, isOptional: true);
            string nameDisplayString = null, valueDisplayString = null, typeDisplayString = null;

            if (!forceNoAttr && (object)ddaType != null)
            {
                var attr = type.FindCustomAttribute(ddaType, inherit: true);
                if (attr == null)
                {
                    if (type.CanCastTo(type.AppDomain.System_Type))
                    {
                        // Show the same thing VS shows
                        valueDisplayString = @"\{Name = {Name} FullName = {FullName}\}";
                    }
                }
                else
                {
                    if (attr.ConstructorArguments.Count == 1)
                    {
                        valueDisplayString = attr.ConstructorArguments[0].Value as string;
                    }
                    nameDisplayString = GetString(attr, nameof(DebuggerDisplayAttribute.Name));
                    typeDisplayString = GetString(attr, nameof(DebuggerDisplayAttribute.Type));
                }
            }

            var nameParts  = CreateDisplayParts(nameDisplayString);
            var valueParts = CreateDisplayParts(valueDisplayString);
            var typeParts  = CreateDisplayParts(typeDisplayString);

            return(nameParts, valueParts, typeParts);
        }
Beispiel #10
0
        public CorType Create(DmdType type)
        {
            if ((object)type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }
            if (recursionCounter++ > 100)
            {
                throw new InvalidOperationException();
            }

            CorType result;
            int     i;
            ReadOnlyCollection <DmdType> types;

            CorType[] corTypes;
            DnModule  dnModule;

            switch (type.TypeSignatureKind)
            {
            case DmdTypeSignatureKind.Type:
                if (!engine.TryGetDnModule(type.Module.GetDebuggerModule() ?? throw new InvalidOperationException(), out dnModule))
                {
                    throw new InvalidOperationException();
                }
                Debug.Assert((type.MetadataToken >> 24) == 0x02);
                result = dnModule.CorModule.GetClassFromToken((uint)type.MetadataToken).GetParameterizedType(type.IsValueType ? CorElementType.ValueType : CorElementType.Class);
                break;

            case DmdTypeSignatureKind.Pointer:
                result = Create(type.GetElementType());
                result = appDomain.GetPtr(result);
                break;

            case DmdTypeSignatureKind.ByRef:
                result = Create(type.GetElementType());
                result = appDomain.GetByRef(result);
                break;

            case DmdTypeSignatureKind.TypeGenericParameter:
            case DmdTypeSignatureKind.MethodGenericParameter:
                throw new InvalidOperationException();

            case DmdTypeSignatureKind.SZArray:
                result = Create(type.GetElementType());
                result = appDomain.GetSZArray(result);
                break;

            case DmdTypeSignatureKind.MDArray:
                result = Create(type.GetElementType());
                result = appDomain.GetArray(result, (uint)type.GetArrayRank());
                break;

            case DmdTypeSignatureKind.GenericInstance:
                result   = Create(type.GetGenericTypeDefinition());
                types    = type.GetGenericArguments();
                corTypes = new CorType[types.Count];
                for (i = 0; i < corTypes.Length; i++)
                {
                    corTypes[i] = Create(types[i]);
                }
                result = result.Class.GetParameterizedType(type.IsValueType ? CorElementType.ValueType : CorElementType.Class, corTypes);
                break;

            case DmdTypeSignatureKind.FunctionPointer:
                var methodSig = type.GetFunctionPointerMethodSignature();
                types       = methodSig.GetParameterTypes();
                corTypes    = new CorType[1 + types.Count + methodSig.GetVarArgsParameterTypes().Count];
                corTypes[0] = Create(methodSig.ReturnType);
                for (i = 0; i < types.Count; i++)
                {
                    corTypes[i + 1] = Create(types[i]);
                }
                types = methodSig.GetVarArgsParameterTypes();
                for (i = 0; i < types.Count; i++)
                {
                    corTypes[i + 1 + methodSig.GetParameterTypes().Count] = Create(types[i]);
                }
                result = appDomain.GetFnPtr(corTypes);
                break;

            default:
                throw new InvalidOperationException();
            }

            if (result == null)
            {
                throw new InvalidOperationException();
            }

            recursionCounter--;
            return(result);
        }
        (TypeMirror type, bool containsGenericParameters) Create(DmdType type)
        {
            if ((object)type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (typeCache.TryGetType(type, out var cachedType))
            {
                return(cachedType, false);
            }

            if (recursionCounter++ > 100)
            {
                throw new InvalidOperationException();
            }

            (TypeMirror type, bool containsGenericParameters)result;
            bool addType = true;

            switch (type.TypeSignatureKind)
            {
            case DmdTypeSignatureKind.Type:
                if (!engine.TryGetMonoModule(type.Module.GetDebuggerModule() ?? throw new InvalidOperationException(), out var monoModule))
                {
                    throw new InvalidOperationException();
                }
                Debug.Assert((type.MetadataToken >> 24) == 0x02);
                //TODO: This can sometimes crash Unity's old mono fork
                //TODO: It's possible to resolve types, but it's an internal method and it requires a method in the module
                result = (monoModule.Assembly.GetType(type.FullName, false, false), false);
                if (result.type == null)
                {
                    throw new InvalidOperationException();
                }
                if (result.type.MetadataToken != type.MetadataToken)
                {
                    throw new InvalidOperationException();
                }
                break;

            case DmdTypeSignatureKind.Pointer:
                result = Create(type.GetElementType());
                result = (TryResolveType(result.type, type), result.containsGenericParameters);
                if (result.type == null)
                {
                    throw new InvalidOperationException();
                }
                if (!result.type.IsPointer)
                {
                    throw new InvalidOperationException();
                }
                break;

            case DmdTypeSignatureKind.ByRef:
                result = Create(type.GetElementType());
                result = (TryResolveType(result.type, type), result.containsGenericParameters);
                if (result.type == null)
                {
                    throw new InvalidOperationException();
                }
                // This currently always fails
                //TODO: We could func-eval MakeByRefType()
                if (!result.type.IsByRef)
                {
                    throw new InvalidOperationException();
                }
                break;

            case DmdTypeSignatureKind.TypeGenericParameter:
            case DmdTypeSignatureKind.MethodGenericParameter:
                result  = (Create(type.AppDomain.System_Object).type, true);
                addType = false;
                break;

            case DmdTypeSignatureKind.SZArray:
                result = Create(type.GetElementType());
                result = (TryResolveType(result.type, type), result.containsGenericParameters);
                if (result.type == null)
                {
                    throw new InvalidOperationException();
                }
                if (!result.type.IsArray || result.type.GetArrayRank() != 1 || !result.type.FullName.EndsWith("[]", StringComparison.Ordinal))
                {
                    throw new InvalidOperationException();
                }
                break;

            case DmdTypeSignatureKind.MDArray:
                result = Create(type.GetElementType());
                result = (TryResolveType(result.type, type), result.containsGenericParameters);
                if (result.type == null)
                {
                    throw new InvalidOperationException();
                }
                if (!result.type.IsArray || (result.type.GetArrayRank() == 1 && result.type.FullName.EndsWith("[]", StringComparison.Ordinal)))
                {
                    throw new InvalidOperationException();
                }
                break;

            case DmdTypeSignatureKind.GenericInstance:
                result = Create(type.GetGenericTypeDefinition());
                result = (TryResolveType(result.type, type), result.containsGenericParameters);
                if (result.type == null)
                {
                    throw new InvalidOperationException();
                }
                // This fails on Unity (version < 2.12), since it doesn't have that info available
                //if (!result.type.IsGenericType)
                //	throw new InvalidOperationException();
                break;

            case DmdTypeSignatureKind.FunctionPointer:
                // It's not possible to create function pointers, so use a pointer type instead
                result  = Create(type.AppDomain.System_Void.MakePointerType());
                addType = false;
                break;

            default:
                throw new InvalidOperationException();
            }

            if (result.type == null)
            {
                throw new InvalidOperationException();
            }
            if (addType && !result.containsGenericParameters)
            {
                typeCache.Add(result.type, type);
            }

            recursionCounter--;
            return(result);
        }