[mono-api-info] Add contract-api option
[mono.git] / mcs / tools / corcompare / mono-api-info.cs
index 55c2aeb4283b7e621624cbb808044cac3accf1ab..dd48a6f05b183ab8ea2f547135d76393ebaf9a95 100644 (file)
@@ -59,6 +59,9 @@ namespace CorCompare
                                { "h|?|help",
                                        "Show this message and exit.",
                                        v => showHelp = v != null },
+                               { "contract-api",
+                                       "Produces contract API with all members at each level of inheritance hierarchy",
+                                       v => FullAPISet = v != null },
                        };
 
                        var asms = options.Parse (args);
@@ -116,6 +119,7 @@ namespace CorCompare
 
                internal static bool AbiMode { get; private set; }
                internal static bool FollowForwarders { get; private set; }
+               internal static bool FullAPISet { get; set; }
        }
 
        public class Utils {
@@ -538,7 +542,7 @@ namespace CorCompare
                                        members.Add (new ConstructorData (writer, ctors));
                                }
 
-                               PropertyDefinition[] properties = GetProperties (type);
+                               PropertyDefinition[] properties = GetProperties (type, Driver.FullAPISet);
                                if (properties.Length > 0) {
                                        Array.Sort (properties, PropertyDefinitionComparer.Default);
                                        members.Add (new PropertyData (writer, properties));
@@ -550,7 +554,7 @@ namespace CorCompare
                                        members.Add (new EventData (writer, events));
                                }
 
-                               MethodDefinition [] methods = GetMethods (type);
+                               MethodDefinition [] methods = GetMethods (type, Driver.FullAPISet);
                                if (methods.Length > 0) {
                                        Array.Sort (methods, MethodDefinitionComparer.Default);
                                        members.Add (new MethodData (writer, methods));
@@ -693,53 +697,91 @@ namespace CorCompare
                }
 
 
-               internal static PropertyDefinition [] GetProperties (TypeDefinition type) {
-                       ArrayList list = new ArrayList ();
+               internal static PropertyDefinition [] GetProperties (TypeDefinition type, bool fullAPI) {
+                       var list = new List<PropertyDefinition> ();
+
+                       var t = type;
+                       do {
+                               var properties = t.Properties;//type.GetProperties (flags);
+                               foreach (PropertyDefinition property in properties) {
+                                       MethodDefinition getMethod = property.GetMethod;
+                                       MethodDefinition setMethod = property.SetMethod;
 
-                       var properties = type.Properties;//type.GetProperties (flags);
-                       foreach (PropertyDefinition property in properties) {
-                               MethodDefinition getMethod = property.GetMethod;
-                               MethodDefinition setMethod = property.SetMethod;
+                                       bool hasGetter = (getMethod != null) && MustDocumentMethod (getMethod);
+                                       bool hasSetter = (setMethod != null) && MustDocumentMethod (setMethod);
 
-                               bool hasGetter = (getMethod != null) && MustDocumentMethod (getMethod);
-                               bool hasSetter = (setMethod != null) && MustDocumentMethod (setMethod);
+                                       // if neither the getter or setter should be documented, then
+                                       // skip the property
+                                       if (hasGetter || hasSetter) {
+
+                                               if (t != type && list.Any (l => l.Name == property.Name))
+                                                       continue;
 
-                               // if neither the getter or setter should be documented, then
-                               // skip the property
-                               if (hasGetter || hasSetter) {
-                                       list.Add (property);
+                                               list.Add (property);
+                                       }
                                }
-                       }
 
-                       return (PropertyDefinition []) list.ToArray (typeof (PropertyDefinition));
+                               if (!fullAPI)
+                                       break;
+
+                               if (t.IsInterface || t.IsEnum)
+                                       break;
+
+                               if (t.BaseType == null || t.BaseType.FullName == "System.Object")
+                                       t = null;
+                               else
+                                       t = t.BaseType.Resolve ();
+
+                       } while (t != null);
+
+                       return list.ToArray ();
                }
 
-               private MethodDefinition[] GetMethods (TypeDefinition type)
+               private MethodDefinition[] GetMethods (TypeDefinition type, bool fullAPI)
                {
-                       ArrayList list = new ArrayList ();
+                       var list = new List<MethodDefinition> ();
 
-                       var methods = type.Methods;//type.GetMethods (flags);
-                       foreach (MethodDefinition method in methods) {
-                               if (method.IsSpecialName && !method.Name.StartsWith ("op_", StringComparison.Ordinal))
-                                       continue;
+                       var t = type;
+                       do {
+                               var methods = t.Methods;//type.GetMethods (flags);
+                               foreach (MethodDefinition method in methods) {
+                                       if (method.IsSpecialName && !method.Name.StartsWith ("op_", StringComparison.Ordinal))
+                                               continue;
 
-                               // we're only interested in public or protected members
-                               if (!MustDocumentMethod(method))
-                                       continue;
+                                       // we're only interested in public or protected members
+                                       if (!MustDocumentMethod (method))
+                                               continue;
+
+                                       if (t == type && IsFinalizer (method)) {
+                                               string name = method.DeclaringType.Name;
+                                               int arity = name.IndexOf ('`');
+                                               if (arity > 0)
+                                                       name = name.Substring (0, arity);
 
-                               if (IsFinalizer (method)) {
-                                       string name = method.DeclaringType.Name;
-                                       int arity = name.IndexOf ('`');
-                                       if (arity > 0)
-                                               name = name.Substring (0, arity);
+                                               method.Name = "~" + name;
+                                       }
+
+                                       // TODO: Better check
+                                       if (t != type && list.Any (l => l.DeclaringType != method.DeclaringType && l.Name == method.Name && l.Parameters.Count == method.Parameters.Count))
+                                               continue;
 
-                                       method.Name = "~" + name;
+                                       list.Add (method);
                                }
 
-                               list.Add (method);
-                       }
+                               if (!fullAPI)
+                                       break;
 
-                       return (MethodDefinition []) list.ToArray (typeof (MethodDefinition));
+                               if (!t.IsInterface || t.IsEnum)
+                                       break;
+
+                               if (t.BaseType == null || t.BaseType.FullName == "System.Object")
+                                       t = null;
+                               else
+                                       t = t.BaseType.Resolve ();
+
+                       } while (t != null);
+
+                       return list.ToArray ();
                }
 
                static bool IsFinalizer (MethodDefinition method)