do not check order sequence if option /order was not used
[mono.git] / mcs / class / IKVM.Reflection / Type.cs
index 841cacf97abfc9ccec7d571c2976c8e2a027c502..bb0273c6ad0b5c9b2fbcbc6f75ab5d90a5b0b99d 100644 (file)
@@ -50,8 +50,10 @@ namespace IKVM.Reflection
                [Flags]
                protected enum TypeFlags
                {
-                       // for use by TypeBuilder
+                       // for use by TypeBuilder or TypeDefImpl
                        IsGenericTypeDefinition = 1,
+
+                       // for use by TypeBuilder
                        HasNestedTypes = 2,
                        Baked = 4,
 
@@ -59,9 +61,12 @@ namespace IKVM.Reflection
                        ValueType = 8,
                        NotValueType = 16,
 
-                       // for use by TypeDef, TypeBuilder or MissingType
+                       // for use by TypeDefImpl, TypeBuilder or MissingType
                        PotentialEnumOrValueType = 32,
                        EnumOrValueType = 64,
+
+                       // for use by TypeDefImpl
+                       NotGenericTypeDefinition = 128,
                }
 
                // prevent subclassing by outsiders
@@ -358,7 +363,8 @@ namespace IKVM.Reflection
                        get { return false; }
                }
 
-               internal virtual bool IsGenericTypeInstance
+               // .NET 4.5 API
+               public virtual bool IsConstructedGenericType
                {
                        get { return false; }
                }
@@ -754,7 +760,6 @@ namespace IKVM.Reflection
 
                private static void AddInterfaces(List<Type> list, Type type)
                {
-                       type.CheckBaked();
                        foreach (Type iface in type.__GetDeclaredInterfaces())
                        {
                                if (!list.Contains(iface))
@@ -801,7 +806,7 @@ namespace IKVM.Reflection
                                                                {
                                                                        baseMethods = new List<MethodInfo>();
                                                                }
-                                                               else if (FindMethod(baseMethods, mi.GetBaseDefinition()))
+                                                               else if (baseMethods.Contains(mi.GetBaseDefinition()))
                                                                {
                                                                        continue;
                                                                }
@@ -815,18 +820,6 @@ namespace IKVM.Reflection
                        return list.ToArray();
                }
 
-               private static bool FindMethod(List<MethodInfo> methods, MethodInfo method)
-               {
-                       foreach (MethodInfo m in methods)
-                       {
-                               if (m.Name == method.Name && m.MethodSignature.Equals(method.MethodSignature))
-                               {
-                                       return true;
-                               }
-                       }
-                       return false;
-               }
-
                public MethodInfo[] GetMethods()
                {
                        return GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
@@ -893,11 +886,33 @@ namespace IKVM.Reflection
                }
 
                public ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
+               {
+                       ConstructorInfo ci1 = null;
+                       if ((bindingAttr & BindingFlags.Instance) != 0)
+                       {
+                               ci1 = GetConstructorImpl(ConstructorInfo.ConstructorName, bindingAttr, binder, types, modifiers);
+                       }
+                       if ((bindingAttr & BindingFlags.Static) != 0)
+                       {
+                               ConstructorInfo ci2 = GetConstructorImpl(ConstructorInfo.TypeConstructorName, bindingAttr, binder, types, modifiers);
+                               if (ci2 != null)
+                               {
+                                       if (ci1 != null)
+                                       {
+                                               throw new AmbiguousMatchException();
+                                       }
+                                       return ci2;
+                               }
+                       }
+                       return ci1;
+               }
+
+               private ConstructorInfo GetConstructorImpl(string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
                {
                        // first we try an exact match and only if that fails we fall back to using the binder
-                       return GetMemberByName<ConstructorInfo>(ConstructorInfo.ConstructorName, bindingAttr | BindingFlags.DeclaredOnly,
+                       return GetMemberByName<ConstructorInfo>(name, bindingAttr | BindingFlags.DeclaredOnly,
                                delegate(ConstructorInfo ctor) { return ctor.MethodSignature.MatchParameterTypes(types); })
-                               ?? GetMethodWithBinder<ConstructorInfo>(ConstructorInfo.ConstructorName, bindingAttr, binder ?? DefaultBinder, types, modifiers);
+                               ?? GetMethodWithBinder<ConstructorInfo>(name, bindingAttr, binder ?? DefaultBinder, types, modifiers);
                }
 
                public ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, CallingConventions callingConvention, Type[] types, ParameterModifier[] modifiers)
@@ -1503,7 +1518,6 @@ namespace IKVM.Reflection
                        get { return Module.Assembly; }
                }
 
-               // note that interface/delegate co- and contravariance is not considered
                public bool IsAssignableFrom(Type type)
                {
                        if (this.Equals(type))
@@ -1528,13 +1542,24 @@ namespace IKVM.Reflection
                                Type e2 = type.GetElementType();
                                return e1.IsValueType == e2.IsValueType && e1.IsAssignableFrom(e2);
                        }
+                       else if (this.IsCovariant(type))
+                       {
+                               return true;
+                       }
                        else if (this.IsSealed)
                        {
                                return false;
                        }
                        else if (this.IsInterface)
                        {
-                               return Array.IndexOf(type.GetInterfaces(), this) != -1;
+                               foreach (Type iface in type.GetInterfaces())
+                               {
+                                       if (this.Equals(iface) || this.IsCovariant(iface))
+                                       {
+                                               return true;
+                                       }
+                               }
+                               return false;
                        }
                        else if (type.IsInterface)
                        {
@@ -1550,6 +1575,48 @@ namespace IKVM.Reflection
                        }
                }
 
+               private bool IsCovariant(Type other)
+               {
+                       if (this.IsConstructedGenericType
+                               && other.IsConstructedGenericType
+                               && this.GetGenericTypeDefinition() == other.GetGenericTypeDefinition())
+                       {
+                               Type[] typeParameters = GetGenericTypeDefinition().GetGenericArguments();
+                               for (int i = 0; i < typeParameters.Length; i++)
+                               {
+                                       Type t1 = this.GetGenericTypeArgument(i);
+                                       Type t2 = other.GetGenericTypeArgument(i);
+                                       if (t1.IsValueType != t2.IsValueType)
+                                       {
+                                               return false;
+                                       }
+                                       switch (typeParameters[i].GenericParameterAttributes & GenericParameterAttributes.VarianceMask)
+                                       {
+                                               case GenericParameterAttributes.Covariant:
+                                                       if (!t1.IsAssignableFrom(t2))
+                                                       {
+                                                               return false;
+                                                       }
+                                                       break;
+                                               case GenericParameterAttributes.Contravariant:
+                                                       if (!t2.IsAssignableFrom(t1))
+                                                       {
+                                                               return false;
+                                                       }
+                                                       break;
+                                               case GenericParameterAttributes.None:
+                                                       if (t1 != t2)
+                                                       {
+                                                               return false;
+                                                       }
+                                                       break;
+                                       }
+                               }
+                               return true;
+                       }
+                       return false;
+               }
+
                public bool IsSubclassOf(Type type)
                {
                        Type thisType = this.BaseType;
@@ -1711,7 +1778,7 @@ namespace IKVM.Reflection
                {
                        get
                        {
-                               IList<CustomAttributeData> cad = GetCustomAttributesData(this.Module.universe.System_AttributeUsageAttribute);
+                               IList<CustomAttributeData> cad = CustomAttributeData.__GetCustomAttributes(this, this.Module.universe.System_AttributeUsageAttribute, false);
                                if (cad.Count == 1)
                                {
                                        foreach (CustomAttributeNamedArgument arg in cad[0].NamedArguments)
@@ -1835,7 +1902,10 @@ namespace IKVM.Reflection
 
                private bool ResolvePotentialEnumOrValueType()
                {
-                       if (this.Assembly == this.Universe.Mscorlib || this.Assembly.GetName().Name.Equals("mscorlib", StringComparison.OrdinalIgnoreCase))
+                       if (this.Assembly == this.Universe.Mscorlib
+                               || this.Assembly.GetName().Name.Equals("mscorlib", StringComparison.OrdinalIgnoreCase)
+                               // check if mscorlib forwards the type (.NETCore profile reference mscorlib forwards System.Enum and System.ValueType to System.Runtime.dll)
+                               || this.Universe.Mscorlib.FindType(new TypeName(__Namespace, __Name)) == this)
                        {
                                typeFlags = (typeFlags & ~TypeFlags.PotentialEnumOrValueType) | TypeFlags.EnumOrValueType;
                                return true;
@@ -1856,11 +1926,6 @@ namespace IKVM.Reflection
                        }
                }
 
-               internal virtual IList<CustomAttributeData> GetInterfaceImplCustomAttributes(Type interfaceType, Type attributeType)
-               {
-                       throw new NotSupportedException();
-               }
-
                internal virtual Universe Universe
                {
                        get { return Module.universe; }
@@ -1875,9 +1940,31 @@ namespace IKVM.Reflection
                {
                        throw new InvalidOperationException();
                }
+
+               internal override int GetCurrentToken()
+               {
+                       return this.MetadataToken;
+               }
+
+               internal sealed override List<CustomAttributeData> GetPseudoCustomAttributes(Type attributeType)
+               {
+                       // types don't have pseudo custom attributes
+                       return null;
+               }
+
+               // in .NET this is an extension method, but we target .NET 2.0, so we have an instance method
+               public TypeInfo GetTypeInfo()
+               {
+                       TypeInfo type = this as TypeInfo;
+                       if (type == null)
+                       {
+                               throw new MissingMemberException(this);
+                       }
+                       return type;
+               }
        }
 
-       abstract class ElementHolderType : Type
+       abstract class ElementHolderType : TypeInfo
        {
                protected readonly Type elementType;
                private int token;
@@ -1988,14 +2075,20 @@ namespace IKVM.Reflection
                        elementType.CheckBaked();
                }
 
-               internal sealed override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               internal sealed override Universe Universe
                {
-                       return CustomAttributeData.EmptyList;
+                       get { return elementType.Universe; }
                }
 
-               internal sealed override Universe Universe
+               internal sealed override bool IsBaked
                {
-                       get { return elementType.Universe; }
+                       get { return elementType.IsBaked; }
+               }
+
+               internal sealed override int GetCurrentToken()
+               {
+                       // we don't have a token, so we return 0 (which is never a valid token)
+                       return 0;
                }
 
                internal abstract string GetSuffix();
@@ -2292,6 +2385,12 @@ namespace IKVM.Reflection
                                return new CustomModifiers();
                        }
 
+                       public override bool __TryGetFieldMarshal(out FieldMarshal fieldMarshal)
+                       {
+                               fieldMarshal = new FieldMarshal();
+                               return false;
+                       }
+
                        public override MemberInfo Member
                        {
                                get { return method.IsConstructor ? (MethodBase)new ConstructorInfoImpl(method) : method; }
@@ -2299,7 +2398,7 @@ namespace IKVM.Reflection
 
                        public override int MetadataToken
                        {
-                               get { return 0x8000000; }
+                               get { return 0x08000000; }
                        }
 
                        internal override Module Module
@@ -2405,7 +2504,7 @@ namespace IKVM.Reflection
                }
        }
 
-       sealed class GenericTypeInstance : Type
+       sealed class GenericTypeInstance : TypeInfo
        {
                private readonly Type type;
                private readonly Type[] args;
@@ -2668,7 +2767,7 @@ namespace IKVM.Reflection
                        get { return true; }
                }
 
-               internal override bool IsGenericTypeInstance
+               public override bool IsConstructedGenericType
                {
                        get { return true; }
                }
@@ -2757,13 +2856,18 @@ namespace IKVM.Reflection
                        return this;
                }
 
-               internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               internal override int GetCurrentToken()
                {
-                       return type.GetCustomAttributesData(attributeType);
+                       return type.GetCurrentToken();
+               }
+
+               internal override bool IsBaked
+               {
+                       get { return type.IsBaked; }
                }
        }
 
-       sealed class FunctionPointerType : Type
+       sealed class FunctionPointerType : TypeInfo
        {
                private readonly Universe universe;
                private readonly __StandAloneMethodSig sig;
@@ -2836,5 +2940,61 @@ namespace IKVM.Reflection
                {
                        return "<FunctionPtr>";
                }
+
+               internal override bool IsBaked
+               {
+                       get { return true; }
+               }
+       }
+
+       sealed class MarkerType : Type
+       {
+               // used by ILGenerator
+               internal static readonly Type Fault = new MarkerType();
+               internal static readonly Type Finally = new MarkerType();
+               internal static readonly Type Filter = new MarkerType();
+               // used by CustomModifiers and SignatureHelper
+               internal static readonly Type ModOpt = new MarkerType();
+               internal static readonly Type ModReq = new MarkerType();
+               // used by SignatureHelper
+               internal static readonly Type Sentinel = new MarkerType();
+               internal static readonly Type Pinned = new MarkerType();
+
+               private MarkerType() { }
+
+               public override Type BaseType
+               {
+                       get { throw new InvalidOperationException(); }
+               }
+
+               public override TypeAttributes Attributes
+               {
+                       get { throw new InvalidOperationException(); }
+               }
+
+               public override string Name
+               {
+                       get { throw new InvalidOperationException(); }
+               }
+
+               public override string FullName
+               {
+                       get { throw new InvalidOperationException(); }
+               }
+
+               public override Module Module
+               {
+                       get { throw new InvalidOperationException(); }
+               }
+
+               internal override bool IsBaked
+               {
+                       get { throw new InvalidOperationException(); }
+               }
+
+               public override bool __IsMissing
+               {
+                       get { throw new InvalidOperationException(); }
+               }
        }
 }