Prevent race conditions for this cached variable, by using a temporary variable,...
[mono.git] / mcs / class / IKVM.Reflection / Missing.cs
index 4559447fc283ed17d3d1a5c7a9103cbf7d390e89..7fc88bf625d69600501bd51563e6fab0116bc7ee 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/*
   Copyright (C) 2011 Jeroen Frijters
 
   This software is provided 'as-is', without any express or implied
@@ -22,7 +22,6 @@
   
 */
 using System;
-using System.Text;
 using System.Collections.Generic;
 using System.Runtime.InteropServices;
 
@@ -97,6 +96,47 @@ namespace IKVM.Reflection
                }
        }
 
+       public struct MissingGenericMethodBuilder
+       {
+               private readonly MissingMethod method;
+
+               public MissingGenericMethodBuilder(Type declaringType, CallingConventions callingConvention, string name, int genericParameterCount)
+               {
+                       method = new MissingMethod(declaringType, name, new MethodSignature(null, null, new PackedCustomModifiers(), callingConvention, genericParameterCount));
+               }
+
+               public Type[] GetGenericArguments()
+               {
+                       return method.GetGenericArguments();
+               }
+
+               public void SetSignature(Type returnType, CustomModifiers returnTypeCustomModifiers, Type[] parameterTypes, CustomModifiers[] parameterTypeCustomModifiers)
+               {
+                       method.signature = new MethodSignature(
+                               returnType ?? method.Module.universe.System_Void,
+                               Util.Copy(parameterTypes),
+                               PackedCustomModifiers.CreateFromExternal(returnTypeCustomModifiers, parameterTypeCustomModifiers, parameterTypes.Length),
+                               method.signature.CallingConvention,
+                               method.signature.GenericParameterCount);
+               }
+
+               [Obsolete("Please use SetSignature(Type, CustomModifiers, Type[], CustomModifiers[]) instead.")]
+               public void SetSignature(Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers, Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+               {
+                       method.signature = new MethodSignature(
+                               returnType ?? method.Module.universe.System_Void,
+                               Util.Copy(parameterTypes),
+                               PackedCustomModifiers.CreateFromExternal(returnTypeOptionalCustomModifiers, returnTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers, parameterTypeRequiredCustomModifiers, parameterTypes.Length),
+                               method.signature.CallingConvention,
+                               method.signature.GenericParameterCount);
+               }
+
+               public MethodInfo Finish()
+               {
+                       return method;
+               }
+       }
+
        sealed class MissingAssembly : Assembly
        {
                private readonly MissingModule module;
@@ -195,7 +235,7 @@ namespace IKVM.Reflection
                }
        }
 
-       sealed class MissingModule : Module
+       sealed class MissingModule : NonPEModule
        {
                private readonly MissingAssembly assembly;
 
@@ -230,36 +270,6 @@ namespace IKVM.Reflection
                        get { throw new MissingModuleException(this); }
                }
 
-               public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
-               {
-                       throw new MissingModuleException(this);
-               }
-
-               public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
-               {
-                       throw new MissingModuleException(this);
-               }
-
-               public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
-               {
-                       throw new MissingModuleException(this);
-               }
-
-               public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
-               {
-                       throw new MissingModuleException(this);
-               }
-
-               public override string ResolveString(int metadataToken)
-               {
-                       throw new MissingModuleException(this);
-               }
-
-               public override Type[] __ResolveOptionalParameterTypes(int metadataToken)
-               {
-                       throw new MissingModuleException(this);
-               }
-
                public override string ScopeName
                {
                        get { throw new MissingModuleException(this); }
@@ -275,21 +285,6 @@ namespace IKVM.Reflection
                        throw new MissingModuleException(this);
                }
 
-               public override AssemblyName[] __GetReferencedAssemblies()
-               {
-                       throw new MissingModuleException(this);
-               }
-
-               internal override Type GetModuleType()
-               {
-                       throw new MissingModuleException(this);
-               }
-
-               internal override IKVM.Reflection.Reader.ByteReader GetBlob(int blobIndex)
-               {
-                       throw new MissingModuleException(this);
-               }
-
                public override void __GetDataDirectoryEntry(int index, out int rva, out int length)
                {
                        throw new MissingModuleException(this);
@@ -334,6 +329,21 @@ namespace IKVM.Reflection
                {
                        throw new MissingModuleException(this);
                }
+
+               protected override Exception InvalidOperationException()
+               {
+                       return new MissingModuleException(this);
+               }
+
+               protected override Exception NotSupportedException()
+               {
+                       return new MissingModuleException(this);
+               }
+
+               protected override Exception ArgumentOutOfRangeException()
+               {
+                       return new MissingModuleException(this);
+               }
        }
 
        sealed class MissingType : Type
@@ -342,6 +352,8 @@ namespace IKVM.Reflection
                private readonly Type declaringType;
                private readonly string ns;
                private readonly string name;
+               private Type[] typeArgs;
+               private int token;
 
                internal MissingType(Module module, Type declaringType, string ns, string name)
                {
@@ -349,6 +361,7 @@ namespace IKVM.Reflection
                        this.declaringType = declaringType;
                        this.ns = ns;
                        this.name = name;
+                       MarkEnumOrValueType(ns, name);
                }
 
                internal override MethodBase FindMethod(string name, MethodSignature signature)
@@ -361,6 +374,11 @@ namespace IKVM.Reflection
                        return method;
                }
 
+               internal override FieldInfo FindField(string name, FieldSignature signature)
+               {
+                       return new MissingField(this, name, signature);
+               }
+
                internal override Type FindNestedType(TypeName name)
                {
                        return null;
@@ -401,6 +419,22 @@ namespace IKVM.Reflection
                        get { return module; }
                }
 
+               public override bool IsValueType
+               {
+                       get
+                       {
+                               switch (typeFlags & (TypeFlags.ValueType | TypeFlags.NotValueType))
+                               {
+                                       case TypeFlags.ValueType:
+                                               return true;
+                                       case TypeFlags.NotValueType:
+                                               return false;
+                                       default:
+                                               throw new MissingMemberException(this);
+                               }
+                       }
+               }
+
                public override Type BaseType
                {
                        get { throw new MissingMemberException(this); }
@@ -446,12 +480,7 @@ namespace IKVM.Reflection
                        throw new MissingMemberException(this);
                }
 
-               public override Type[] __GetRequiredCustomModifiers()
-               {
-                       throw new MissingMemberException(this);
-               }
-
-               public override Type[] __GetOptionalCustomModifiers()
+               public override CustomModifiers __GetCustomModifiers()
                {
                        throw new MissingMemberException(this);
                }
@@ -461,12 +490,7 @@ namespace IKVM.Reflection
                        throw new MissingMemberException(this);
                }
 
-               public override Type[][] __GetGenericArgumentsRequiredCustomModifiers()
-               {
-                       throw new MissingMemberException(this);
-               }
-
-               public override Type[][] __GetGenericArgumentsOptionalCustomModifiers()
+               public override CustomModifiers[] __GetGenericArgumentsCustomModifiers()
                {
                        throw new MissingMemberException(this);
                }
@@ -486,6 +510,19 @@ namespace IKVM.Reflection
                        get { throw new MissingMemberException(this); }
                }
 
+               internal override Type GetGenericTypeArgument(int index)
+               {
+                       if (typeArgs == null)
+                       {
+                               typeArgs = new Type[index + 1];
+                       }
+                       else if (typeArgs.Length <= index)
+                       {
+                               Array.Resize(ref typeArgs, index + 1);
+                       }
+                       return typeArgs[index] ?? (typeArgs[index] = new MissingTypeParameter(this, index));
+               }
+
                internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
                {
                        throw new MissingMemberException(this);
@@ -495,13 +532,63 @@ namespace IKVM.Reflection
                {
                        return this;
                }
+
+               internal int GetMetadataTokenForMissing()
+               {
+                       return token;
+               }
+
+               internal override Type SetMetadataTokenForMissing(int token)
+               {
+                       this.token = token;
+                       return this;
+               }
+       }
+
+       sealed class MissingTypeParameter : IKVM.Reflection.Reader.TypeParameterType
+       {
+               private readonly MemberInfo owner;
+               private readonly int index;
+
+               internal MissingTypeParameter(MemberInfo owner, int index)
+               {
+                       this.owner = owner;
+                       this.index = index;
+               }
+
+               public override Module Module
+               {
+                       get { return owner.Module; }
+               }
+
+               public override string Name
+               {
+                       get { return null; }
+               }
+
+               public override int GenericParameterPosition
+               {
+                       get { return index; }
+               }
+
+               public override MethodBase DeclaringMethod
+               {
+                       get { return owner as MethodBase; }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return owner as Type; }
+               }
        }
 
        sealed class MissingMethod : MethodInfo
        {
                private readonly Type declaringType;
                private readonly string name;
-               private readonly MethodSignature signature;
+               internal MethodSignature signature;
+               private MethodInfo forwarder;
+               private Type[] typeArgs;
 
                internal MissingMethod(Type declaringType, string name, MethodSignature signature)
                {
@@ -510,9 +597,40 @@ namespace IKVM.Reflection
                        this.signature = signature;
                }
 
+               private MethodInfo Forwarder
+               {
+                       get
+                       {
+                               MethodInfo method = TryGetForwarder();
+                               if (method == null)
+                               {
+                                       throw new MissingMemberException(this);
+                               }
+                               return method;
+                       }
+               }
+
+               private MethodInfo TryGetForwarder()
+               {
+                       if (forwarder == null && !declaringType.__IsMissing)
+                       {
+                               MethodBase mb = declaringType.FindMethod(name, signature);
+                               ConstructorInfo ci = mb as ConstructorInfo;
+                               if (ci != null)
+                               {
+                                       forwarder = ci.GetMethodInfo();
+                               }
+                               else
+                               {
+                                       forwarder = (MethodInfo)mb;
+                               }
+                       }
+                       return forwarder;
+               }
+
                public override bool __IsMissing
                {
-                       get { return true; }
+                       get { return TryGetForwarder() == null; }
                }
 
                public override Type ReturnType
@@ -532,7 +650,7 @@ namespace IKVM.Reflection
 
                internal override int ParameterCount
                {
-                       get { throw new MissingMemberException(this); }
+                       get { return signature.GetParameterCount(); }
                }
 
                private sealed class ParameterInfoImpl : ParameterInfo
@@ -546,9 +664,14 @@ namespace IKVM.Reflection
                                this.index = index;
                        }
 
+                       private ParameterInfo Forwarder
+                       {
+                               get { return index == -1 ? method.Forwarder.ReturnParameter : method.Forwarder.GetParameters()[index]; }
+                       }
+
                        public override string Name
                        {
-                               get { throw new MissingMemberException(method); }
+                               get { return Forwarder.Name; }
                        }
 
                        public override Type ParameterType
@@ -558,7 +681,7 @@ namespace IKVM.Reflection
 
                        public override ParameterAttributes Attributes
                        {
-                               get { throw new MissingMemberException(method); }
+                               get { return Forwarder.Attributes; }
                        }
 
                        public override int Position
@@ -568,25 +691,14 @@ namespace IKVM.Reflection
 
                        public override object RawDefaultValue
                        {
-                               get { throw new MissingMemberException(method); }
-                       }
-
-                       public override Type[] GetOptionalCustomModifiers()
-                       {
-                               if (index == -1)
-                               {
-                                       return Util.Copy(method.signature.GetReturnTypeOptionalCustomModifiers(method));
-                               }
-                               return Util.Copy(method.signature.GetParameterOptionalCustomModifiers(method, index));
+                               get { return Forwarder.RawDefaultValue; }
                        }
 
-                       public override Type[] GetRequiredCustomModifiers()
+                       public override CustomModifiers __GetCustomModifiers()
                        {
-                               if (index == -1)
-                               {
-                                       return Util.Copy(method.signature.GetReturnTypeRequiredCustomModifiers(method));
-                               }
-                               return Util.Copy(method.signature.GetParameterRequiredCustomModifiers(method, index));
+                               return index == -1
+                                       ? method.signature.GetReturnTypeCustomModifiers(method)
+                                       : method.signature.GetParameterCustomModifiers(method, index);
                        }
 
                        public override MemberInfo Member
@@ -596,18 +708,28 @@ namespace IKVM.Reflection
 
                        public override int MetadataToken
                        {
-                               get { throw new MissingMemberException(method); }
+                               get { return Forwarder.MetadataToken; }
                        }
 
                        internal override Module Module
                        {
                                get { return method.Module; }
                        }
+
+                       internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+                       {
+                               return Forwarder.GetCustomAttributesData(attributeType);
+                       }
+
+                       public override string ToString()
+                       {
+                               return Forwarder.ToString();
+                       }
                }
 
                public override ParameterInfo[] GetParameters()
                {
-                       ParameterInfoImpl[] parameters = new ParameterInfoImpl[signature.GetParameterCount()];
+                       ParameterInfo[] parameters = new ParameterInfo[signature.GetParameterCount()];
                        for (int i = 0; i < parameters.Length; i++)
                        {
                                parameters[i] = new ParameterInfoImpl(this, i);
@@ -617,17 +739,17 @@ namespace IKVM.Reflection
 
                public override MethodAttributes Attributes
                {
-                       get { throw new MissingMemberException(this); }
+                       get { return Forwarder.Attributes; }
                }
 
                public override MethodImplAttributes GetMethodImplementationFlags()
                {
-                       throw new MissingMemberException(this);
+                       return Forwarder.GetMethodImplementationFlags();
                }
 
                public override MethodBody GetMethodBody()
                {
-                       throw new MissingMemberException(this);
+                       return Forwarder.GetMethodBody();
                }
 
                public override CallingConventions CallingConvention
@@ -637,7 +759,12 @@ namespace IKVM.Reflection
 
                internal override int ImportTo(IKVM.Reflection.Emit.ModuleBuilder module)
                {
-                       throw new MissingMemberException(this);
+                       MethodInfo method = TryGetForwarder();
+                       if (method != null)
+                       {
+                               return method.ImportTo(module);
+                       }
+                       return module.ImportMethodOrField(declaringType, this.Name, this.MethodSignature);
                }
 
                public override string Name
@@ -668,5 +795,304 @@ namespace IKVM.Reflection
                {
                        return declaringType.GetHashCode() ^ name.GetHashCode() ^ signature.GetHashCode();
                }
+
+               internal override MethodBase BindTypeParameters(Type type)
+               {
+                       MethodInfo forwarder = TryGetForwarder();
+                       if (forwarder != null)
+                       {
+                               return forwarder.BindTypeParameters(type);
+                       }
+                       return new GenericMethodInstance(type, this, null);
+               }
+
+               public override bool ContainsGenericParameters
+               {
+                       get { return Forwarder.ContainsGenericParameters; }
+               }
+
+               internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               {
+                       return Forwarder.GetCustomAttributesData(attributeType);
+               }
+
+               public override Type[] GetGenericArguments()
+               {
+                       MethodInfo method = TryGetForwarder();
+                       if (method != null)
+                       {
+                               return Forwarder.GetGenericArguments();
+                       }
+                       if (typeArgs == null)
+                       {
+                               typeArgs = new Type[signature.GenericParameterCount];
+                               for (int i = 0; i < typeArgs.Length; i++)
+                               {
+                                       typeArgs[i] = new MissingTypeParameter(this, i);
+                               }
+                       }
+                       return Util.Copy(typeArgs);
+               }
+
+               internal override Type GetGenericMethodArgument(int index)
+               {
+                       return GetGenericArguments()[index];
+               }
+
+               internal override int GetGenericMethodArgumentCount()
+               {
+                       return Forwarder.GetGenericMethodArgumentCount();
+               }
+
+               public override MethodInfo GetGenericMethodDefinition()
+               {
+                       return Forwarder.GetGenericMethodDefinition();
+               }
+
+               internal override MethodInfo GetMethodOnTypeDefinition()
+               {
+                       return Forwarder.GetMethodOnTypeDefinition();
+               }
+
+               internal override bool HasThis
+               {
+                       get { return (signature.CallingConvention & (CallingConventions.HasThis | CallingConventions.ExplicitThis)) == CallingConventions.HasThis; }
+               }
+
+               public override bool IsGenericMethod
+               {
+                       get { return IsGenericMethodDefinition; }
+               }
+
+               public override bool IsGenericMethodDefinition
+               {
+                       get { return signature.GenericParameterCount != 0; }
+               }
+
+               public override MethodInfo MakeGenericMethod(params Type[] typeArguments)
+               {
+                       MethodInfo method = TryGetForwarder();
+                       if (method != null)
+                       {
+                               return method.MakeGenericMethod(typeArguments);
+                       }
+                       return new GenericMethodInstance(declaringType, this, typeArguments);
+               }
+
+               public override int MetadataToken
+               {
+                       get { return Forwarder.MetadataToken; }
+               }
+       }
+
+       sealed class MissingField : FieldInfo
+       {
+               private readonly Type declaringType;
+               private readonly string name;
+               private readonly FieldSignature signature;
+               private FieldInfo forwarder;
+
+               internal MissingField(Type declaringType, string name, FieldSignature signature)
+               {
+                       this.declaringType = declaringType;
+                       this.name = name;
+                       this.signature = signature;
+               }
+
+               private FieldInfo Forwarder
+               {
+                       get
+                       {
+                               FieldInfo field = TryGetForwarder();
+                               if (field == null)
+                               {
+                                       throw new MissingMemberException(this);
+                               }
+                               return field;
+                       }
+               }
+
+               private FieldInfo TryGetForwarder()
+               {
+                       if (forwarder == null && !declaringType.__IsMissing)
+                       {
+                               forwarder = declaringType.FindField(name, signature);
+                       }
+                       return forwarder;
+               }
+
+               public override bool __IsMissing
+               {
+                       get { return TryGetForwarder() == null; }
+               }
+
+               public override FieldAttributes Attributes
+               {
+                       get { return Forwarder.Attributes; }
+               }
+
+               public override void __GetDataFromRVA(byte[] data, int offset, int length)
+               {
+                       Forwarder.__GetDataFromRVA(data, offset, length);
+               }
+
+               public override int __FieldRVA
+               {
+                       get { return Forwarder.__FieldRVA; }
+               }
+
+               public override object GetRawConstantValue()
+               {
+                       return Forwarder.GetRawConstantValue();
+               }
+
+               internal override FieldSignature FieldSignature
+               {
+                       get { return signature; }
+               }
+
+               internal override int ImportTo(IKVM.Reflection.Emit.ModuleBuilder module)
+               {
+                       FieldInfo field = TryGetForwarder();
+                       if (field != null)
+                       {
+                               return field.ImportTo(module);
+                       }
+                       return module.ImportMethodOrField(declaringType, this.Name, this.FieldSignature);
+               }
+
+               public override string Name
+               {
+                       get { return name; }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return declaringType.IsModulePseudoType ? null : declaringType; }
+               }
+
+               public override Module Module
+               {
+                       get { return declaringType.Module; }
+               }
+
+               internal override FieldInfo BindTypeParameters(Type type)
+               {
+                       FieldInfo forwarder = TryGetForwarder();
+                       if (forwarder != null)
+                       {
+                               return forwarder.BindTypeParameters(type);
+                       }
+                       return new GenericFieldInstance(type, this);
+               }
+
+               internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
+               {
+                       return Forwarder.GetCustomAttributesData(attributeType);
+               }
+
+               public override int MetadataToken
+               {
+                       get { return Forwarder.MetadataToken; }
+               }
+
+               public override bool Equals(object obj)
+               {
+                       MissingField other = obj as MissingField;
+                       return other != null
+                               && other.declaringType == declaringType
+                               && other.name == name
+                               && other.signature.Equals(signature);
+               }
+
+               public override int GetHashCode()
+               {
+                       return declaringType.GetHashCode() ^ name.GetHashCode() ^ signature.GetHashCode();
+               }
+
+               public override string ToString()
+               {
+                       return this.FieldType.Name + " " + this.Name;
+               }
+       }
+
+       // NOTE this is currently only used by CustomAttributeData (because there is no other way to refer to a property)
+       sealed class MissingProperty : PropertyInfo
+       {
+               private readonly Type declaringType;
+               private readonly string name;
+               private readonly PropertySignature signature;
+
+               internal MissingProperty(Type declaringType, string name, PropertySignature signature)
+               {
+                       this.declaringType = declaringType;
+                       this.name = name;
+                       this.signature = signature;
+               }
+
+               public override PropertyAttributes Attributes
+               {
+                       get { throw new MissingMemberException(this); }
+               }
+
+               public override bool CanRead
+               {
+                       get { throw new MissingMemberException(this); }
+               }
+
+               public override bool CanWrite
+               {
+                       get { throw new MissingMemberException(this); }
+               }
+
+               public override MethodInfo GetGetMethod(bool nonPublic)
+               {
+                       throw new MissingMemberException(this);
+               }
+
+               public override MethodInfo GetSetMethod(bool nonPublic)
+               {
+                       throw new MissingMemberException(this);
+               }
+
+               public override MethodInfo[] GetAccessors(bool nonPublic)
+               {
+                       throw new MissingMemberException(this);
+               }
+
+               public override object GetRawConstantValue()
+               {
+                       throw new MissingMemberException(this);
+               }
+
+               internal override bool IsPublic
+               {
+                       get { throw new MissingMemberException(this); }
+               }
+
+               internal override bool IsStatic
+               {
+                       get { throw new MissingMemberException(this); }
+               }
+
+               internal override PropertySignature PropertySignature
+               {
+                       get { return signature; }
+               }
+
+               public override string Name
+               {
+                       get { return name; }
+               }
+
+               public override Type DeclaringType
+               {
+                       get { return declaringType; }
+               }
+
+               public override Module Module
+               {
+                       get { return declaringType.Module; }
+               }
        }
 }