Merge pull request #487 from mayerwin/patch-1
[mono.git] / mcs / class / corlib / System / MonoCustomAttrs.cs
index 8659e7aa570a9eb30e180b878532bee4afc6796d..14641fbe66119662e4a5a903a73eb3316fc13627 100644 (file)
@@ -35,20 +35,39 @@ using System;
 using System.Reflection;
 using System.Collections;
 using System.Runtime.CompilerServices;
+#if !FULL_AOT_RUNTIME
+using System.Reflection.Emit;
+#endif
 
-#if  NET_2_0
 using System.Collections.Generic;
-#endif
 
 namespace System
 {
        internal class MonoCustomAttrs
        {
+               static Assembly corlib;
+
+               /* Treat as user types all corlib types extending System.Type that are not MonoType and TypeBuilder */
+               static bool IsUserCattrProvider (object obj)
+               {
+                       Type type = obj as Type;
+#if !FULL_AOT_RUNTIME
+                       if ((type is MonoType) || (type is TypeBuilder))
+#else
+                       if (type is MonoType)
+#endif
+                               return false;
+                       if ((obj is Type))
+                               return true;
+                       if (corlib == null)
+                                corlib = typeof (int).Assembly;
+                       return obj.GetType ().Assembly != corlib;
+               }
+       
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                internal static extern object[] GetCustomAttributesInternal (ICustomAttributeProvider obj, Type attributeType, bool pseudoAttrs);
 
                internal static object[] GetPseudoCustomAttributes (ICustomAttributeProvider obj, Type attributeType) {
-#if NET_2_0 || BOOTSTRAP_NET_2_0
                        object[] pseudoAttrs = null;
 
                        /* FIXME: Add other types */
@@ -72,14 +91,15 @@ namespace System
                        }
                        else
                                return pseudoAttrs;
-#else
-                       return null;
-#endif
                }
 
                internal static object[] GetCustomAttributesBase (ICustomAttributeProvider obj, Type attributeType)
                {
-                       object[] attrs = GetCustomAttributesInternal (obj, attributeType, false);
+                       object[] attrs;
+                       if (IsUserCattrProvider (obj))
+                               attrs = obj.GetCustomAttributes (attributeType, true);
+                       else
+                               attrs = GetCustomAttributesInternal (obj, attributeType, false);
 
                        object[] pseudoAttrs = GetPseudoCustomAttributes (obj, attributeType);
                        if (pseudoAttrs != null) {
@@ -115,12 +135,20 @@ namespace System
                {
                        if (obj == null)
                                throw new ArgumentNullException ("obj");
+                       if (attributeType == null)
+                               throw new ArgumentNullException ("attributeType");      
 
+                       if (attributeType == typeof (MonoCustomAttrs))
+                               attributeType = null;
+                       
                        object[] r;
                        object[] res = GetCustomAttributesBase (obj, attributeType);
                        // shortcut
                        if (!inherit && res.Length == 1)
                        {
+                               if (res [0] == null)
+                                       throw new CustomAttributeFormatException ("Invalid custom attribute format");
+
                                if (attributeType != null)
                                {
                                        if (attributeType.IsAssignableFrom (res[0].GetType ()))
@@ -166,6 +194,8 @@ namespace System
                                foreach (object attr in res)
                                {
                                        AttributeUsageAttribute usage;
+                                       if (attr == null)
+                                               throw new CustomAttributeFormatException ("Invalid custom attribute format");
 
                                        Type attrType = attr.GetType ();
                                        if (attributeType != null)
@@ -239,10 +269,9 @@ namespace System
                        if (!inherit)
                                return (object[]) GetCustomAttributesBase (obj, null).Clone ();
 
-                       return GetCustomAttributes (obj, null, inherit);
+                       return GetCustomAttributes (obj, typeof (MonoCustomAttrs), inherit);
                }
 
-#if NET_2_0
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                static extern CustomAttributeData [] GetCustomAttributesDataInternal (ICustomAttributeProvider obj);
 
@@ -254,28 +283,38 @@ namespace System
                        CustomAttributeData [] attrs = GetCustomAttributesDataInternal (obj);
                        return Array.AsReadOnly<CustomAttributeData> (attrs);
                }
-#endif
 
                internal static bool IsDefined (ICustomAttributeProvider obj, Type attributeType, bool inherit)
                {
-                       if (obj.GetType ().Assembly != typeof (int).Assembly)
-                               // User types might overwrite GetCustomAttributes () but not 
-                               // IsDefined ().
-                               return obj.GetCustomAttributes (attributeType, inherit).Length > 0;
+                       if (attributeType == null)
+                               throw new ArgumentNullException ("attributeType");
+
+                       AttributeUsageAttribute usage = null;
+                       do {
+                               if (IsUserCattrProvider (obj))
+                                       return obj.IsDefined (attributeType, inherit);
+
+                               if (IsDefinedInternal (obj, attributeType))
+                                       return true;
+
+                               object[] pseudoAttrs = GetPseudoCustomAttributes (obj, attributeType);
+                               if (pseudoAttrs != null) {
+                                       for (int i = 0; i < pseudoAttrs.Length; ++i)
+                                               if (attributeType.IsAssignableFrom (pseudoAttrs[i].GetType ()))
+                                                       return true;
+                               }
 
-                       if (IsDefinedInternal (obj, attributeType))
-                               return true;
+                               if (usage == null) {
+                                       if (!inherit)
+                                               return false;
 
-                       object[] pseudoAttrs = GetPseudoCustomAttributes (obj, attributeType);
-                       if (pseudoAttrs != null) {
-                               for (int i = 0; i < pseudoAttrs.Length; ++i)
-                                       if (attributeType.IsAssignableFrom (pseudoAttrs [i].GetType ()))
-                                               return true;
-                       }
+                                       usage = RetrieveAttributeUsage (attributeType);
+                                       if (!usage.Inherited)
+                                               return false;
+                               }
 
-                       ICustomAttributeProvider btype;
-                       if (inherit && ((btype = GetBase (obj)) != null))
-                               return IsDefined (btype, attributeType, inherit);
+                               obj = GetBase (obj);
+                       } while (obj != null);
 
                        return false;
                }
@@ -283,6 +322,51 @@ namespace System
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                internal static extern bool IsDefinedInternal (ICustomAttributeProvider obj, Type AttributeType);
 
+               static PropertyInfo GetBasePropertyDefinition (PropertyInfo property)
+               {
+                       MethodInfo method = property.GetGetMethod (true);
+                       if (method == null || !method.IsVirtual)
+                               method = property.GetSetMethod (true);
+                       if (method == null || !method.IsVirtual)
+                               return null;
+
+                       MethodInfo baseMethod = method.GetBaseMethod ();
+                       if (baseMethod != null && baseMethod != method) {
+                               ParameterInfo[] parameters = property.GetIndexParameters ();
+                               if (parameters != null && parameters.Length > 0) {
+                                       Type[] paramTypes = new Type[parameters.Length];
+                                       for (int i=0; i < paramTypes.Length; i++)
+                                               paramTypes[i] = parameters[i].ParameterType;
+                                       return baseMethod.DeclaringType.GetProperty (property.Name, property.PropertyType, 
+                                                                                    paramTypes);
+                               } else {
+                                       return baseMethod.DeclaringType.GetProperty (property.Name, property.PropertyType);
+                               }
+                       }
+                       return null;
+
+               }
+
+               static EventInfo GetBaseEventDefinition (EventInfo evt)
+               {
+                       MethodInfo method = evt.GetAddMethod (true);
+                       if (method == null || !method.IsVirtual)
+                               method = evt.GetRaiseMethod (true);
+                       if (method == null || !method.IsVirtual)
+                               method = evt.GetRemoveMethod (true);
+                       if (method == null || !method.IsVirtual)
+                               return null;
+
+                       MethodInfo baseMethod = method.GetBaseMethod ();
+                       if (baseMethod != null && baseMethod != method) {
+                               BindingFlags flags = method.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic;
+                               flags |= method.IsStatic ? BindingFlags.Static : BindingFlags.Instance;
+
+                               return baseMethod.DeclaringType.GetEvent (evt.Name, flags);
+                       }
+                       return null;
+               }
+
                // Handles Type, MonoProperty and MonoMethod.
                // The runtime has also cases for MonoEvent, MonoField, Assembly and ParameterInfo,
                // but for those we return null here.
@@ -296,16 +380,11 @@ namespace System
 
                        MethodInfo method = null;
                        if (obj is MonoProperty)
-                       {
-                               MonoProperty prop = (MonoProperty) obj;
-                               method = prop.GetGetMethod (true);
-                               if (method == null)
-                                       method = prop.GetSetMethod (true);
-                       }
+                               return GetBasePropertyDefinition ((MonoProperty) obj);
+                       else if (obj is MonoEvent)
+                               return GetBaseEventDefinition ((MonoEvent)obj);
                        else if (obj is MonoMethod)
-                       {
                                method = (MethodInfo) obj;
-                       }
 
                        /**
                         * ParameterInfo -> null
@@ -316,7 +395,7 @@ namespace System
                        if (method == null || !method.IsVirtual)
                                return null;
 
-                       MethodInfo baseMethod = method.GetBaseDefinition ();
+                       MethodInfo baseMethod = method.GetBaseMethod ();
                        if (baseMethod == method)
                                return null;
 
@@ -330,8 +409,7 @@ namespace System
                                return new AttributeUsageAttribute (AttributeTargets.Class);
 
                        AttributeUsageAttribute usageAttribute = null;
-                       object[] attribs = GetCustomAttributes (attributeType,
-                               MonoCustomAttrs.AttributeUsageType, false);
+                       object[] attribs = GetCustomAttributes (attributeType, typeof(AttributeUsageAttribute), false);
                        if (attribs.Length == 0)
                        {
                                // if no AttributeUsage was defined on the attribute level, then
@@ -363,7 +441,6 @@ namespace System
                        return ((AttributeUsageAttribute) attribs[0]);
                }
 
-               private static readonly Type AttributeUsageType = typeof(AttributeUsageAttribute);
                private static readonly AttributeUsageAttribute DefaultAttributeUsage =
                        new AttributeUsageAttribute (AttributeTargets.All);