From 446634bfd80d8fc9a90922638532094740037abf Mon Sep 17 00:00:00 2001 From: Jb Evain Date: Wed, 2 Dec 2009 16:57:10 +0000 Subject: [PATCH] in System: 2009-12-02 Jb Evain * Environment.cs (mono_corlib_version): bump. * Attribute.cs: when retrieving custom attributes defined on parameters belonging to a virtual method, walk the inheritance chain to check for parameters attributes all the way down. in System.Reflection: 2009-12-02 Jb Evain * MethodInfo.cs: add an internal virtual GetBaseMethod returning the immediate predecessor in the inheritance chain. * MonoMethod.cs: modify the get_base_definition icall to take a boolean indicating that we want the immediate base method or the original method definition and rename it to get_base_method. Implement GetBaseMethod with it. svn path=/trunk/mcs/; revision=147460 --- mcs/class/corlib/System.Reflection/ChangeLog | 9 +++ mcs/class/corlib/System.Reflection/MethodInfo.cs | 5 ++ mcs/class/corlib/System.Reflection/MonoMethod.cs | 9 ++- mcs/class/corlib/System/Attribute.cs | 83 +++++++++++++++++++++--- mcs/class/corlib/System/ChangeLog | 8 +++ mcs/class/corlib/System/Environment.cs | 2 +- 6 files changed, 105 insertions(+), 11 deletions(-) diff --git a/mcs/class/corlib/System.Reflection/ChangeLog b/mcs/class/corlib/System.Reflection/ChangeLog index 3e7ebdeb0a5..821818a0d2c 100644 --- a/mcs/class/corlib/System.Reflection/ChangeLog +++ b/mcs/class/corlib/System.Reflection/ChangeLog @@ -1,3 +1,12 @@ +2009-12-02 Jb Evain + + * MethodInfo.cs: add an internal virtual GetBaseMethod + returning the immediate predecessor in the inheritance chain. + * MonoMethod.cs: modify the get_base_definition icall to take + a boolean indicating that we want the immediate base method + or the original method definition and rename it to + get_base_method. Implement GetBaseMethod with it. + 2009-11-21 Miguel de Icaza * Assembly.cs: Implement missing method. diff --git a/mcs/class/corlib/System.Reflection/MethodInfo.cs b/mcs/class/corlib/System.Reflection/MethodInfo.cs index 31c4d495707..1e5814e04fe 100644 --- a/mcs/class/corlib/System.Reflection/MethodInfo.cs +++ b/mcs/class/corlib/System.Reflection/MethodInfo.cs @@ -41,6 +41,11 @@ namespace System.Reflection { public abstract MethodInfo GetBaseDefinition(); + internal virtual MethodInfo GetBaseMethod () + { + return this; + } + protected MethodInfo() { } diff --git a/mcs/class/corlib/System.Reflection/MonoMethod.cs b/mcs/class/corlib/System.Reflection/MonoMethod.cs index 01254a1409b..49d78bd99b0 100644 --- a/mcs/class/corlib/System.Reflection/MonoMethod.cs +++ b/mcs/class/corlib/System.Reflection/MonoMethod.cs @@ -126,11 +126,16 @@ namespace System.Reflection { internal static extern string get_name (MethodBase method); [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern MonoMethod get_base_definition (MonoMethod method); + internal static extern MonoMethod get_base_method (MonoMethod method, bool definition); public override MethodInfo GetBaseDefinition () { - return get_base_definition (this); + return get_base_method (this, true); + } + + internal override MethodInfo GetBaseMethod () + { + return get_base_method (this, false); } public override ParameterInfo ReturnParameter { diff --git a/mcs/class/corlib/System/Attribute.cs b/mcs/class/corlib/System/Attribute.cs index e5e56eb4906..d2491c73cee 100644 --- a/mcs/class/corlib/System/Attribute.cs +++ b/mcs/class/corlib/System/Attribute.cs @@ -29,6 +29,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +using System.Collections.Generic; using System.Reflection; using System.Runtime.InteropServices; @@ -36,7 +37,6 @@ namespace System { [AttributeUsage (AttributeTargets.All)] [Serializable] - [ComVisible (true)] [ComDefaultInterface (typeof (_Attribute))] [ClassInterfaceAttribute (ClassInterfaceType.None)] @@ -131,9 +131,7 @@ namespace System // neither parameter is allowed to be null CheckParameters (element, attributeType); - // ParameterInfo inheritance hierarchies CAN NOT be searched for attributes, so the second - // parameter of GetCustomAttributes () is IGNORED. - object[] attributes = element.GetCustomAttributes (attributeType, inherit); + object[] attributes = GetCustomAttributes (element, attributeType, inherit); return FindAttribute (attributes); } @@ -201,6 +199,10 @@ namespace System // element parameter is not allowed to be null CheckParameters (element, attributeType); + Attribute [] attributes; + if (inherit && TryGetParamCustomAttributes (element, attributeType, out attributes)) + return attributes; + return (Attribute []) element.GetCustomAttributes (attributeType, inherit); } @@ -263,7 +265,7 @@ namespace System // element parameter is not allowed to be null CheckParameters (element, typeof (Attribute)); - return (Attribute []) element.GetCustomAttributes (inherit); + return GetCustomAttributes (element, typeof (Attribute), inherit); } public override int GetHashCode () @@ -331,7 +333,6 @@ namespace System return element.IsDefined (attributeType, inherit); } - // FIXME: MS apparently walks the inheritance way in some form. public static bool IsDefined (ParameterInfo element, Type attributeType, bool inherit) { CheckParameters (element, attributeType); @@ -339,8 +340,74 @@ namespace System if (element.IsDefined (attributeType, inherit)) return true; - // FIXME: MS walks up the inheritance chain in some crazy way - return IsDefined (element.Member, attributeType, inherit); + if (inherit) + return IsDefinedOnParameter (element, attributeType); + + return false; + } + + static bool IsDefinedOnParameter (ParameterInfo parameter, Type attributeType) + { + var member = parameter.Member; + if (member.MemberType != MemberTypes.Method) + return false; + + var method = ((MethodInfo) member).GetBaseMethod (); + + while (true) { + var param = method.GetParameters () [parameter.Position]; + if (param.IsDefined (attributeType, false)) + return true; + + var base_method = method.GetBaseMethod (); + if (base_method == method) + break; + + method = base_method; + } + + return false; + } + + static bool TryGetParamCustomAttributes (ParameterInfo parameter, Type attributeType, out Attribute [] attributes) + { + attributes = null; + + if (parameter.Member.MemberType != MemberTypes.Method) + return false; + + var method = (MethodInfo) parameter.Member; + var definition = method.GetBaseDefinition (); + + if (method == definition) + return false; + + var types = new List (); + var custom_attributes = new List (); + + while (true) { + var param = method.GetParameters () [parameter.Position]; + var param_attributes = (Attribute []) param.GetCustomAttributes (attributeType, false); + foreach (var param_attribute in param_attributes) { + var param_type = param_attribute.GetType (); + if (types.Contains (param_type)) + continue; + + types.Add (param_type); + custom_attributes.Add (param_attribute); + } + + var base_method = method.GetBaseMethod (); + if (base_method == method) + break; + + method = base_method; + } + + attributes = (Attribute []) Array.CreateInstance (attributeType, custom_attributes.Count); + custom_attributes.CopyTo (attributes, 0); + + return true; } public virtual bool Match (object obj) diff --git a/mcs/class/corlib/System/ChangeLog b/mcs/class/corlib/System/ChangeLog index 15bd0479475..cbfe96cdecc 100644 --- a/mcs/class/corlib/System/ChangeLog +++ b/mcs/class/corlib/System/ChangeLog @@ -1,3 +1,11 @@ +2009-12-02 Jb Evain + + * Environment.cs (mono_corlib_version): bump. + * Attribute.cs: when retrieving custom attributes defined + on parameters belonging to a virtual method, walk + the inheritance chain to check for parameters attributes + all the way down. + 2009-12-01 Jb Evain * Type.cs (MakeByRefType): throw a TypeLoadException when being diff --git a/mcs/class/corlib/System/Environment.cs b/mcs/class/corlib/System/Environment.cs index 1911321af16..3ce400b2537 100644 --- a/mcs/class/corlib/System/Environment.cs +++ b/mcs/class/corlib/System/Environment.cs @@ -54,7 +54,7 @@ namespace System { * Changes which are already detected at runtime, like the addition * of icalls, do not require an increment. */ - private const int mono_corlib_version = 86; + private const int mono_corlib_version = 87; [ComVisible (true)] public enum SpecialFolder -- 2.11.4.GIT