[Pkg-mono-svn-commits] [SCM] mono branch, master, updated. debian/2.4+dfsg-6-26-g8b65c7c
Mirco Bauer
meebey at meebey.net
Wed Aug 5 23:03:41 UTC 2009
The following commit has been merged in the master branch:
commit ecd1828d24a5f6c82766305be8b8f7956fc12b1c
Author: Mirco Bauer <meebey at meebey.net>
Date: Thu Jul 30 15:55:09 2009 +0200
really include the source of mono-api-diff.cs
diff --git a/debian/mono-api-diff.cs b/debian/mono-api-diff.cs
new file mode 100644
index 0000000..9a714cd
--- /dev/null
+++ b/debian/mono-api-diff.cs
@@ -0,0 +1,1851 @@
+//
+// mono-api-diff.cs - Compares 2 xml files produced by mono-api-info and
+// produces a file suitable to build class status pages.
+//
+// Authors:
+// Gonzalo Paniagua Javier (gonzalo at ximian.com)
+// Marek Safar (marek.safar at gmail.com)
+//
+// (C) 2003 Novell, Inc (http://www.novell.com)
+//
+
+using System;
+using System.Collections;
+using System.IO;
+using System.Reflection;
+using System.Text;
+using System.Xml;
+
+namespace Mono.AssemblyCompare
+{
+ class Driver
+ {
+ static int Main (string [] args)
+ {
+ if (args.Length != 2) {
+ Console.WriteLine ("Usage: mono mono-api-diff.exe <assembly 1 xml> <assembly 2 xml>");
+ return 1;
+ }
+
+ XMLAssembly ms = CreateXMLAssembly (args [0]);
+ XMLAssembly mono = CreateXMLAssembly (args [1]);
+ XmlDocument doc = ms.CompareAndGetDocument (mono);
+
+ XmlTextWriter writer = new XmlTextWriter (Console.Out);
+ writer.Formatting = Formatting.Indented;
+ doc.WriteTo (writer);
+
+ return 0;
+ }
+
+ static XMLAssembly CreateXMLAssembly (string file)
+ {
+ XmlDocument doc = new XmlDocument ();
+ doc.Load (File.OpenRead (file));
+
+ XmlNode node = doc.SelectSingleNode ("/assemblies/assembly");
+ XMLAssembly result = new XMLAssembly ();
+ try {
+ result.LoadData (node);
+ } catch (Exception e) {
+ Console.Error.WriteLine ("Error loading {0}: {1}\n{2}", file, e.Message, e);
+ Environment.Exit (1);
+ }
+
+ return result;
+ }
+ }
+
+ class Counters
+ {
+ public int Present;
+ public int PresentTotal;
+ public int Missing;
+ public int MissingTotal;
+ public int Todo;
+ public int TodoTotal;
+
+ public int Extra;
+ public int ExtraTotal;
+ public int Warning;
+ public int WarningTotal;
+ public int ErrorTotal;
+
+ public Counters ()
+ {
+ }
+
+ public void AddPartialToPartial (Counters other)
+ {
+ Present += other.Present;
+ Extra += other.Extra;
+ Missing += other.Missing;
+
+ Todo += other.Todo;
+ Warning += other.Warning;
+ AddPartialToTotal (other);
+ }
+
+ public void AddPartialToTotal (Counters other)
+ {
+ PresentTotal += other.Present;
+ ExtraTotal += other.Extra;
+ MissingTotal += other.Missing;
+
+ TodoTotal += other.Todo;
+ WarningTotal += other.Warning;
+ }
+
+ public void AddTotalToPartial (Counters other)
+ {
+ Present += other.PresentTotal;
+ Extra += other.ExtraTotal;
+ Missing += other.MissingTotal;
+
+ Todo += other.TodoTotal;
+ Warning += other.WarningTotal;
+ AddTotalToTotal (other);
+ }
+
+ public void AddTotalToTotal (Counters other)
+ {
+ PresentTotal += other.PresentTotal;
+ ExtraTotal += other.ExtraTotal;
+ MissingTotal += other.MissingTotal;
+
+ TodoTotal += other.TodoTotal;
+ WarningTotal += other.WarningTotal;
+ ErrorTotal += other.ErrorTotal;
+ }
+
+ public int Total {
+ get { return Present + Missing; }
+ }
+
+ public int AbsTotal {
+ get { return PresentTotal + MissingTotal; }
+ }
+
+ public int Ok {
+ get { return Present - Todo; }
+ }
+
+ public int OkTotal {
+ get { return PresentTotal - TodoTotal - ErrorTotal; }
+ }
+
+ public override string ToString ()
+ {
+ StringWriter sw = new StringWriter ();
+ sw.WriteLine ("Present: {0}", Present);
+ sw.WriteLine ("PresentTotal: {0}", PresentTotal);
+ sw.WriteLine ("Missing: {0}", Missing);
+ sw.WriteLine ("MissingTotal: {0}", MissingTotal);
+ sw.WriteLine ("Todo: {0}", Todo);
+ sw.WriteLine ("TodoTotal: {0}", TodoTotal);
+ sw.WriteLine ("Extra: {0}", Extra);
+ sw.WriteLine ("ExtraTotal: {0}", ExtraTotal);
+ sw.WriteLine ("Warning: {0}", Warning);
+ sw.WriteLine ("WarningTotal: {0}", WarningTotal);
+ sw.WriteLine ("ErrorTotal: {0}", ErrorTotal);
+ sw.WriteLine ("--");
+ return sw.GetStringBuilder ().ToString ();
+ }
+ }
+
+ abstract class XMLData
+ {
+ protected XmlDocument document;
+ protected Counters counters;
+ bool haveWarnings;
+
+ public XMLData ()
+ {
+ counters = new Counters ();
+ }
+
+ public virtual void LoadData (XmlNode node)
+ {
+ }
+
+ protected object [] LoadRecursive (XmlNodeList nodeList, Type type)
+ {
+ ArrayList list = new ArrayList ();
+ foreach (XmlNode node in nodeList) {
+ XMLData data = (XMLData) Activator.CreateInstance (type);
+ data.LoadData (node);
+ list.Add (data);
+ }
+
+ return (object []) list.ToArray (type);
+ }
+
+ public static bool IsMeaninglessAttribute (string s)
+ {
+ if (s == null)
+ return false;
+ if (s == "System.Runtime.CompilerServices.CompilerGeneratedAttribute")
+ return true;
+ return false;
+ }
+
+ public static bool IsMonoTODOAttribute (string s)
+ {
+ if (s == null)
+ return false;
+ if (//s.EndsWith ("MonoTODOAttribute") ||
+ s.EndsWith ("MonoDocumentationNoteAttribute") ||
+ s.EndsWith ("MonoExtensionAttribute") ||
+// s.EndsWith ("MonoInternalNoteAttribute") ||
+ s.EndsWith ("MonoLimitationAttribute") ||
+ s.EndsWith ("MonoNotSupportedAttribute"))
+ return true;
+ return s.EndsWith ("TODOAttribute");
+ }
+
+ protected void AddAttribute (XmlNode node, string name, string value)
+ {
+ XmlAttribute attr = document.CreateAttribute (name);
+ attr.Value = value;
+ node.Attributes.Append (attr);
+ }
+
+ protected void AddExtra (XmlNode node)
+ {
+ //TODO: count all the subnodes?
+ AddAttribute (node, "presence", "extra");
+ AddAttribute (node, "ok", "1");
+ AddAttribute (node, "ok_total", "1");
+ AddAttribute (node, "extra", "1");
+ AddAttribute (node, "extra_total", "1");
+ }
+
+ public void AddCountersAttributes (XmlNode node)
+ {
+ if (counters.Missing > 0)
+ AddAttribute (node, "missing", counters.Missing.ToString ());
+
+ if (counters.Present > 0)
+ AddAttribute (node, "present", counters.Present.ToString ());
+
+ if (counters.Extra > 0)
+ AddAttribute (node, "extra", counters.Extra.ToString ());
+
+ if (counters.Ok > 0)
+ AddAttribute (node, "ok", counters.Ok.ToString ());
+
+ if (counters.Total > 0) {
+ int percent = (100 * counters.Ok / counters.Total);
+ AddAttribute (node, "complete", percent.ToString ());
+ }
+
+ if (counters.Todo > 0)
+ AddAttribute (node, "todo", counters.Todo.ToString ());
+
+ if (counters.Warning > 0)
+ AddAttribute (node, "warning", counters.Warning.ToString ());
+
+ if (counters.MissingTotal > 0)
+ AddAttribute (node, "missing_total", counters.MissingTotal.ToString ());
+
+ if (counters.PresentTotal > 0)
+ AddAttribute (node, "present_total", counters.PresentTotal.ToString ());
+
+ if (counters.ExtraTotal > 0)
+ AddAttribute (node, "extra_total", counters.ExtraTotal.ToString ());
+
+ if (counters.OkTotal > 0)
+ AddAttribute (node, "ok_total", counters.OkTotal.ToString ());
+
+ if (counters.AbsTotal > 0) {
+ int percent = (100 * counters.OkTotal / counters.AbsTotal);
+ AddAttribute (node, "complete_total", percent.ToString ());
+ }
+
+ if (counters.TodoTotal > 0) {
+ AddAttribute (node, "todo_total", counters.TodoTotal.ToString ());
+ //TODO: should be different on error. check error cases in corcompare.
+ AddAttribute (node, "error_total", counters.Todo.ToString ());
+ }
+
+ if (counters.WarningTotal > 0)
+ AddAttribute (node, "warning_total", counters.WarningTotal.ToString ());
+
+ }
+
+ protected void AddWarning (XmlNode parent, string fmt, params object [] args)
+ {
+ counters.Warning++;
+ haveWarnings = true;
+ XmlNode warnings = parent.SelectSingleNode ("warnings");
+ if (warnings == null) {
+ warnings = document.CreateElement ("warnings", null);
+ parent.AppendChild (warnings);
+ }
+
+ AddAttribute (parent, "error", "warning");
+ XmlNode warning = document.CreateElement ("warning", null);
+ AddAttribute (warning, "text", String.Format (fmt, args));
+ warnings.AppendChild (warning);
+ }
+
+ public bool HaveWarnings {
+ get { return haveWarnings; }
+ }
+
+ public Counters Counters {
+ get { return counters; }
+ }
+
+ public abstract void CompareTo (XmlDocument doc, XmlNode parent, object other);
+ }
+
+ abstract class XMLNameGroup : XMLData
+ {
+ protected XmlNode group;
+ protected Hashtable keys;
+
+ public override void LoadData (XmlNode node)
+ {
+ if (node == null)
+ throw new ArgumentNullException ("node");
+
+ if (node.Name != GroupName)
+ throw new FormatException (String.Format ("Expecting <{0}>", GroupName));
+
+ keys = new Hashtable ();
+ foreach (XmlNode n in node.ChildNodes) {
+ string name = n.Attributes ["name"].Value;
+ if (CheckIfAdd (name, n)) {
+ string key = GetNodeKey (name, n);
+ //keys.Add (key, name);
+ keys [key] = name;
+ LoadExtraData (key, n);
+ }
+ }
+ }
+
+ protected virtual bool CheckIfAdd (string value, XmlNode node)
+ {
+ return true;
+ }
+
+ protected virtual void LoadExtraData (string name, XmlNode node)
+ {
+ }
+
+ public override void CompareTo (XmlDocument doc, XmlNode parent, object other)
+ {
+ this.document = doc;
+ if (group == null)
+ group = doc.CreateElement (GroupName, null);
+
+ Hashtable okeys = null;
+ if (other != null && ((XMLNameGroup) other).keys != null) {
+ okeys = ((XMLNameGroup) other).keys;
+ }
+
+ XmlNode node = null;
+ bool onull = (okeys == null);
+ if (keys != null) {
+ foreach (DictionaryEntry entry in keys) {
+ node = doc.CreateElement (Name, null);
+ group.AppendChild (node);
+ string key = (string) entry.Key;
+ string name = (string) entry.Value;
+ AddAttribute (node, "name", name);
+
+ if (!onull && HasKey (key, okeys)) {
+ CompareToInner (key, node, (XMLNameGroup) other);
+ okeys.Remove (key);
+ counters.Present++;
+ } else {
+ AddAttribute (node, "presence", "missing");
+ counters.Missing++;
+ }
+ }
+ }
+
+ if (!onull && okeys.Count != 0) {
+ foreach (string value in okeys.Values) {
+ node = doc.CreateElement (Name, null);
+ AddAttribute (node, "name", (string) value);
+ AddAttribute (node, "presence", "extra");
+ group.AppendChild (node);
+ counters.Extra++;
+ }
+ }
+
+ if (group.HasChildNodes)
+ parent.AppendChild (group);
+ }
+
+ protected virtual void CompareToInner (string name, XmlNode node, XMLNameGroup other)
+ {
+ }
+
+ public virtual string GetNodeKey (string name, XmlNode node)
+ {
+ return name;
+ }
+
+ public virtual bool HasKey (string key, Hashtable other)
+ {
+ return other.ContainsKey (key);
+ }
+
+ public abstract string GroupName { get; }
+ public abstract string Name { get; }
+ }
+
+ class XMLAssembly : XMLData
+ {
+ XMLAttributes attributes;
+ XMLNamespace [] namespaces;
+ string name;
+ string version;
+
+ public override void LoadData (XmlNode node)
+ {
+ if (node == null)
+ throw new ArgumentNullException ("node");
+
+ name = node.Attributes ["name"].Value;
+ version = node.Attributes ["version"].Value;
+ XmlNode atts = node.FirstChild;
+ attributes = new XMLAttributes ();
+ if (atts.Name == "attributes") {
+ attributes.LoadData (atts);
+ atts = atts.NextSibling;
+ }
+
+ if (atts == null || atts.Name != "namespaces") {
+ Console.Error.WriteLine ("Warning: no namespaces found!");
+ return;
+ }
+
+ namespaces = (XMLNamespace []) LoadRecursive (atts.ChildNodes, typeof (XMLNamespace));
+ }
+
+ public override void CompareTo (XmlDocument doc, XmlNode parent, object other)
+ {
+ XMLAssembly assembly = (XMLAssembly) other;
+
+ XmlNode childA = doc.CreateElement ("assembly", null);
+ AddAttribute (childA, "name", name);
+ AddAttribute (childA, "version", version);
+ if (name != assembly.name)
+ AddWarning (childA, "Assembly names not equal: {0}, {1}", name, assembly.name);
+
+ if (version != assembly.version)
+ AddWarning (childA, "Assembly version not equal: {0}, {1}", version, assembly.version);
+
+ parent.AppendChild (childA);
+
+ attributes.CompareTo (doc, childA, assembly.attributes);
+ counters.AddPartialToPartial (attributes.Counters);
+
+ CompareNamespaces (childA, assembly.namespaces);
+ if (assembly.attributes != null && assembly.attributes.IsTodo) {
+ counters.Todo++;
+ counters.TodoTotal++;
+ counters.ErrorTotal++;
+ AddAttribute (childA, "error", "todo");
+ if (assembly.attributes.Comment != null)
+ AddAttribute (childA, "comment", assembly.attributes.Comment);
+ }
+
+ AddCountersAttributes (childA);
+ }
+
+ void CompareNamespaces (XmlNode parent, XMLNamespace [] other)
+ {
+ ArrayList newNS = new ArrayList ();
+ XmlNode group = document.CreateElement ("namespaces", null);
+ parent.AppendChild (group);
+
+ Hashtable oh = CreateHash (other);
+ XmlNode node = null;
+ int count = (namespaces == null) ? 0 : namespaces.Length;
+ for (int i = 0; i < count; i++) {
+ XMLNamespace xns = namespaces [i];
+
+ node = document.CreateElement ("namespace", null);
+ newNS.Add (node);
+ AddAttribute (node, "name", xns.Name);
+
+ int idx = -1;
+ if (oh.ContainsKey (xns.Name))
+ idx = (int) oh [xns.Name];
+ XMLNamespace ons = idx >= 0 ? (XMLNamespace) other [idx] : null;
+ xns.CompareTo (document, node, ons);
+ if (idx >= 0)
+ other [idx] = null;
+ xns.AddCountersAttributes (node);
+ counters.Present++;
+ counters.PresentTotal++;
+ counters.AddPartialToTotal (xns.Counters);
+ }
+
+ if (other != null) {
+ count = other.Length;
+ for (int i = 0; i < count; i++) {
+ XMLNamespace n = other [i];
+ if (n == null)
+ continue;
+
+ node = document.CreateElement ("namespace", null);
+ newNS.Add (node);
+ AddAttribute (node, "name", n.Name);
+ AddExtra (node);
+ counters.ExtraTotal++;
+ }
+ }
+
+ XmlNode [] nodes = (XmlNode []) newNS.ToArray (typeof (XmlNode));
+ Array.Sort (nodes, XmlNodeComparer.Default);
+ foreach (XmlNode nn in nodes)
+ group.AppendChild (nn);
+ }
+
+ static Hashtable CreateHash (XMLNamespace [] other)
+ {
+ Hashtable result = new Hashtable ();
+ if (other != null) {
+ int i = 0;
+ foreach (XMLNamespace n in other) {
+ result [n.Name] = i++;
+ }
+ }
+
+ return result;
+ }
+
+ public XmlDocument CompareAndGetDocument (XMLAssembly other)
+ {
+ XmlDocument doc = new XmlDocument ();
+ this.document = doc;
+ XmlNode parent = doc.CreateElement ("assemblies", null);
+ doc.AppendChild (parent);
+
+ CompareTo (doc, parent, other);
+
+ XmlNode decl = doc.CreateXmlDeclaration ("1.0", null, null);
+ doc.InsertBefore (decl, doc.DocumentElement);
+
+ return doc;
+ }
+ }
+
+ class XMLNamespace : XMLData
+ {
+ string name;
+ XMLClass [] types;
+
+ public override void LoadData (XmlNode node)
+ {
+ if (node == null)
+ throw new ArgumentNullException ("node");
+
+ if (node.Name != "namespace")
+ throw new FormatException ("Expecting <namespace>");
+
+ name = node.Attributes ["name"].Value;
+ XmlNode classes = node.FirstChild;
+ if (classes == null) {
+ Console.Error.WriteLine ("Warning: no classes for {0}", node.Attributes ["name"]);
+ return;
+ }
+
+ if (classes.Name != "classes")
+ throw new FormatException ("Expecting <classes>. Got <" + classes.Name + ">");
+
+ types = (XMLClass []) LoadRecursive (classes.ChildNodes, typeof (XMLClass));
+ }
+
+ public override void CompareTo (XmlDocument doc, XmlNode parent, object other)
+ {
+ this.document = doc;
+ XMLNamespace nspace = (XMLNamespace) other;
+
+ XmlNode childA = doc.CreateElement ("classes", null);
+ parent.AppendChild (childA);
+
+ CompareTypes (childA, nspace != null ? nspace.types : new XMLClass [0]);
+ }
+
+ void CompareTypes (XmlNode parent, XMLClass [] other)
+ {
+ ArrayList newNodes = new ArrayList ();
+ Hashtable oh = CreateHash (other);
+ XmlNode node = null;
+ int count = (types == null) ? 0 : types.Length;
+ for (int i = 0; i < count; i++) {
+ XMLClass xclass = types [i];
+
+ node = document.CreateElement ("class", null);
+ newNodes.Add (node);
+ AddAttribute (node, "name", xclass.Name);
+ AddAttribute (node, "type", xclass.Type);
+
+ int idx = -1;
+ if (oh.ContainsKey (xclass.Name))
+ idx = (int) oh [xclass.Name];
+ xclass.CompareTo (document, node, idx >= 0 ? other [idx] : new XMLClass ());
+ if (idx >= 0)
+ other [idx] = null;
+ counters.AddPartialToPartial (xclass.Counters);
+ }
+
+ if (other != null) {
+ count = other.Length;
+ for (int i = 0; i < count; i++) {
+ XMLClass c = other [i];
+ if (c == null || IsMonoTODOAttribute (c.Name))
+ continue;
+
+ node = document.CreateElement ("class", null);
+ newNodes.Add (node);
+ AddAttribute (node, "name", c.Name);
+ AddAttribute (node, "type", c.Type);
+ AddExtra (node);
+ counters.Extra++;
+ counters.ExtraTotal++;
+ }
+ }
+
+ XmlNode [] nodes = (XmlNode []) newNodes.ToArray (typeof (XmlNode));
+ Array.Sort (nodes, XmlNodeComparer.Default);
+ foreach (XmlNode nn in nodes)
+ parent.AppendChild (nn);
+ }
+
+ static Hashtable CreateHash (XMLClass [] other)
+ {
+ Hashtable result = new Hashtable ();
+ if (other != null) {
+ int i = 0;
+ foreach (XMLClass c in other) {
+ result [c.Name] = i++;
+ }
+ }
+
+ return result;
+ }
+
+ public string Name {
+ get { return name; }
+ }
+ }
+
+ class XMLClass : XMLData
+ {
+ string name;
+ string type;
+ string baseName;
+ bool isSealed;
+ bool isSerializable;
+ bool isAbstract;
+ string charSet;
+ string layout;
+ XMLAttributes attributes;
+ XMLInterfaces interfaces;
+ XMLGenericTypeConstraints genericConstraints;
+ XMLFields fields;
+ XMLConstructors constructors;
+ XMLProperties properties;
+ XMLEvents events;
+ XMLMethods methods;
+ XMLClass [] nested;
+
+ public override void LoadData (XmlNode node)
+ {
+ if (node == null)
+ throw new ArgumentNullException ("node");
+
+ name = node.Attributes ["name"].Value;
+ type = node.Attributes ["type"].Value;
+ XmlAttribute xatt = node.Attributes ["base"];
+ if (xatt != null)
+ baseName = xatt.Value;
+
+ xatt = node.Attributes ["sealed"];
+ isSealed = (xatt != null && xatt.Value == "true");
+
+ xatt = node.Attributes ["abstract"];
+ isAbstract = (xatt != null && xatt.Value == "true");
+
+ xatt = node.Attributes["serializable"];
+ isSerializable = (xatt != null && xatt.Value == "true");
+
+ xatt = node.Attributes["charset"];
+ if (xatt != null)
+ charSet = xatt.Value;
+
+ xatt = node.Attributes["layout"];
+ if (xatt != null)
+ layout = xatt.Value;
+
+ XmlNode child = node.FirstChild;
+ if (child == null) {
+ // Console.Error.WriteLine ("Empty class {0} {1}", name, type);
+ return;
+ }
+
+ if (child.Name == "attributes") {
+ attributes = new XMLAttributes ();
+ attributes.LoadData (child);
+ child = child.NextSibling;
+ }
+
+ if (child != null && child.Name == "interfaces") {
+ interfaces = new XMLInterfaces ();
+ interfaces.LoadData (child);
+ child = child.NextSibling;
+ }
+
+ if (child != null && child.Name == "generic-type-constraints") {
+ genericConstraints = new XMLGenericTypeConstraints ();
+ genericConstraints.LoadData (child);
+ child = child.NextSibling;
+ }
+
+ if (child != null && child.Name == "fields") {
+ fields = new XMLFields ();
+ fields.LoadData (child);
+ child = child.NextSibling;
+ }
+
+ if (child != null && child.Name == "constructors") {
+ constructors = new XMLConstructors ();
+ constructors.LoadData (child);
+ child = child.NextSibling;
+ }
+
+ if (child != null && child.Name == "properties") {
+ properties = new XMLProperties ();
+ properties.LoadData (child);
+ child = child.NextSibling;
+ }
+
+ if (child != null && child.Name == "events") {
+ events = new XMLEvents ();
+ events.LoadData (child);
+ child = child.NextSibling;
+ }
+
+ if (child != null && child.Name == "methods") {
+ methods = new XMLMethods ();
+ methods.LoadData (child);
+ child = child.NextSibling;
+ }
+
+ if (child == null)
+ return;
+
+ if (child.Name != "classes") {
+ Console.WriteLine ("name: {0} type: {1} {2}", name, type, child.NodeType);
+ throw new FormatException ("Expecting <classes>. Got <" + child.Name + ">");
+ }
+
+ nested = (XMLClass []) LoadRecursive (child.ChildNodes, typeof (XMLClass));
+ }
+
+ public override void CompareTo (XmlDocument doc, XmlNode parent, object other)
+ {
+ this.document = doc;
+ XMLClass oclass = (XMLClass) other;
+
+ if (attributes != null || oclass.attributes != null) {
+ if (attributes == null)
+ attributes = new XMLAttributes ();
+
+ attributes.CompareTo (doc, parent, oclass.attributes);
+ counters.AddPartialToPartial (attributes.Counters);
+ if (oclass.attributes != null && oclass.attributes.IsTodo) {
+ counters.Todo++;
+ counters.TodoTotal++;
+ counters.ErrorTotal++;
+ AddAttribute (parent, "error", "todo");
+ if (oclass.attributes.Comment != null)
+ AddAttribute (parent, "comment", oclass.attributes.Comment);
+ }
+ }
+
+ if (type != oclass.type)
+ AddWarning (parent, "Class type is wrong: {0} != {1}", type, oclass.type);
+
+ if (baseName != oclass.baseName)
+ AddWarning (parent, "Base class is wrong: {0} != {1}", baseName, oclass.baseName);
+
+ if (isAbstract != oclass.isAbstract || isSealed != oclass.isSealed) {
+ if ((isAbstract && isSealed) || (oclass.isAbstract && oclass.isSealed))
+ AddWarning (parent, "Should {0}be static", (isAbstract && isSealed) ? "" : "not ");
+ else if (isAbstract != oclass.isAbstract)
+ AddWarning (parent, "Should {0}be abstract", isAbstract ? "" : "not ");
+ else if (isSealed != oclass.isSealed)
+ AddWarning (parent, "Should {0}be sealed", isSealed ? "" : "not ");
+ }
+
+ if (isSerializable != oclass.isSerializable)
+ AddWarning (parent, "Should {0}be serializable", isSerializable ? "" : "not ");
+
+ if (charSet != oclass.charSet)
+ AddWarning (parent, "CharSet is wrong: {0} != {1}", charSet, oclass.charSet);
+
+ if (layout != oclass.layout)
+ AddWarning (parent, "Layout is wrong: {0} != {1}", layout, oclass.layout);
+
+ if (interfaces != null || oclass.interfaces != null) {
+ if (interfaces == null)
+ interfaces = new XMLInterfaces ();
+
+ interfaces.CompareTo (doc, parent, oclass.interfaces);
+ counters.AddPartialToPartial (interfaces.Counters);
+ }
+
+ if (genericConstraints != null || oclass.genericConstraints != null) {
+ if (genericConstraints == null)
+ genericConstraints = new XMLGenericTypeConstraints ();
+
+ genericConstraints.CompareTo (doc, parent, oclass.genericConstraints);
+ counters.AddPartialToPartial (genericConstraints.Counters);
+ }
+
+ if (fields != null || oclass.fields != null) {
+ if (fields == null)
+ fields = new XMLFields ();
+
+ fields.CompareTo (doc, parent, oclass.fields);
+ counters.AddPartialToPartial (fields.Counters);
+ }
+
+ if (constructors != null || oclass.constructors != null) {
+ if (constructors == null)
+ constructors = new XMLConstructors ();
+
+ constructors.CompareTo (doc, parent, oclass.constructors);
+ counters.AddPartialToPartial (constructors.Counters);
+ }
+
+ if (properties != null || oclass.properties != null) {
+ if (properties == null)
+ properties = new XMLProperties ();
+
+ properties.CompareTo (doc, parent, oclass.properties);
+ counters.AddPartialToPartial (properties.Counters);
+ }
+
+ if (events != null || oclass.events != null) {
+ if (events == null)
+ events = new XMLEvents ();
+
+ events.CompareTo (doc, parent, oclass.events);
+ counters.AddPartialToPartial (events.Counters);
+ }
+
+ if (methods != null || oclass.methods != null) {
+ if (methods == null)
+ methods = new XMLMethods ();
+
+ methods.CompareTo (doc, parent, oclass.methods);
+ counters.AddPartialToPartial (methods.Counters);
+ }
+
+ if (nested != null || oclass.nested != null) {
+ XmlNode n = doc.CreateElement ("classes", null);
+ parent.AppendChild (n);
+ CompareTypes (n, oclass.nested);
+ }
+
+ AddCountersAttributes (parent);
+ }
+
+ void CompareTypes (XmlNode parent, XMLClass [] other)
+ {
+ ArrayList newNodes = new ArrayList ();
+ Hashtable oh = CreateHash (other);
+ XmlNode node = null;
+ int count = (nested == null) ? 0 : nested.Length;
+ for (int i = 0; i < count; i++) {
+ XMLClass xclass = nested [i];
+
+ node = document.CreateElement ("class", null);
+ newNodes.Add (node);
+ AddAttribute (node, "name", xclass.Name);
+ AddAttribute (node, "type", xclass.Type);
+
+ if (oh.ContainsKey (xclass.Name)) {
+ int idx = (int) oh [xclass.Name];
+ xclass.CompareTo (document, node, other [idx]);
+ other [idx] = null;
+ counters.AddPartialToPartial (xclass.Counters);
+ } else {
+ // TODO: Should I count here?
+ AddAttribute (node, "presence", "missing");
+ counters.Missing++;
+ counters.MissingTotal++;
+ }
+ }
+
+ if (other != null) {
+ count = other.Length;
+ for (int i = 0; i < count; i++) {
+ XMLClass c = other [i];
+ if (c == null || IsMonoTODOAttribute (c.Name))
+ continue;
+
+ node = document.CreateElement ("class", null);
+ newNodes.Add (node);
+ AddAttribute (node, "name", c.Name);
+ AddAttribute (node, "type", c.Type);
+ AddExtra (node);
+ counters.Extra++;
+ counters.ExtraTotal++;
+ }
+ }
+
+ XmlNode [] nodes = (XmlNode []) newNodes.ToArray (typeof (XmlNode));
+ Array.Sort (nodes, XmlNodeComparer.Default);
+ foreach (XmlNode nn in nodes)
+ parent.AppendChild (nn);
+ }
+
+ static Hashtable CreateHash (XMLClass [] other)
+ {
+ Hashtable result = new Hashtable ();
+ if (other != null) {
+ int i = 0;
+ foreach (XMLClass c in other) {
+ result [c.Name] = i++;
+ }
+ }
+
+ return result;
+ }
+
+ public string Name {
+ get { return name; }
+ }
+
+ public string Type {
+ get { return type; }
+ }
+ }
+
+ class XMLParameter : XMLData
+ {
+ string name;
+ string type;
+ string attrib;
+ string direction;
+ bool isUnsafe;
+ bool isOptional;
+ string defaultValue;
+ XMLAttributes attributes;
+
+ public override void LoadData (XmlNode node)
+ {
+ if (node == null)
+ throw new ArgumentNullException ("node");
+
+ if (node.Name != "parameter")
+ throw new ArgumentException ("Expecting <parameter>");
+
+ name = node.Attributes["name"].Value;
+ type = node.Attributes["type"].Value;
+ attrib = node.Attributes["attrib"].Value;
+ if (node.Attributes ["direction"] != null)
+ direction = node.Attributes["direction"].Value;
+ if (node.Attributes["unsafe"] != null)
+ isUnsafe = bool.Parse (node.Attributes["unsafe"].Value);
+ if (node.Attributes["optional"] != null)
+ isOptional = bool.Parse (node.Attributes["optional"].Value);
+ if (node.Attributes["defaultValue"] != null)
+ defaultValue = node.Attributes["defaultValue"].Value;
+
+ XmlNode child = node.FirstChild;
+ if (child == null)
+ return;
+
+ if (child.Name == "attributes") {
+ attributes = new XMLAttributes ();
+ attributes.LoadData (child);
+ child = child.NextSibling;
+ }
+ }
+
+ public override void CompareTo (XmlDocument doc, XmlNode parent, object other)
+ {
+ this.document = doc;
+
+ XMLParameter oparm = (XMLParameter) other;
+
+ if (name != oparm.name)
+ AddWarning (parent, "Parameter name is wrong: {0} != {1}", name, oparm.name);
+
+ if (type != oparm.type)
+ AddWarning (parent, "Parameter type is wrong: {0} != {1}", type, oparm.type);
+
+ if (attrib != oparm.attrib)
+ AddWarning (parent, "Parameter attributes wrong: {0} != {1}", attrib, oparm.attrib);
+
+ if (direction != oparm.direction)
+ AddWarning (parent, "Parameter direction wrong: {0} != {1}", direction, oparm.direction);
+
+ if (isUnsafe != oparm.isUnsafe)
+ AddWarning (parent, "Parameter unsafe wrong: {0} != {1}", isUnsafe, oparm.isUnsafe);
+
+ if (isOptional != oparm.isOptional)
+ AddWarning (parent, "Parameter optional wrong: {0} != {1}", isOptional, oparm.isOptional);
+
+ if (defaultValue != oparm.defaultValue)
+ AddWarning (parent, "Parameter default value wrong: {0} != {1}", (defaultValue == null) ? "(no default value)" : defaultValue, (oparm.defaultValue == null) ? "(no default value)" : oparm.defaultValue);
+
+ if (attributes != null || oparm.attributes != null) {
+ if (attributes == null)
+ attributes = new XMLAttributes ();
+
+ attributes.CompareTo (doc, parent, oparm.attributes);
+ counters.AddPartialToPartial (attributes.Counters);
+ if (oparm.attributes != null && oparm.attributes.IsTodo) {
+ counters.Todo++;
+ counters.TodoTotal++;
+ counters.ErrorTotal++;
+ AddAttribute (parent, "error", "todo");
+ if (oparm.attributes.Comment != null)
+ AddAttribute (parent, "comment", oparm.attributes.Comment);
+ }
+ }
+ }
+
+ public string Name {
+ get { return name; }
+ }
+ }
+
+ class XMLAttributeProperties: XMLNameGroup
+ {
+ static Hashtable ignored_properties;
+ static XMLAttributeProperties ()
+ {
+ ignored_properties = new Hashtable ();
+ ignored_properties.Add ("System.Reflection.AssemblyKeyFileAttribute", "KeyFile");
+ ignored_properties.Add ("System.Reflection.AssemblyCompanyAttribute", "Company");
+ ignored_properties.Add ("System.Reflection.AssemblyConfigurationAttribute", "Configuration");
+ ignored_properties.Add ("System.Reflection.AssemblyCopyrightAttribute", "Copyright");
+ ignored_properties.Add ("System.Reflection.AssemblyProductAttribute", "Product");
+ ignored_properties.Add ("System.Reflection.AssemblyTrademarkAttribute", "Trademark");
+ ignored_properties.Add ("System.Reflection.AssemblyInformationalVersionAttribute", "InformationalVersion");
+
+ ignored_properties.Add ("System.ObsoleteAttribute", "Message");
+ ignored_properties.Add ("System.IO.IODescriptionAttribute", "Description");
+ ignored_properties.Add ("System.Diagnostics.MonitoringDescriptionAttribute", "Description");
+ }
+
+ Hashtable properties = new Hashtable ();
+ string attribute;
+
+ public XMLAttributeProperties (string attribute)
+ {
+ this.attribute = attribute;
+ }
+
+ public override void LoadData(XmlNode node)
+ {
+ if (node == null)
+ throw new ArgumentNullException ("node");
+
+ if (node.ChildNodes == null)
+ return;
+
+ string ignored = ignored_properties [attribute] as string;
+
+ foreach (XmlNode n in node.ChildNodes) {
+ string name = n.Attributes ["name"].Value;
+ if (ignored == name)
+ continue;
+
+ if (n.Attributes ["null"] != null) {
+ properties.Add (name, null);
+ continue;
+ }
+ string value = n.Attributes ["value"].Value;
+ properties.Add (name, value);
+ }
+ }
+
+ public override void CompareTo (XmlDocument doc, XmlNode parent, object other)
+ {
+ this.document = doc;
+
+ Hashtable other_properties = ((XMLAttributeProperties)other).properties;
+ foreach (DictionaryEntry de in other_properties) {
+ object other_value = properties [de.Key];
+
+ if (de.Value == null) {
+ if (other_value != null)
+ AddWarning (parent, "Property '{0}' is 'null' and should be '{1}'", de.Key, other_value);
+ continue;
+ }
+
+ if (de.Value.Equals (other_value))
+ continue;
+
+ AddWarning (parent, "Property '{0}' is '{1}' and should be '{2}'",
+ de.Key, de.Value, other_value == null ? "null" : other_value);
+ }
+ }
+
+ public override string GroupName {
+ get {
+ return "properties";
+ }
+ }
+
+ public override string Name {
+ get {
+ return "";
+ }
+ }
+ }
+
+ class XMLAttributes : XMLNameGroup
+ {
+ Hashtable properties = new Hashtable ();
+
+ bool isTodo;
+ string comment;
+
+ protected override bool CheckIfAdd (string value, XmlNode node)
+ {
+ if (IsMonoTODOAttribute (value)) {
+ isTodo = true;
+
+ XmlNode pNode = node.SelectSingleNode ("properties");
+ if (pNode != null && pNode.ChildNodes.Count > 0 && pNode.ChildNodes [0].Attributes ["value"] != null) {
+ comment = pNode.ChildNodes [0].Attributes ["value"].Value;
+ }
+ return false;
+ }
+
+ return !IsMeaninglessAttribute (value);
+ }
+
+ protected override void CompareToInner (string name, XmlNode node, XMLNameGroup other)
+ {
+ XMLAttributeProperties other_prop = ((XMLAttributes)other).properties [name] as XMLAttributeProperties;
+ XMLAttributeProperties this_prop = properties [name] as XMLAttributeProperties;
+ if (other_prop == null || this_prop == null)
+ return;
+
+ this_prop.CompareTo (document, node, other_prop);
+ counters.AddPartialToPartial (this_prop.Counters);
+ }
+
+ public override string GetNodeKey (string name, XmlNode node)
+ {
+ string key = null;
+
+ // if multiple attributes with the same name (type) exist, then we
+ // cannot be sure which attributes correspond, so we must use the
+ // name of the attribute (type) and the name/value of its properties
+ // as key
+ XmlNodeList attributes = node.ParentNode.SelectNodes("attribute[@name='" + name + "']");
+ if (attributes.Count > 1) {
+ ArrayList keyParts = new ArrayList ();
+
+ XmlNodeList properties = node.SelectNodes ("properties/property");
+ foreach (XmlNode property in properties) {
+ XmlAttributeCollection attrs = property.Attributes;
+ if (attrs["value"] != null) {
+ keyParts.Add (attrs["name"].Value + "=" + attrs["value"].Value);
+ } else {
+ keyParts.Add (attrs["name"].Value + "=");
+ }
+ }
+
+ // sort properties by name, as order of properties in XML is
+ // undefined
+ keyParts.Sort ();
+
+ // insert name (type) of attribute
+ keyParts.Insert (0, name);
+
+ StringBuilder sb = new StringBuilder ();
+ foreach (string value in keyParts) {
+ sb.Append (value);
+ sb.Append (';');
+ }
+ key = sb.ToString ();
+ } else {
+ key = name;
+ }
+
+ return key;
+ }
+
+ protected override void LoadExtraData(string name, XmlNode node)
+ {
+ XmlNode pNode = node.SelectSingleNode ("properties");
+
+ if (IsMonoTODOAttribute (name)) {
+ isTodo = true;
+ if (pNode.ChildNodes [0].Attributes ["value"] != null) {
+ comment = pNode.ChildNodes [0].Attributes ["value"].Value;
+ }
+ return;
+ }
+
+ if (pNode != null) {
+ XMLAttributeProperties p = new XMLAttributeProperties (name);
+ p.LoadData (pNode);
+
+ properties[name] = p;
+ }
+ }
+
+ public override string GroupName {
+ get { return "attributes"; }
+ }
+
+ public override string Name {
+ get { return "attribute"; }
+ }
+
+ public bool IsTodo {
+ get { return isTodo; }
+ }
+
+ public string Comment {
+ get { return comment; }
+ }
+ }
+
+ class XMLInterfaces : XMLNameGroup
+ {
+ public override string GroupName {
+ get { return "interfaces"; }
+ }
+
+ public override string Name {
+ get { return "interface"; }
+ }
+ }
+
+ abstract class XMLGenericGroup : XMLNameGroup
+ {
+ string attributes;
+
+ protected override void LoadExtraData (string name, XmlNode node)
+ {
+ attributes = ((XmlElement) node).GetAttribute ("generic-attribute");
+ }
+
+ protected override void CompareToInner (string name, XmlNode parent, XMLNameGroup other)
+ {
+ base.CompareToInner (name, parent, other);
+
+ XMLGenericGroup g = (XMLGenericGroup) other;
+ if (attributes != g.attributes)
+ AddWarning (parent, "Incorrect generic attributes: '{0}' != '{1}'", attributes, g.attributes);
+ }
+ }
+
+ class XMLGenericTypeConstraints : XMLGenericGroup
+ {
+ public override string GroupName {
+ get { return "generic-type-constraints"; }
+ }
+
+ public override string Name {
+ get { return "generic-type-constraint"; }
+ }
+ }
+
+ class XMLGenericMethodConstraints : XMLGenericGroup
+ {
+ public override string GroupName {
+ get { return "generic-method-constraints"; }
+ }
+
+ public override string Name {
+ get { return "generic-method-constraint"; }
+ }
+ }
+
+ abstract class XMLMember : XMLNameGroup
+ {
+ Hashtable attributeMap;
+ Hashtable access = new Hashtable ();
+
+ protected override void LoadExtraData (string name, XmlNode node)
+ {
+ XmlAttribute xatt = node.Attributes ["attrib"];
+ if (xatt != null)
+ access [name] = xatt.Value;
+
+ XmlNode orig = node;
+
+ node = node.FirstChild;
+ while (node != null) {
+ if (node != null && node.Name == "attributes") {
+ XMLAttributes a = new XMLAttributes ();
+ a.LoadData (node);
+ if (attributeMap == null)
+ attributeMap = new Hashtable ();
+
+ attributeMap [name] = a;
+ break;
+ }
+ node = node.NextSibling;
+ }
+
+ base.LoadExtraData (name, orig);
+ }
+
+ protected override void CompareToInner (string name, XmlNode parent, XMLNameGroup other)
+ {
+ base.CompareToInner (name, parent, other);
+ XMLMember mb = other as XMLMember;
+ XMLAttributes att = null;
+ XMLAttributes oatt = null;
+ if (attributeMap != null)
+ att = attributeMap [name] as XMLAttributes;
+
+ if (mb != null && mb.attributeMap != null)
+ oatt = mb.attributeMap [name] as XMLAttributes;
+
+ if (att != null || oatt != null) {
+ if (att == null)
+ att = new XMLAttributes ();
+
+ att.CompareTo (document, parent, oatt);
+ counters.AddPartialToPartial(att.Counters);
+ if (oatt != null && oatt.IsTodo) {
+ counters.Todo++;
+ counters.ErrorTotal++;
+ AddAttribute (parent, "error", "todo");
+ if (oatt.Comment != null)
+ AddAttribute (parent, "comment", oatt.Comment);
+ }
+ }
+
+ XMLMember member = (XMLMember) other;
+ string acc = access [name] as string;
+ if (acc == null)
+ return;
+
+ string oacc = null;
+ if (member.access != null)
+ oacc = member.access [name] as string;
+
+ string accName = ConvertToString (Int32.Parse (acc));
+ string oaccName = "";
+ if (oacc != null)
+ oaccName = ConvertToString (Int32.Parse (oacc));
+
+ if (accName != oaccName)
+ AddWarning (parent, "Incorrect attributes: '{0}' != '{1}'", accName, oaccName);
+ }
+
+ protected virtual string ConvertToString (int att)
+ {
+ return null;
+ }
+ }
+
+ class XMLFields : XMLMember
+ {
+ Hashtable fieldTypes;
+ Hashtable fieldValues;
+
+ protected override void LoadExtraData (string name, XmlNode node)
+ {
+ XmlAttribute xatt = node.Attributes ["fieldtype"];
+ if (xatt != null) {
+ if (fieldTypes == null)
+ fieldTypes = new Hashtable ();
+
+ fieldTypes [name] = xatt.Value;
+ }
+
+ xatt = node.Attributes ["value"];
+ if (xatt != null) {
+ if (fieldValues == null)
+ fieldValues = new Hashtable ();
+
+ fieldValues[name] = xatt.Value;
+ }
+
+ base.LoadExtraData (name, node);
+ }
+
+ protected override void CompareToInner (string name, XmlNode parent, XMLNameGroup other)
+ {
+ base.CompareToInner (name, parent, other);
+ XMLFields fields = (XMLFields) other;
+ if (fieldTypes != null) {
+ string ftype = fieldTypes [name] as string;
+ string oftype = null;
+ if (fields.fieldTypes != null)
+ oftype = fields.fieldTypes [name] as string;
+
+ if (ftype != oftype)
+ AddWarning (parent, "Field type is {0} and should be {1}", oftype, ftype);
+ }
+ if (fieldValues != null) {
+ string fvalue = fieldValues [name] as string;
+ string ofvalue = null;
+ if (fields.fieldValues != null)
+ ofvalue = fields.fieldValues [name] as string;
+
+ if (fvalue != ofvalue)
+ AddWarning (parent, "Field value is {0} and should be {1}", ofvalue, fvalue);
+ }
+ }
+
+ protected override string ConvertToString (int att)
+ {
+ FieldAttributes fa = (FieldAttributes) att;
+ return fa.ToString ();
+ }
+
+ public override string GroupName {
+ get { return "fields"; }
+ }
+
+ public override string Name {
+ get { return "field"; }
+ }
+ }
+
+ class XMLParameters : XMLNameGroup
+ {
+ public override void LoadData (XmlNode node)
+ {
+ if (node == null)
+ throw new ArgumentNullException ("node");
+
+ if (node.Name != GroupName)
+ throw new FormatException (String.Format ("Expecting <{0}>", GroupName));
+
+ keys = new Hashtable ();
+ foreach (XmlNode n in node.ChildNodes) {
+ string name = n.Attributes["name"].Value;
+ string key = GetNodeKey (name, n);
+ XMLParameter parm = new XMLParameter ();
+ parm.LoadData (n);
+ keys.Add (key, parm);
+ LoadExtraData (key, n);
+ }
+ }
+
+ public override string GroupName {
+ get {
+ return "parameters";
+ }
+ }
+
+ public override string Name {
+ get {
+ return "parameter";
+ }
+ }
+
+ public override string GetNodeKey (string name, XmlNode node)
+ {
+ return node.Attributes["position"].Value;
+ }
+
+ public override void CompareTo (XmlDocument doc, XmlNode parent, object other)
+ {
+ this.document = doc;
+ if (group == null)
+ group = doc.CreateElement (GroupName, null);
+
+ Hashtable okeys = null;
+ if (other != null && ((XMLParameters) other).keys != null) {
+ okeys = ((XMLParameters) other).keys;
+ }
+
+ XmlNode node = null;
+ bool onull = (okeys == null);
+ if (keys != null) {
+ foreach (DictionaryEntry entry in keys) {
+ node = doc.CreateElement (Name, null);
+ group.AppendChild (node);
+ string key = (string) entry.Key;
+ XMLParameter parm = (XMLParameter) entry.Value;
+ AddAttribute (node, "name", parm.Name);
+
+ if (!onull && HasKey (key, okeys)) {
+ parm.CompareTo (document, node, okeys[key]);
+ counters.AddPartialToPartial (parm.Counters);
+ okeys.Remove (key);
+ counters.Present++;
+ } else {
+ AddAttribute (node, "presence", "missing");
+ counters.Missing++;
+ }
+ }
+ }
+
+ if (!onull && okeys.Count != 0) {
+ foreach (XMLParameter value in okeys.Values) {
+ node = doc.CreateElement (Name, null);
+ AddAttribute (node, "name", value.Name);
+ AddAttribute (node, "presence", "extra");
+ group.AppendChild (node);
+ counters.Extra++;
+ }
+ }
+
+ if (group.HasChildNodes)
+ parent.AppendChild (group);
+ }
+ }
+
+ class XMLProperties : XMLMember
+ {
+ Hashtable nameToMethod = new Hashtable ();
+
+ protected override void CompareToInner (string name, XmlNode parent, XMLNameGroup other)
+ {
+ Counters copy = counters;
+ counters = new Counters();
+
+ XMLProperties oprop = other as XMLProperties;
+ if (oprop != null) {
+ XMLMethods m = nameToMethod [name] as XMLMethods;
+ XMLMethods om = oprop.nameToMethod [name] as XMLMethods;
+ if (m != null || om != null) {
+ if (m == null)
+ m = new XMLMethods ();
+
+ m.CompareTo(document, parent, om);
+ counters.AddPartialToPartial(m.Counters);
+ }
+ }
+
+ base.CompareToInner (name, parent, other);
+ AddCountersAttributes(parent);
+
+ copy.AddPartialToPartial(counters);
+ counters = copy;
+ }
+
+ protected override void LoadExtraData (string name, XmlNode node)
+ {
+ XmlNode orig = node;
+ node = node.FirstChild;
+ while (node != null) {
+ if (node != null && node.Name == "methods") {
+ XMLMethods m = new XMLMethods ();
+ XmlNode parent = node.ParentNode;
+ string key = GetNodeKey (name, parent);
+ m.LoadData (node);
+ nameToMethod [key] = m;
+ break;
+ }
+ node = node.NextSibling;
+ }
+
+ base.LoadExtraData (name, orig);
+ }
+
+ public override string GetNodeKey (string name, XmlNode node)
+ {
+ XmlAttributeCollection atts = node.Attributes;
+ return String.Format ("{0}:{1}:{2}",
+ (atts["name"] != null ? atts["name"].Value : ""),
+ (atts["ptype"] != null ? atts["ptype"].Value : ""),
+ (atts["params"] != null ? atts["params"].Value : "")
+ );
+ }
+
+ public override string GroupName {
+ get { return "properties"; }
+ }
+
+ public override string Name {
+ get { return "property"; }
+ }
+ }
+
+ class XMLEvents : XMLMember
+ {
+ Hashtable eventTypes;
+ Hashtable nameToMethod = new Hashtable ();
+
+ protected override void LoadExtraData (string name, XmlNode node)
+ {
+ XmlAttribute xatt = node.Attributes ["eventtype"];
+ if (xatt != null) {
+ if (eventTypes == null)
+ eventTypes = new Hashtable ();
+
+ 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);
+ }
+
+ protected override void CompareToInner (string name, XmlNode parent, XMLNameGroup other)
+ {
+ Counters copy = counters;
+ counters = new Counters ();
+
+ try {
+ base.CompareToInner (name, parent, other);
+ AddCountersAttributes (parent);
+ if (eventTypes == null)
+ return;
+
+ XMLEvents evt = (XMLEvents) other;
+ string etype = eventTypes [name] as string;
+ string oetype = null;
+ if (evt.eventTypes != null)
+ oetype = evt.eventTypes [name] as string;
+
+ 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);
+ counters = copy;
+ }
+ }
+
+ protected override string ConvertToString (int att)
+ {
+ EventAttributes ea = (EventAttributes) att;
+ return ea.ToString ();
+ }
+
+ public override string GroupName {
+ get { return "events"; }
+ }
+
+ public override string Name {
+ get { return "event"; }
+ }
+ }
+
+ class XMLMethods : XMLMember
+ {
+ Hashtable returnTypes;
+ Hashtable parameters;
+ Hashtable genericConstraints;
+ Hashtable signatureFlags;
+
+ [Flags]
+ enum SignatureFlags
+ {
+ None = 0,
+ Abstract = 1,
+ Virtual = 2,
+ Static = 4,
+ Final = 8,
+ }
+
+ protected override void LoadExtraData (string name, XmlNode node)
+ {
+ XmlAttribute xatt = node.Attributes ["returntype"];
+ if (xatt != null) {
+ if (returnTypes == null)
+ returnTypes = new Hashtable ();
+
+ returnTypes [name] = xatt.Value;
+ }
+
+ SignatureFlags flags = SignatureFlags.None;
+ if (((XmlElement) node).GetAttribute ("abstract") == "true")
+ flags |= SignatureFlags.Abstract;
+ if (((XmlElement) node).GetAttribute ("static") == "true")
+ flags |= SignatureFlags.Static;
+ if (((XmlElement) node).GetAttribute ("virtual") == "true")
+ flags |= SignatureFlags.Virtual;
+ if (((XmlElement) node).GetAttribute ("final") == "true")
+ flags |= SignatureFlags.Final;
+ if (flags != SignatureFlags.None) {
+ if (signatureFlags == null)
+ signatureFlags = new Hashtable ();
+ signatureFlags [name] = flags;
+ }
+
+ XmlNode parametersNode = node.SelectSingleNode ("parameters");
+ if (parametersNode != null) {
+ if (parameters == null)
+ parameters = new Hashtable ();
+
+ XMLParameters parms = new XMLParameters ();
+ parms.LoadData (parametersNode);
+
+ parameters[name] = parms;
+ }
+
+ XmlNode genericNode = node.SelectSingleNode ("generic-method-constraints");
+ if (genericNode != null) {
+ if (genericConstraints == null)
+ genericConstraints = new Hashtable ();
+ XMLGenericMethodConstraints csts = new XMLGenericMethodConstraints ();
+ csts.LoadData (genericNode);
+ genericConstraints [name] = csts;
+ }
+
+ base.LoadExtraData (name, node);
+ }
+
+ public override string GetNodeKey (string name, XmlNode node)
+ {
+ // for explicit/implicit operators we need to include the return
+ // type in the key to allow matching; as a side-effect, differences
+ // in return types will be reported as extra/missing methods
+ //
+ // for regular methods we do not need to take into account the
+ // return type for matching methods; differences in return types
+ // will be reported as a warning on the method
+ if (name.StartsWith ("op_")) {
+ XmlAttribute xatt = node.Attributes ["returntype"];
+ string returnType = xatt != null ? xatt.Value + " " : string.Empty;
+ return returnType + name;
+ }
+ return name;
+ }
+
+ protected override void CompareToInner (string name, XmlNode parent, XMLNameGroup other)
+ {
+ // create backup of actual counters
+ Counters copy = counters;
+ // initialize counters for current method
+ counters = new Counters();
+
+ try {
+ base.CompareToInner(name, parent, other);
+ XMLMethods methods = (XMLMethods) other;
+
+ SignatureFlags flags = signatureFlags != null &&
+ signatureFlags.ContainsKey (name) ?
+ (SignatureFlags) signatureFlags [name] :
+ SignatureFlags.None;
+ SignatureFlags oflags = methods.signatureFlags != null &&
+ methods.signatureFlags.ContainsKey (name) ?
+ (SignatureFlags) methods.signatureFlags [name] :
+ SignatureFlags.None;
+
+ if (flags!= oflags) {
+ if (flags == SignatureFlags.None)
+ AddWarning (parent, String.Format ("should not be {0}", oflags));
+ else if (oflags == SignatureFlags.None)
+ AddWarning (parent, String.Format ("should be {0}", flags));
+ else
+ AddWarning (parent, String.Format ("{0} and should be {1}", oflags, flags));
+ }
+
+ if (returnTypes != null) {
+ string rtype = returnTypes[name] as string;
+ string ortype = null;
+ if (methods.returnTypes != null)
+ ortype = methods.returnTypes[name] as string;
+
+ if (rtype != ortype)
+ AddWarning (parent, "Return type is {0} and should be {1}", ortype, rtype);
+ }
+
+ if (parameters != null) {
+ XMLParameters parms = parameters[name] as XMLParameters;
+ parms.CompareTo (document, parent, methods.parameters[name]);
+ counters.AddPartialToPartial (parms.Counters);
+ }
+ } finally {
+ // output counter attributes in result document
+ AddCountersAttributes(parent);
+
+ // add temporary counters to actual counters
+ copy.AddPartialToPartial(counters);
+ // restore backup of actual counters
+ counters = copy;
+ }
+ }
+
+ protected override string ConvertToString (int att)
+ {
+ MethodAttributes ma = (MethodAttributes) att;
+ // ignore ReservedMasks
+ ma &= ~ MethodAttributes.ReservedMask;
+ ma &= ~ MethodAttributes.VtableLayoutMask;
+ if ((ma & MethodAttributes.FamORAssem) != 0)
+ ma = (ma & ~ MethodAttributes.FamORAssem) | MethodAttributes.Family;
+
+ // ignore the HasSecurity attribute for now
+ if ((ma & MethodAttributes.HasSecurity) != 0)
+ ma = (MethodAttributes) (att - (int) MethodAttributes.HasSecurity);
+
+ // ignore the RequireSecObject attribute for now
+ if ((ma & MethodAttributes.RequireSecObject) != 0)
+ ma = (MethodAttributes) (att - (int) MethodAttributes.RequireSecObject);
+
+ // we don't care if the implementation is forwarded through PInvoke
+ if ((ma & MethodAttributes.PinvokeImpl) != 0)
+ ma = (MethodAttributes) (att - (int) MethodAttributes.PinvokeImpl);
+
+ return ma.ToString ();
+ }
+
+ public override string GroupName {
+ get { return "methods"; }
+ }
+
+ public override string Name {
+ get { return "method"; }
+ }
+ }
+
+ class XMLConstructors : XMLMethods
+ {
+ public override string GroupName {
+ get { return "constructors"; }
+ }
+
+ public override string Name {
+ get { return "constructor"; }
+ }
+ }
+
+ class XmlNodeComparer : IComparer
+ {
+ public static XmlNodeComparer Default = new XmlNodeComparer ();
+
+ public int Compare (object a, object b)
+ {
+ XmlNode na = (XmlNode) a;
+ XmlNode nb = (XmlNode) b;
+ return String.Compare (na.Attributes ["name"].Value, nb.Attributes ["name"].Value);
+ }
+ }
+}
+
--
mono
More information about the Pkg-mono-svn-commits
mailing list