diff options
author | Rolf Bjarne Kvinge <rolf@xamarin.com> | 2016-01-28 15:13:25 +0300 |
---|---|---|
committer | Rolf Bjarne Kvinge <rolf@xamarin.com> | 2016-01-28 17:32:52 +0300 |
commit | 4279991d274796eb3ae6c5507c6194bd3cd69187 (patch) | |
tree | 26f3fdcbf6ac68bd7d5537a3ebb390ab2061604c | |
parent | 88b287f06584a6284face60accb94d000b1c6ce7 (diff) |
[mono-api-info] Add an is-override attribute to determine if a method is overriding another method.
-rw-r--r-- | mcs/tools/corcompare/Util.cs | 107 | ||||
-rw-r--r-- | mcs/tools/corcompare/mono-api-info.cs | 9 |
2 files changed, 116 insertions, 0 deletions
diff --git a/mcs/tools/corcompare/Util.cs b/mcs/tools/corcompare/Util.cs index 782280535dd..fa643ed20f8 100644 --- a/mcs/tools/corcompare/Util.cs +++ b/mcs/tools/corcompare/Util.cs @@ -83,5 +83,112 @@ namespace CorCompare { { return att.AttributeType.Resolve (); } + + static bool IsOverride (MethodDefinition method) + { + return method.IsVirtual && !method.IsNewSlot; + } + + public static MethodDefinition GetBaseMethodInTypeHierarchy (MethodDefinition method) + { + if (!IsOverride (method)) + return method; + + var @base = GetBaseType (method.DeclaringType); + while (@base != null) { + MethodDefinition base_method = TryMatchMethod (@base.Resolve (), method); + if (base_method != null) + return GetBaseMethodInTypeHierarchy (base_method) ?? base_method; + + @base = GetBaseType (@base); + } + + return method; + } + + static MethodDefinition TryMatchMethod (TypeDefinition type, MethodDefinition method) + { + if (!type.HasMethods) + return null; + + foreach (MethodDefinition candidate in type.Methods) + if (MethodMatch (candidate, method)) + return candidate; + + return null; + } + + static bool MethodMatch (MethodDefinition candidate, MethodDefinition method) + { + if (!candidate.IsVirtual) + return false; + + if (candidate.Name != method.Name) + return false; + + if (!TypeMatch (candidate.ReturnType, method.ReturnType)) + return false; + + if (candidate.Parameters.Count != method.Parameters.Count) + return false; + + for (int i = 0; i < candidate.Parameters.Count; i++) + if (!TypeMatch (candidate.Parameters [i].ParameterType, method.Parameters [i].ParameterType)) + return false; + + return true; + } + + public static bool TypeMatch (IModifierType a, IModifierType b) + { + if (!TypeMatch (a.ModifierType, b.ModifierType)) + return false; + + return TypeMatch (a.ElementType, b.ElementType); + } + + public static bool TypeMatch (TypeSpecification a, TypeSpecification b) + { + if (a is GenericInstanceType) + return TypeMatch ((GenericInstanceType) a, (GenericInstanceType) b); + + if (a is IModifierType) + return TypeMatch ((IModifierType) a, (IModifierType) b); + + return TypeMatch (a.ElementType, b.ElementType); + } + + public static bool TypeMatch (GenericInstanceType a, GenericInstanceType b) + { + if (!TypeMatch (a.ElementType, b.ElementType)) + return false; + + if (a.GenericArguments.Count != b.GenericArguments.Count) + return false; + + if (a.GenericArguments.Count == 0) + return true; + + for (int i = 0; i < a.GenericArguments.Count; i++) + if (!TypeMatch (a.GenericArguments [i], b.GenericArguments [i])) + return false; + + return true; + } + + public static bool TypeMatch (TypeReference a, TypeReference b) + { + if (a is GenericParameter) + return true; + + if (a is TypeSpecification || b is TypeSpecification) { + if (a.GetType () != b.GetType ()) + return false; + + return TypeMatch ((TypeSpecification) a, (TypeSpecification) b); + } + + return a.FullName == b.FullName; + } } } diff --git a/mcs/tools/corcompare/mono-api-info.cs b/mcs/tools/corcompare/mono-api-info.cs index f9189a2ce80..8b1ad945095 100644 --- a/mcs/tools/corcompare/mono-api-info.cs +++ b/mcs/tools/corcompare/mono-api-info.cs @@ -1010,6 +1010,15 @@ namespace CorCompare AddAttribute ("sealed", "true"); if (mbase.IsStatic) AddAttribute ("static", "true"); + var baseMethod = TypeHelper.GetBaseMethodInTypeHierarchy (mbase); + if (baseMethod != null && baseMethod != mbase) { + // This indicates whether this method is an override of another method. + // This information is not necessarily available in the api info for any + // particular assembly, because a method is only overriding another if + // there is a base virtual function with the same signature, and that + // base method can come from another assembly. + AddAttribute ("is-override", "true"); + } string rettype = Utils.CleanupTypeName (mbase.MethodReturnType.ReturnType); if (rettype != "System.Void" || !mbase.IsConstructor) AddAttribute ("returntype", (rettype)); |