* mono-api.xsl: Added support for event accessors.
authorGert Driesen <drieseng@users.sourceforge.net>
Wed, 21 May 2008 15:05:56 +0000 (15:05 -0000)
committerGert Driesen <drieseng@users.sourceforge.net>
Wed, 21 May 2008 15:05:56 +0000 (15:05 -0000)
* mono-api-diff.cs: Added support for event accessors.
* mono-api-info.cs: Added support for explicit interface
implementations, and groups event accessors with the corresponding
event.

svn path=/trunk/mcs/; revision=103699

mcs/tools/corcompare/ChangeLog
mcs/tools/corcompare/mono-api-diff.cs
mcs/tools/corcompare/mono-api-info.cs
mcs/tools/corcompare/mono-api.xsl

index c24e8d365d6174220464f931d5acd78913768ff3..3e1e5ef5b22e6b00db91a6dd847dd47bbee0eda3 100644 (file)
@@ -1,3 +1,11 @@
+2008-05-21  Gert Driesen  <drieseng@users.sourceforge.net>
+
+       * mono-api.xsl: Added support for event accessors.
+       * mono-api-diff.cs: Added support for event accessors.
+       * mono-api-info.cs: Added support for explicit interface
+       implementations, and groups event accessors with the corresponding
+       event.
+
 2008-05-19  Atsushi Enomoto  <atsushi@ximian.com>
 
        * mono-api-diff.cs : do not report CompilerGeneratedAttribute which
index 71393872eed48fb071a4a46e3a4d586522e4c6c2..3ef9815d9898b9056ba38421fbc3cf2e05a6280a 100644 (file)
@@ -1575,6 +1575,7 @@ namespace Mono.AssemblyCompare
        class XMLEvents : XMLMember
        {
                Hashtable eventTypes;
+               Hashtable nameToMethod = new Hashtable ();
 
                protected override void LoadExtraData (string name, XmlNode node)
                {
@@ -1586,6 +1587,19 @@ namespace Mono.AssemblyCompare
                                eventTypes [name] = xatt.Value;
                        }
 
+                       XmlNode child = node.FirstChild;
+                       while (child != null) {
+                               if (child != null && child.Name == "methods") {
+                                       XMLMethods m = new XMLMethods ();
+                                       XmlNode parent = child.ParentNode;
+                                       string key = GetNodeKey (name, parent);
+                                       m.LoadData (child);
+                                       nameToMethod [key] = m;
+                                       break;
+                               }
+                               child = child.NextSibling;
+                       }
+
                        base.LoadExtraData (name, node);
                }
 
@@ -1608,6 +1622,16 @@ namespace Mono.AssemblyCompare
 
                                if (etype != oetype)
                                        AddWarning (parent, "Event type is {0} and should be {1}", oetype, etype);
+
+                               XMLMethods m = nameToMethod [name] as XMLMethods;
+                               XMLMethods om = evt.nameToMethod [name] as XMLMethods;
+                               if (m != null || om != null) {
+                                       if (m == null)
+                                               m = new XMLMethods ();
+
+                                       m.CompareTo (document, parent, om);
+                                       counters.AddPartialToPartial (m.Counters);
+                               }
                        } finally {
                                AddCountersAttributes (parent);
                                copy.AddPartialToPartial (counters);
index c2ff8a7ca4a1420fe3a4936bd6f5f38ddbbf089b..74ca1c81538d98e48e4dc535e9d788f40441f44b 100644 (file)
@@ -412,10 +412,77 @@ namespace Mono.AssemblyInfo
                        return ((int) type.Attributes).ToString (CultureInfo.InvariantCulture);
                }
 
-               public static bool MustDocumentMethod(MethodBase method)
+               /// <summary>
+               /// The includeExplicit bool was introduced to ignore explicit interface
+               /// implementations for properties and events.
+               ///
+               /// When a property / event implements an explicit interface, then
+               /// the MS class libraries only have the accessors; the corresponding
+               /// property/event is not emitted.
+               /// 
+               /// For an example of a property, see System.Windows.Forms.TreeNodeCollection's
+               /// implementation of ICollection.IsSynchronized.
+               /// 
+               /// For an example of an event, see System.Windows.Forms.PropertyGrid's
+               /// implementation of IComPropertyBrowser.ComComponentNameChanged.
+               /// 
+               /// Both our C# compiler and that of MS always emit the property/event,
+               /// so MS must be using another language and/or compiler for (part of)
+               /// the BCL.
+               ///
+               /// To avoid numerous extra reports in the Class Status Pages, we'll
+               /// ignore properties/events that are explictly implemented.
+               /// 
+               /// The getters/setters themselves are included in the generated API info
+               /// though.
+               /// </summary>
+               public static bool MustDocumentMethod (MethodBase method, bool includeExplicit, out bool explicitImpl)
                {
-                       // All other methods
-                       return (method.IsPublic || method.IsFamily || method.IsFamilyOrAssembly);
+                       explicitImpl = false;
+
+                       if (method.IsPublic || method.IsFamily || method.IsFamilyOrAssembly)
+                               return true;
+
+                       if (!includeExplicit || method.DeclaringType.IsInterface)
+                               return false;
+
+                       Type [] interfaces = method.DeclaringType.GetInterfaces ();
+                       foreach (Type interfaceType in interfaces) {
+                               if (!IsPublicType (interfaceType))
+                                       continue;
+
+                               InterfaceMapping map = method.DeclaringType.GetInterfaceMap (
+                                       interfaceType);
+                               if (Array.IndexOf (map.TargetMethods, method) != -1) {
+                                       explicitImpl = true;
+                                       return true;
+                               }
+                       }
+
+                       return false;
+               }
+
+               public static bool MustDocumentMethod (MethodBase method, bool includeExplicit)
+               {
+                       bool explicitImpl;
+                       return MustDocumentMethod (method, includeExplicit, out explicitImpl);
+               }
+
+               static bool IsPublicType (Type t)
+               {
+                       if (t.IsPublic)
+                               return true;
+                       else if (!t.IsNestedPublic)
+                               return false;
+
+                       while (t.DeclaringType != null) {
+                               t = t.DeclaringType;
+
+                               if (!t.IsPublic && !(t.IsNestedPublic || t.IsNestedFamily || t.IsNestedFamORAssem))
+                                       return false;
+                       }
+
+                       return true;
                }
 
                static string GetClassType (Type t)
@@ -500,8 +567,8 @@ namespace Mono.AssemblyInfo
                                        catch (System.Security.SecurityException) { }
                                }
 
-                               bool hasGetter = (getMethod != null) && MustDocumentMethod (getMethod);
-                               bool hasSetter = (setMethod != null) && MustDocumentMethod (setMethod);
+                               bool hasGetter = (getMethod != null) && MustDocumentMethod (getMethod, false);
+                               bool hasSetter = (setMethod != null) && MustDocumentMethod (setMethod, false);
 
                                // if neither the getter or setter should be documented, then
                                // skip the property
@@ -521,11 +588,13 @@ namespace Mono.AssemblyInfo
 
                        MethodInfo[] methods = type.GetMethods (flags);
                        foreach (MethodInfo method in methods) {
-                               if (method.IsSpecialName && !method.Name.StartsWith ("op_"))
+                               bool explicitImpl;
+
+                               if (!MustDocumentMethod (method, true, out explicitImpl))
                                        continue;
 
-                               // we're only interested in public or protected members
-                               if (!MustDocumentMethod(method))
+                               // avoid writing (property/event) accessors twice
+                               if (!explicitImpl && method.IsSpecialName && !method.Name.StartsWith ("op_"))
                                        continue;
 
                                list.Add (method);
@@ -558,7 +627,7 @@ namespace Mono.AssemblyInfo
                        foreach (EventInfo eventInfo in events) {
                                MethodInfo addMethod = eventInfo.GetAddMethod (true);
 
-                               if (addMethod == null || !MustDocumentMethod (addMethod))
+                               if (addMethod == null || !MustDocumentMethod (addMethod, false))
                                        continue;
 
                                list.Add (eventInfo);
@@ -636,12 +705,11 @@ namespace Mono.AssemblyInfo
                {
                        base.AddExtraData (p, member);
                        PropertyInfo prop = (PropertyInfo) member;
-                       Type t = prop.PropertyType;
                        AddAttribute (p, "ptype", prop.PropertyType.ToString ());
                        MethodInfo _get = prop.GetGetMethod (true);
                        MethodInfo _set = prop.GetSetMethod (true);
-                       bool haveGet = (_get != null && TypeData.MustDocumentMethod(_get));
-                       bool haveSet = (_set != null && TypeData.MustDocumentMethod(_set));
+                       bool haveGet = (_get != null && TypeData.MustDocumentMethod(_get, false));
+                       bool haveSet = (_set != null && TypeData.MustDocumentMethod(_set, false));
                        MethodInfo [] methods;
 
                        if (haveGet && haveSet) {
@@ -702,6 +770,25 @@ namespace Mono.AssemblyInfo
                        base.AddExtraData (p, member);
                        EventInfo evt = (EventInfo) member;
                        AddAttribute (p, "eventtype", evt.EventHandlerType.ToString ());
+
+                       MethodInfo _add = evt.GetAddMethod (true);
+                       MethodInfo _remove = evt.GetRemoveMethod (true);
+                       bool haveAdd = (_add != null && TypeData.MustDocumentMethod (_add, true));
+                       bool haveRemove = (_remove != null && TypeData.MustDocumentMethod (_remove, true));
+                       MethodInfo [] methods;
+
+                       if (haveAdd && haveRemove) {
+                               methods = new MethodInfo [] { _add, _remove };
+                       } else if (haveAdd) {
+                               methods = new MethodInfo [] { _add };
+                       } else if (haveRemove) {
+                               methods = new MethodInfo [] { _remove };
+                       } else {
+                               return;
+                       }
+
+                       MethodData data = new MethodData (document, p, methods);
+                       data.DoOutput ();
                }
 
                public override string ParentTag {
@@ -1070,4 +1157,3 @@ namespace Mono.AssemblyInfo
                }
        }
 }
-
index 37b0a9df662069725429139fc81c87567c4b7218..5aca9cd05b8a738ff03508df0b4ebcf0dce113d4 100644 (file)
                </xsl:apply-templates>
        </xsl:template>
 
+       <!-- accessor -->
+       <xsl:template match="event/methods">
+               <xsl:apply-templates select="method">
+                       <xsl:sort select="@name"/>
+               </xsl:apply-templates>
+       </xsl:template>
+
        <xsl:template match="event[@missing_total or @todo_total or @extra_total or @warning_total or @error or @presence]">
                <div>
                        <xsl:call-template name="ELEMENT">