Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRolf Bjarne Kvinge <rolf@xamarin.com>2016-01-28 15:13:25 +0300
committerRolf Bjarne Kvinge <rolf@xamarin.com>2016-01-28 17:32:52 +0300
commit4279991d274796eb3ae6c5507c6194bd3cd69187 (patch)
tree26f3fdcbf6ac68bd7d5537a3ebb390ab2061604c
parent88b287f06584a6284face60accb94d000b1c6ce7 (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.cs107
-rw-r--r--mcs/tools/corcompare/mono-api-info.cs9
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));