2 // mono-api-diff.cs - Compares 2 xml files produced by mono-api-info and
3 // produces a file suitable to build class status pages.
6 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // Marek Safar (marek.safar@gmail.com)
10 // C.J. Adams-Collier (cjac@colliertech.org)
12 // (C) 2003 Novell, Inc (http://www.novell.com)
13 // (C) 2009,2010 Collier Technologies (http://www.colliertech.org)
16 using System
.Collections
;
18 using System
.Reflection
;
22 namespace Mono
.AssemblyCompare
26 static int Main (string [] args
)
28 if (args
.Length
!= 2) {
29 Console
.WriteLine ("Usage: mono mono-api-diff.exe <assembly 1 xml> <assembly 2 xml>");
33 XMLAssembly ms
= CreateXMLAssembly (args
[0]);
34 XMLAssembly mono
= CreateXMLAssembly (args
[1]);
35 XmlDocument doc
= ms
.CompareAndGetDocument (mono
);
37 XmlTextWriter writer
= new XmlTextWriter (Console
.Out
);
38 writer
.Formatting
= Formatting
.Indented
;
44 static XMLAssembly
CreateXMLAssembly (string file
)
46 XmlDocument doc
= new XmlDocument ();
47 doc
.Load (File
.OpenRead (file
));
49 XmlNode node
= doc
.SelectSingleNode ("/assemblies/assembly");
50 XMLAssembly result
= new XMLAssembly ();
52 result
.LoadData (node
);
53 } catch (Exception e
) {
54 Console
.Error
.WriteLine ("Error loading {0}: {1}\n{2}", file
, e
.Message
, e
);
65 public int PresentTotal
;
67 public int MissingTotal
;
72 public int ExtraTotal
;
74 public int WarningTotal
;
75 public int ErrorTotal
;
81 public void AddPartialToPartial (Counters other
)
83 Present
+= other
.Present
;
85 Missing
+= other
.Missing
;
88 Warning
+= other
.Warning
;
89 AddPartialToTotal (other
);
92 public void AddPartialToTotal (Counters other
)
94 PresentTotal
+= other
.Present
;
95 ExtraTotal
+= other
.Extra
;
96 MissingTotal
+= other
.Missing
;
98 TodoTotal
+= other
.Todo
;
99 WarningTotal
+= other
.Warning
;
102 public void AddTotalToPartial (Counters other
)
104 Present
+= other
.PresentTotal
;
105 Extra
+= other
.ExtraTotal
;
106 Missing
+= other
.MissingTotal
;
108 Todo
+= other
.TodoTotal
;
109 Warning
+= other
.WarningTotal
;
110 AddTotalToTotal (other
);
113 public void AddTotalToTotal (Counters other
)
115 PresentTotal
+= other
.PresentTotal
;
116 ExtraTotal
+= other
.ExtraTotal
;
117 MissingTotal
+= other
.MissingTotal
;
119 TodoTotal
+= other
.TodoTotal
;
120 WarningTotal
+= other
.WarningTotal
;
121 ErrorTotal
+= other
.ErrorTotal
;
125 get { return Present + Missing; }
128 public int AbsTotal
{
129 get { return PresentTotal + MissingTotal; }
133 get { return Present - Todo; }
137 get { return PresentTotal - TodoTotal - ErrorTotal; }
140 public override string ToString ()
142 StringWriter sw
= new StringWriter ();
143 sw
.WriteLine ("Present: {0}", Present
);
144 sw
.WriteLine ("PresentTotal: {0}", PresentTotal
);
145 sw
.WriteLine ("Missing: {0}", Missing
);
146 sw
.WriteLine ("MissingTotal: {0}", MissingTotal
);
147 sw
.WriteLine ("Todo: {0}", Todo
);
148 sw
.WriteLine ("TodoTotal: {0}", TodoTotal
);
149 sw
.WriteLine ("Extra: {0}", Extra
);
150 sw
.WriteLine ("ExtraTotal: {0}", ExtraTotal
);
151 sw
.WriteLine ("Warning: {0}", Warning
);
152 sw
.WriteLine ("WarningTotal: {0}", WarningTotal
);
153 sw
.WriteLine ("ErrorTotal: {0}", ErrorTotal
);
155 return sw
.GetStringBuilder ().ToString ();
159 abstract class XMLData
161 protected XmlDocument document
;
162 protected Counters counters
;
167 counters
= new Counters ();
170 public virtual void LoadData (XmlNode node
)
174 protected object [] LoadRecursive (XmlNodeList nodeList
, Type type
)
176 ArrayList list
= new ArrayList ();
177 foreach (XmlNode node
in nodeList
) {
178 XMLData data
= (XMLData
) Activator
.CreateInstance (type
);
179 data
.LoadData (node
);
183 return (object []) list
.ToArray (type
);
186 public static bool IsMeaninglessAttribute (string s
)
190 if (s
== "System.Runtime.CompilerServices.CompilerGeneratedAttribute")
195 public static bool IsMonoTODOAttribute (string s
)
199 if (//s.EndsWith ("MonoTODOAttribute") ||
200 s
.EndsWith ("MonoDocumentationNoteAttribute") ||
201 s
.EndsWith ("MonoExtensionAttribute") ||
202 // s.EndsWith ("MonoInternalNoteAttribute") ||
203 s
.EndsWith ("MonoLimitationAttribute") ||
204 s
.EndsWith ("MonoNotSupportedAttribute"))
206 return s
.EndsWith ("TODOAttribute");
209 protected void AddAttribute (XmlNode node
, string name
, string value)
211 XmlAttribute attr
= document
.CreateAttribute (name
);
213 node
.Attributes
.Append (attr
);
216 protected void AddExtra (XmlNode node
)
218 //TODO: count all the subnodes?
219 AddAttribute (node
, "presence", "extra");
220 AddAttribute (node
, "ok", "1");
221 AddAttribute (node
, "ok_total", "1");
222 AddAttribute (node
, "extra", "1");
223 AddAttribute (node
, "extra_total", "1");
226 public void AddCountersAttributes (XmlNode node
)
228 if (counters
.Missing
> 0)
229 AddAttribute (node
, "missing", counters
.Missing
.ToString ());
231 if (counters
.Present
> 0)
232 AddAttribute (node
, "present", counters
.Present
.ToString ());
234 if (counters
.Extra
> 0)
235 AddAttribute (node
, "extra", counters
.Extra
.ToString ());
238 AddAttribute (node
, "ok", counters
.Ok
.ToString ());
240 if (counters
.Total
> 0) {
241 int percent
= (100 * counters
.Ok
/ counters
.Total
);
242 AddAttribute (node
, "complete", percent
.ToString ());
245 if (counters
.Todo
> 0)
246 AddAttribute (node
, "todo", counters
.Todo
.ToString ());
248 if (counters
.Warning
> 0)
249 AddAttribute (node
, "warning", counters
.Warning
.ToString ());
251 if (counters
.MissingTotal
> 0)
252 AddAttribute (node
, "missing_total", counters
.MissingTotal
.ToString ());
254 if (counters
.PresentTotal
> 0)
255 AddAttribute (node
, "present_total", counters
.PresentTotal
.ToString ());
257 if (counters
.ExtraTotal
> 0)
258 AddAttribute (node
, "extra_total", counters
.ExtraTotal
.ToString ());
260 if (counters
.OkTotal
> 0)
261 AddAttribute (node
, "ok_total", counters
.OkTotal
.ToString ());
263 if (counters
.AbsTotal
> 0) {
264 int percent
= (100 * counters
.OkTotal
/ counters
.AbsTotal
);
265 AddAttribute (node
, "complete_total", percent
.ToString ());
268 if (counters
.TodoTotal
> 0) {
269 AddAttribute (node
, "todo_total", counters
.TodoTotal
.ToString ());
270 //TODO: should be different on error. check error cases in corcompare.
271 AddAttribute (node
, "error_total", counters
.Todo
.ToString ());
274 if (counters
.WarningTotal
> 0)
275 AddAttribute (node
, "warning_total", counters
.WarningTotal
.ToString ());
279 protected void AddWarning (XmlNode parent
, string fmt
, params object [] args
)
283 XmlNode warnings
= parent
.SelectSingleNode ("warnings");
284 if (warnings
== null) {
285 warnings
= document
.CreateElement ("warnings", null);
286 parent
.AppendChild (warnings
);
289 AddAttribute (parent
, "error", "warning");
290 XmlNode warning
= document
.CreateElement ("warning", null);
291 AddAttribute (warning
, "text", String
.Format (fmt
, args
));
292 warnings
.AppendChild (warning
);
295 public bool HaveWarnings
{
296 get { return haveWarnings; }
299 public Counters Counters
{
300 get { return counters; }
303 public abstract void CompareTo (XmlDocument doc
, XmlNode parent
, object other
);
306 abstract class XMLNameGroup
: XMLData
308 protected XmlNode
group;
309 protected Hashtable keys
;
311 public override void LoadData (XmlNode node
)
314 throw new ArgumentNullException ("node");
316 if (node
.Name
!= GroupName
)
317 throw new FormatException (String
.Format ("Expecting <{0}>", GroupName
));
319 keys
= new Hashtable ();
320 foreach (XmlNode n
in node
.ChildNodes
) {
321 string name
= n
.Attributes
["name"].Value
;
322 if (CheckIfAdd (name
, n
)) {
323 string key
= GetNodeKey (name
, n
);
324 //keys.Add (key, name);
326 LoadExtraData (key
, n
);
331 protected virtual bool CheckIfAdd (string value, XmlNode node
)
336 protected virtual void LoadExtraData (string name
, XmlNode node
)
340 public override void CompareTo (XmlDocument doc
, XmlNode parent
, object other
)
344 group = doc
.CreateElement (GroupName
, null);
346 Hashtable okeys
= null;
347 if (other
!= null && ((XMLNameGroup
) other
).keys
!= null) {
348 okeys
= ((XMLNameGroup
) other
).keys
;
352 bool onull
= (okeys
== null);
354 foreach (DictionaryEntry entry
in keys
) {
355 node
= doc
.CreateElement (Name
, null);
356 group.AppendChild (node
);
357 string key
= (string) entry
.Key
;
358 string name
= (string) entry
.Value
;
359 AddAttribute (node
, "name", name
);
361 if (!onull
&& HasKey (key
, okeys
)) {
362 CompareToInner (key
, node
, (XMLNameGroup
) other
);
366 AddAttribute (node
, "presence", "missing");
372 if (!onull
&& okeys
.Count
!= 0) {
373 foreach (string value in okeys
.Values
) {
374 node
= doc
.CreateElement (Name
, null);
375 AddAttribute (node
, "name", (string) value);
376 AddAttribute (node
, "presence", "extra");
377 group.AppendChild (node
);
382 if (group.HasChildNodes
)
383 parent
.AppendChild (group);
386 protected virtual void CompareToInner (string name
, XmlNode node
, XMLNameGroup other
)
390 public virtual string GetNodeKey (string name
, XmlNode node
)
395 public virtual bool HasKey (string key
, Hashtable other
)
397 return other
.ContainsKey (key
);
400 public abstract string GroupName { get; }
401 public abstract string Name { get; }
404 class XMLAssembly
: XMLData
406 XMLAttributes attributes
;
407 XMLNamespace
[] namespaces
;
411 public override void LoadData (XmlNode node
)
414 throw new ArgumentNullException ("node");
416 name
= node
.Attributes
["name"].Value
;
417 version
= node
.Attributes
["version"].Value
;
418 XmlNode atts
= node
.FirstChild
;
419 attributes
= new XMLAttributes ();
420 if (atts
.Name
== "attributes") {
421 attributes
.LoadData (atts
);
422 atts
= atts
.NextSibling
;
425 if (atts
== null || atts
.Name
!= "namespaces") {
426 Console
.Error
.WriteLine ("Warning: no namespaces found!");
430 namespaces
= (XMLNamespace
[]) LoadRecursive (atts
.ChildNodes
, typeof (XMLNamespace
));
433 public override void CompareTo (XmlDocument doc
, XmlNode parent
, object other
)
435 XMLAssembly assembly
= (XMLAssembly
) other
;
437 XmlNode childA
= doc
.CreateElement ("assembly", null);
438 AddAttribute (childA
, "name", name
);
439 AddAttribute (childA
, "version", version
);
440 if (name
!= assembly
.name
)
441 AddWarning (childA
, "Assembly names not equal: {0}, {1}", name
, assembly
.name
);
443 if (version
!= assembly
.version
)
444 AddWarning (childA
, "Assembly version not equal: {0}, {1}", version
, assembly
.version
);
446 parent
.AppendChild (childA
);
448 attributes
.CompareTo (doc
, childA
, assembly
.attributes
);
449 counters
.AddPartialToPartial (attributes
.Counters
);
451 CompareNamespaces (childA
, assembly
.namespaces
);
452 if (assembly
.attributes
!= null && assembly
.attributes
.IsTodo
) {
454 counters
.TodoTotal
++;
455 counters
.ErrorTotal
++;
456 AddAttribute (childA
, "error", "todo");
457 if (assembly
.attributes
.Comment
!= null)
458 AddAttribute (childA
, "comment", assembly
.attributes
.Comment
);
461 AddCountersAttributes (childA
);
464 void CompareNamespaces (XmlNode parent
, XMLNamespace
[] other
)
466 ArrayList newNS
= new ArrayList ();
467 XmlNode
group = document
.CreateElement ("namespaces", null);
468 parent
.AppendChild (group);
470 Hashtable oh
= CreateHash (other
);
472 int count
= (namespaces
== null) ? 0 : namespaces
.Length
;
473 for (int i
= 0; i
< count
; i
++) {
474 XMLNamespace xns
= namespaces
[i
];
476 node
= document
.CreateElement ("namespace", null);
478 AddAttribute (node
, "name", xns
.Name
);
481 if (oh
.ContainsKey (xns
.Name
))
482 idx
= (int) oh
[xns
.Name
];
483 XMLNamespace ons
= idx
>= 0 ? (XMLNamespace
) other
[idx
] : null;
484 xns
.CompareTo (document
, node
, ons
);
487 xns
.AddCountersAttributes (node
);
489 counters
.PresentTotal
++;
490 counters
.AddPartialToTotal (xns
.Counters
);
494 count
= other
.Length
;
495 for (int i
= 0; i
< count
; i
++) {
496 XMLNamespace n
= other
[i
];
500 node
= document
.CreateElement ("namespace", null);
502 AddAttribute (node
, "name", n
.Name
);
504 counters
.ExtraTotal
++;
508 XmlNode
[] nodes
= (XmlNode
[]) newNS
.ToArray (typeof (XmlNode
));
509 Array
.Sort (nodes
, XmlNodeComparer
.Default
);
510 foreach (XmlNode nn
in nodes
)
511 group.AppendChild (nn
);
514 static Hashtable
CreateHash (XMLNamespace
[] other
)
516 Hashtable result
= new Hashtable ();
519 foreach (XMLNamespace n
in other
) {
520 result
[n
.Name
] = i
++;
527 public XmlDocument
CompareAndGetDocument (XMLAssembly other
)
529 XmlDocument doc
= new XmlDocument ();
531 XmlNode parent
= doc
.CreateElement ("assemblies", null);
532 doc
.AppendChild (parent
);
534 CompareTo (doc
, parent
, other
);
536 XmlNode decl
= doc
.CreateXmlDeclaration ("1.0", null, null);
537 doc
.InsertBefore (decl
, doc
.DocumentElement
);
543 class XMLNamespace
: XMLData
548 public override void LoadData (XmlNode node
)
551 throw new ArgumentNullException ("node");
553 if (node
.Name
!= "namespace")
554 throw new FormatException ("Expecting <namespace>");
556 name
= node
.Attributes
["name"].Value
;
557 XmlNode classes
= node
.FirstChild
;
558 if (classes
== null) {
559 Console
.Error
.WriteLine ("Warning: no classes for {0}", node
.Attributes
["name"]);
563 if (classes
.Name
!= "classes")
564 throw new FormatException ("Expecting <classes>. Got <" + classes
.Name
+ ">");
566 types
= (XMLClass
[]) LoadRecursive (classes
.ChildNodes
, typeof (XMLClass
));
569 public override void CompareTo (XmlDocument doc
, XmlNode parent
, object other
)
572 XMLNamespace nspace
= (XMLNamespace
) other
;
574 XmlNode childA
= doc
.CreateElement ("classes", null);
575 parent
.AppendChild (childA
);
577 CompareTypes (childA
, nspace
!= null ? nspace
.types
: new XMLClass
[0]);
580 void CompareTypes (XmlNode parent
, XMLClass
[] other
)
582 ArrayList newNodes
= new ArrayList ();
583 Hashtable oh
= CreateHash (other
);
585 int count
= (types
== null) ? 0 : types
.Length
;
586 for (int i
= 0; i
< count
; i
++) {
587 XMLClass xclass
= types
[i
];
589 node
= document
.CreateElement ("class", null);
591 AddAttribute (node
, "name", xclass
.Name
);
592 AddAttribute (node
, "type", xclass
.Type
);
595 if (oh
.ContainsKey (xclass
.Name
))
596 idx
= (int) oh
[xclass
.Name
];
597 xclass
.CompareTo (document
, node
, idx
>= 0 ? other
[idx
] : new XMLClass ());
600 counters
.AddPartialToPartial (xclass
.Counters
);
604 count
= other
.Length
;
605 for (int i
= 0; i
< count
; i
++) {
606 XMLClass c
= other
[i
];
607 if (c
== null || IsMonoTODOAttribute (c
.Name
))
610 node
= document
.CreateElement ("class", null);
612 AddAttribute (node
, "name", c
.Name
);
613 AddAttribute (node
, "type", c
.Type
);
616 counters
.ExtraTotal
++;
620 XmlNode
[] nodes
= (XmlNode
[]) newNodes
.ToArray (typeof (XmlNode
));
621 Array
.Sort (nodes
, XmlNodeComparer
.Default
);
622 foreach (XmlNode nn
in nodes
)
623 parent
.AppendChild (nn
);
626 static Hashtable
CreateHash (XMLClass
[] other
)
628 Hashtable result
= new Hashtable ();
631 foreach (XMLClass c
in other
) {
632 result
[c
.Name
] = i
++;
644 class XMLClass
: XMLData
654 XMLAttributes attributes
;
655 XMLInterfaces interfaces
;
656 XMLGenericTypeConstraints genericConstraints
;
658 XMLConstructors constructors
;
659 XMLProperties properties
;
664 public override void LoadData (XmlNode node
)
667 throw new ArgumentNullException ("node");
669 name
= node
.Attributes
["name"].Value
;
670 type
= node
.Attributes
["type"].Value
;
671 XmlAttribute xatt
= node
.Attributes
["base"];
673 baseName
= xatt
.Value
;
675 xatt
= node
.Attributes
["sealed"];
676 isSealed
= (xatt
!= null && xatt
.Value
== "true");
678 xatt
= node
.Attributes
["abstract"];
679 isAbstract
= (xatt
!= null && xatt
.Value
== "true");
681 xatt
= node
.Attributes
["serializable"];
682 isSerializable
= (xatt
!= null && xatt
.Value
== "true");
684 xatt
= node
.Attributes
["charset"];
686 charSet
= xatt
.Value
;
688 xatt
= node
.Attributes
["layout"];
692 XmlNode child
= node
.FirstChild
;
694 // Console.Error.WriteLine ("Empty class {0} {1}", name, type);
698 if (child
.Name
== "attributes") {
699 attributes
= new XMLAttributes ();
700 attributes
.LoadData (child
);
701 child
= child
.NextSibling
;
704 if (child
!= null && child
.Name
== "interfaces") {
705 interfaces
= new XMLInterfaces ();
706 interfaces
.LoadData (child
);
707 child
= child
.NextSibling
;
710 if (child
!= null && child
.Name
== "generic-type-constraints") {
711 genericConstraints
= new XMLGenericTypeConstraints ();
712 genericConstraints
.LoadData (child
);
713 child
= child
.NextSibling
;
716 if (child
!= null && child
.Name
== "fields") {
717 fields
= new XMLFields ();
718 fields
.LoadData (child
);
719 child
= child
.NextSibling
;
722 if (child
!= null && child
.Name
== "constructors") {
723 constructors
= new XMLConstructors ();
724 constructors
.LoadData (child
);
725 child
= child
.NextSibling
;
728 if (child
!= null && child
.Name
== "properties") {
729 properties
= new XMLProperties ();
730 properties
.LoadData (child
);
731 child
= child
.NextSibling
;
734 if (child
!= null && child
.Name
== "events") {
735 events
= new XMLEvents ();
736 events
.LoadData (child
);
737 child
= child
.NextSibling
;
740 if (child
!= null && child
.Name
== "methods") {
741 methods
= new XMLMethods ();
742 methods
.LoadData (child
);
743 child
= child
.NextSibling
;
746 if (child
!= null && child
.Name
== "generic-parameters") {
747 // HACK: ignore this tag as it doesn't seem to
748 // add any value when checking for differences
755 if (child
.Name
!= "classes") {
756 Console
.WriteLine ("name: {0} type: {1} {2}", name
, type
, child
.NodeType
);
757 throw new FormatException ("Expecting <classes>. Got <" + child
.Name
+ ">");
760 nested
= (XMLClass
[]) LoadRecursive (child
.ChildNodes
, typeof (XMLClass
));
763 public override void CompareTo (XmlDocument doc
, XmlNode parent
, object other
)
766 XMLClass oclass
= (XMLClass
) other
;
768 if (attributes
!= null || oclass
.attributes
!= null) {
769 if (attributes
== null)
770 attributes
= new XMLAttributes ();
772 attributes
.CompareTo (doc
, parent
, oclass
.attributes
);
773 counters
.AddPartialToPartial (attributes
.Counters
);
774 if (oclass
.attributes
!= null && oclass
.attributes
.IsTodo
) {
776 counters
.TodoTotal
++;
777 counters
.ErrorTotal
++;
778 AddAttribute (parent
, "error", "todo");
779 if (oclass
.attributes
.Comment
!= null)
780 AddAttribute (parent
, "comment", oclass
.attributes
.Comment
);
784 if (type
!= oclass
.type
)
785 AddWarning (parent
, "Class type is wrong: {0} != {1}", type
, oclass
.type
);
787 if (baseName
!= oclass
.baseName
)
788 AddWarning (parent
, "Base class is wrong: {0} != {1}", baseName
, oclass
.baseName
);
790 if (isAbstract
!= oclass
.isAbstract
|| isSealed
!= oclass
.isSealed
) {
791 if ((isAbstract
&& isSealed
) || (oclass
.isAbstract
&& oclass
.isSealed
))
792 AddWarning (parent
, "Should {0}be static", (isAbstract
&& isSealed
) ? "" : "not ");
793 else if (isAbstract
!= oclass
.isAbstract
)
794 AddWarning (parent
, "Should {0}be abstract", isAbstract
? "" : "not ");
795 else if (isSealed
!= oclass
.isSealed
)
796 AddWarning (parent
, "Should {0}be sealed", isSealed
? "" : "not ");
799 if (isSerializable
!= oclass
.isSerializable
)
800 AddWarning (parent
, "Should {0}be serializable", isSerializable
? "" : "not ");
802 if (charSet
!= oclass
.charSet
)
803 AddWarning (parent
, "CharSet is wrong: {0} != {1}", charSet
, oclass
.charSet
);
805 if (layout
!= oclass
.layout
)
806 AddWarning (parent
, "Layout is wrong: {0} != {1}", layout
, oclass
.layout
);
808 if (interfaces
!= null || oclass
.interfaces
!= null) {
809 if (interfaces
== null)
810 interfaces
= new XMLInterfaces ();
812 interfaces
.CompareTo (doc
, parent
, oclass
.interfaces
);
813 counters
.AddPartialToPartial (interfaces
.Counters
);
816 if (genericConstraints
!= null || oclass
.genericConstraints
!= null) {
817 if (genericConstraints
== null)
818 genericConstraints
= new XMLGenericTypeConstraints ();
820 genericConstraints
.CompareTo (doc
, parent
, oclass
.genericConstraints
);
821 counters
.AddPartialToPartial (genericConstraints
.Counters
);
824 if (fields
!= null || oclass
.fields
!= null) {
826 fields
= new XMLFields ();
828 fields
.CompareTo (doc
, parent
, oclass
.fields
);
829 counters
.AddPartialToPartial (fields
.Counters
);
832 if (constructors
!= null || oclass
.constructors
!= null) {
833 if (constructors
== null)
834 constructors
= new XMLConstructors ();
836 constructors
.CompareTo (doc
, parent
, oclass
.constructors
);
837 counters
.AddPartialToPartial (constructors
.Counters
);
840 if (properties
!= null || oclass
.properties
!= null) {
841 if (properties
== null)
842 properties
= new XMLProperties ();
844 properties
.CompareTo (doc
, parent
, oclass
.properties
);
845 counters
.AddPartialToPartial (properties
.Counters
);
848 if (events
!= null || oclass
.events
!= null) {
850 events
= new XMLEvents ();
852 events
.CompareTo (doc
, parent
, oclass
.events
);
853 counters
.AddPartialToPartial (events
.Counters
);
856 if (methods
!= null || oclass
.methods
!= null) {
858 methods
= new XMLMethods ();
860 methods
.CompareTo (doc
, parent
, oclass
.methods
);
861 counters
.AddPartialToPartial (methods
.Counters
);
864 if (nested
!= null || oclass
.nested
!= null) {
865 XmlNode n
= doc
.CreateElement ("classes", null);
866 parent
.AppendChild (n
);
867 CompareTypes (n
, oclass
.nested
);
870 AddCountersAttributes (parent
);
873 void CompareTypes (XmlNode parent
, XMLClass
[] other
)
875 ArrayList newNodes
= new ArrayList ();
876 Hashtable oh
= CreateHash (other
);
878 int count
= (nested
== null) ? 0 : nested
.Length
;
879 for (int i
= 0; i
< count
; i
++) {
880 XMLClass xclass
= nested
[i
];
882 node
= document
.CreateElement ("class", null);
884 AddAttribute (node
, "name", xclass
.Name
);
885 AddAttribute (node
, "type", xclass
.Type
);
887 if (oh
.ContainsKey (xclass
.Name
)) {
888 int idx
= (int) oh
[xclass
.Name
];
889 xclass
.CompareTo (document
, node
, other
[idx
]);
891 counters
.AddPartialToPartial (xclass
.Counters
);
893 // TODO: Should I count here?
894 AddAttribute (node
, "presence", "missing");
896 counters
.MissingTotal
++;
901 count
= other
.Length
;
902 for (int i
= 0; i
< count
; i
++) {
903 XMLClass c
= other
[i
];
904 if (c
== null || IsMonoTODOAttribute (c
.Name
))
907 node
= document
.CreateElement ("class", null);
909 AddAttribute (node
, "name", c
.Name
);
910 AddAttribute (node
, "type", c
.Type
);
913 counters
.ExtraTotal
++;
917 XmlNode
[] nodes
= (XmlNode
[]) newNodes
.ToArray (typeof (XmlNode
));
918 Array
.Sort (nodes
, XmlNodeComparer
.Default
);
919 foreach (XmlNode nn
in nodes
)
920 parent
.AppendChild (nn
);
923 static Hashtable
CreateHash (XMLClass
[] other
)
925 Hashtable result
= new Hashtable ();
928 foreach (XMLClass c
in other
) {
929 result
[c
.Name
] = i
++;
945 class XMLParameter
: XMLData
954 XMLAttributes attributes
;
956 public override void LoadData (XmlNode node
)
959 throw new ArgumentNullException ("node");
961 if (node
.Name
!= "parameter")
962 throw new ArgumentException ("Expecting <parameter>");
964 name
= node
.Attributes
["name"].Value
;
965 type
= node
.Attributes
["type"].Value
;
966 attrib
= node
.Attributes
["attrib"].Value
;
967 if (node
.Attributes
["direction"] != null)
968 direction
= node
.Attributes
["direction"].Value
;
969 if (node
.Attributes
["unsafe"] != null)
970 isUnsafe
= bool.Parse (node
.Attributes
["unsafe"].Value
);
971 if (node
.Attributes
["optional"] != null)
972 isOptional
= bool.Parse (node
.Attributes
["optional"].Value
);
973 if (node
.Attributes
["defaultValue"] != null)
974 defaultValue
= node
.Attributes
["defaultValue"].Value
;
976 XmlNode child
= node
.FirstChild
;
980 if (child
.Name
== "attributes") {
981 attributes
= new XMLAttributes ();
982 attributes
.LoadData (child
);
983 child
= child
.NextSibling
;
987 public override void CompareTo (XmlDocument doc
, XmlNode parent
, object other
)
991 XMLParameter oparm
= (XMLParameter
) other
;
993 if (name
!= oparm
.name
)
994 AddWarning (parent
, "Parameter name is wrong: {0} != {1}", name
, oparm
.name
);
996 if (type
!= oparm
.type
)
997 AddWarning (parent
, "Parameter type is wrong: {0} != {1}", type
, oparm
.type
);
999 if (attrib
!= oparm
.attrib
)
1000 AddWarning (parent
, "Parameter attributes wrong: {0} != {1}", attrib
, oparm
.attrib
);
1002 if (direction
!= oparm
.direction
)
1003 AddWarning (parent
, "Parameter direction wrong: {0} != {1}", direction
, oparm
.direction
);
1005 if (isUnsafe
!= oparm
.isUnsafe
)
1006 AddWarning (parent
, "Parameter unsafe wrong: {0} != {1}", isUnsafe
, oparm
.isUnsafe
);
1008 if (isOptional
!= oparm
.isOptional
)
1009 AddWarning (parent
, "Parameter optional wrong: {0} != {1}", isOptional
, oparm
.isOptional
);
1011 if (defaultValue
!= oparm
.defaultValue
)
1012 AddWarning (parent
, "Parameter default value wrong: {0} != {1}", (defaultValue
== null) ? "(no default value)" : defaultValue
, (oparm
.defaultValue
== null) ? "(no default value)" : oparm
.defaultValue
);
1014 if (attributes
!= null || oparm
.attributes
!= null) {
1015 if (attributes
== null)
1016 attributes
= new XMLAttributes ();
1018 attributes
.CompareTo (doc
, parent
, oparm
.attributes
);
1019 counters
.AddPartialToPartial (attributes
.Counters
);
1020 if (oparm
.attributes
!= null && oparm
.attributes
.IsTodo
) {
1022 counters
.TodoTotal
++;
1023 counters
.ErrorTotal
++;
1024 AddAttribute (parent
, "error", "todo");
1025 if (oparm
.attributes
.Comment
!= null)
1026 AddAttribute (parent
, "comment", oparm
.attributes
.Comment
);
1031 public string Name
{
1032 get { return name; }
1036 class XMLAttributeProperties
: XMLNameGroup
1038 static Hashtable ignored_properties
;
1039 static XMLAttributeProperties ()
1041 ignored_properties
= new Hashtable ();
1042 ignored_properties
.Add ("System.Reflection.AssemblyKeyFileAttribute", "KeyFile");
1043 ignored_properties
.Add ("System.Reflection.AssemblyCompanyAttribute", "Company");
1044 ignored_properties
.Add ("System.Reflection.AssemblyConfigurationAttribute", "Configuration");
1045 ignored_properties
.Add ("System.Reflection.AssemblyCopyrightAttribute", "Copyright");
1046 ignored_properties
.Add ("System.Reflection.AssemblyProductAttribute", "Product");
1047 ignored_properties
.Add ("System.Reflection.AssemblyTrademarkAttribute", "Trademark");
1048 ignored_properties
.Add ("System.Reflection.AssemblyInformationalVersionAttribute", "InformationalVersion");
1050 ignored_properties
.Add ("System.ObsoleteAttribute", "Message");
1051 ignored_properties
.Add ("System.IO.IODescriptionAttribute", "Description");
1052 ignored_properties
.Add ("System.Diagnostics.MonitoringDescriptionAttribute", "Description");
1055 Hashtable properties
= new Hashtable ();
1058 public XMLAttributeProperties (string attribute
)
1060 this.attribute
= attribute
;
1063 public override void LoadData(XmlNode node
)
1066 throw new ArgumentNullException ("node");
1068 if (node
.ChildNodes
== null)
1071 string ignored
= ignored_properties
[attribute
] as string;
1073 foreach (XmlNode n
in node
.ChildNodes
) {
1074 string name
= n
.Attributes
["name"].Value
;
1075 if (ignored
== name
)
1078 if (n
.Attributes
["null"] != null) {
1079 properties
.Add (name
, null);
1082 string value = n
.Attributes
["value"].Value
;
1083 properties
.Add (name
, value);
1087 public override void CompareTo (XmlDocument doc
, XmlNode parent
, object other
)
1089 this.document
= doc
;
1091 Hashtable other_properties
= ((XMLAttributeProperties
)other
).properties
;
1092 foreach (DictionaryEntry de
in other_properties
) {
1093 object other_value
= properties
[de
.Key
];
1095 if (de
.Value
== null) {
1096 if (other_value
!= null)
1097 AddWarning (parent
, "Property '{0}' is 'null' and should be '{1}'", de
.Key
, other_value
);
1101 if (de
.Value
.Equals (other_value
))
1104 AddWarning (parent
, "Property '{0}' is '{1}' and should be '{2}'",
1105 de
.Key
, de
.Value
, other_value
== null ? "null" : other_value
);
1109 public override string GroupName
{
1111 return "properties";
1115 public override string Name
{
1122 class XMLAttributes
: XMLNameGroup
1124 Hashtable properties
= new Hashtable ();
1129 protected override bool CheckIfAdd (string value, XmlNode node
)
1131 if (IsMonoTODOAttribute (value)) {
1134 XmlNode pNode
= node
.SelectSingleNode ("properties");
1135 if (pNode
!= null && pNode
.ChildNodes
.Count
> 0 && pNode
.ChildNodes
[0].Attributes
["value"] != null) {
1136 comment
= pNode
.ChildNodes
[0].Attributes
["value"].Value
;
1141 return !IsMeaninglessAttribute (value);
1144 protected override void CompareToInner (string name
, XmlNode node
, XMLNameGroup other
)
1146 XMLAttributeProperties other_prop
= ((XMLAttributes
)other
).properties
[name
] as XMLAttributeProperties
;
1147 XMLAttributeProperties this_prop
= properties
[name
] as XMLAttributeProperties
;
1148 if (other_prop
== null || this_prop
== null)
1151 this_prop
.CompareTo (document
, node
, other_prop
);
1152 counters
.AddPartialToPartial (this_prop
.Counters
);
1155 public override string GetNodeKey (string name
, XmlNode node
)
1159 // if multiple attributes with the same name (type) exist, then we
1160 // cannot be sure which attributes correspond, so we must use the
1161 // name of the attribute (type) and the name/value of its properties
1164 XmlNodeList attributes
= node
.ParentNode
.SelectNodes("attribute[@name='" + name
+ "']");
1165 if (attributes
.Count
> 1) {
1166 ArrayList keyParts
= new ArrayList ();
1168 XmlNodeList properties
= node
.SelectNodes ("properties/property");
1169 foreach (XmlNode property
in properties
) {
1170 XmlAttributeCollection attrs
= property
.Attributes
;
1171 if (attrs
["value"] != null) {
1172 keyParts
.Add (attrs
["name"].Value
+ "=" + attrs
["value"].Value
);
1174 keyParts
.Add (attrs
["name"].Value
+ "=");
1178 // sort properties by name, as order of properties in XML is
1182 // insert name (type) of attribute
1183 keyParts
.Insert (0, name
);
1185 StringBuilder sb
= new StringBuilder ();
1186 foreach (string value in keyParts
) {
1190 key
= sb
.ToString ();
1198 protected override void LoadExtraData(string name
, XmlNode node
)
1200 XmlNode pNode
= node
.SelectSingleNode ("properties");
1202 if (IsMonoTODOAttribute (name
)) {
1204 if (pNode
.ChildNodes
[0].Attributes
["value"] != null) {
1205 comment
= pNode
.ChildNodes
[0].Attributes
["value"].Value
;
1210 if (pNode
!= null) {
1211 XMLAttributeProperties p
= new XMLAttributeProperties (name
);
1214 properties
[name
] = p
;
1218 public override string GroupName
{
1219 get { return "attributes"; }
1222 public override string Name
{
1223 get { return "attribute"; }
1226 public bool IsTodo
{
1227 get { return isTodo; }
1230 public string Comment
{
1231 get { return comment; }
1235 class XMLInterfaces
: XMLNameGroup
1237 public override string GroupName
{
1238 get { return "interfaces"; }
1241 public override string Name
{
1242 get { return "interface"; }
1246 abstract class XMLGenericGroup
: XMLNameGroup
1250 protected override void LoadExtraData (string name
, XmlNode node
)
1252 attributes
= ((XmlElement
) node
).GetAttribute ("generic-attribute");
1255 protected override void CompareToInner (string name
, XmlNode parent
, XMLNameGroup other
)
1257 base.CompareToInner (name
, parent
, other
);
1259 XMLGenericGroup g
= (XMLGenericGroup
) other
;
1260 if (attributes
!= g
.attributes
)
1261 AddWarning (parent
, "Incorrect generic attributes: '{0}' != '{1}'", attributes
, g
.attributes
);
1265 class XMLGenericTypeConstraints
: XMLGenericGroup
1267 public override string GroupName
{
1268 get { return "generic-type-constraints"; }
1271 public override string Name
{
1272 get { return "generic-type-constraint"; }
1276 class XMLGenericMethodConstraints
: XMLGenericGroup
1278 public override string GroupName
{
1279 get { return "generic-method-constraints"; }
1282 public override string Name
{
1283 get { return "generic-method-constraint"; }
1287 abstract class XMLMember
: XMLNameGroup
1289 Hashtable attributeMap
;
1290 Hashtable access
= new Hashtable ();
1292 protected override void LoadExtraData (string name
, XmlNode node
)
1294 XmlAttribute xatt
= node
.Attributes
["attrib"];
1296 access
[name
] = xatt
.Value
;
1298 XmlNode orig
= node
;
1300 node
= node
.FirstChild
;
1301 while (node
!= null) {
1302 if (node
!= null && node
.Name
== "attributes") {
1303 XMLAttributes a
= new XMLAttributes ();
1305 if (attributeMap
== null)
1306 attributeMap
= new Hashtable ();
1308 attributeMap
[name
] = a
;
1311 node
= node
.NextSibling
;
1314 base.LoadExtraData (name
, orig
);
1317 protected override void CompareToInner (string name
, XmlNode parent
, XMLNameGroup other
)
1319 base.CompareToInner (name
, parent
, other
);
1320 XMLMember mb
= other
as XMLMember
;
1321 XMLAttributes att
= null;
1322 XMLAttributes oatt
= null;
1323 if (attributeMap
!= null)
1324 att
= attributeMap
[name
] as XMLAttributes
;
1326 if (mb
!= null && mb
.attributeMap
!= null)
1327 oatt
= mb
.attributeMap
[name
] as XMLAttributes
;
1329 if (att
!= null || oatt
!= null) {
1331 att
= new XMLAttributes ();
1333 att
.CompareTo (document
, parent
, oatt
);
1334 counters
.AddPartialToPartial(att
.Counters
);
1335 if (oatt
!= null && oatt
.IsTodo
) {
1337 counters
.ErrorTotal
++;
1338 AddAttribute (parent
, "error", "todo");
1339 if (oatt
.Comment
!= null)
1340 AddAttribute (parent
, "comment", oatt
.Comment
);
1344 XMLMember member
= (XMLMember
) other
;
1345 string acc
= access
[name
] as string;
1350 if (member
.access
!= null)
1351 oacc
= member
.access
[name
] as string;
1353 string accName
= ConvertToString (Int32
.Parse (acc
));
1354 string oaccName
= "";
1356 oaccName
= ConvertToString (Int32
.Parse (oacc
));
1358 if (accName
!= oaccName
)
1359 AddWarning (parent
, "Incorrect attributes: '{0}' != '{1}'", accName
, oaccName
);
1362 protected virtual string ConvertToString (int att
)
1368 class XMLFields
: XMLMember
1370 Hashtable fieldTypes
;
1371 Hashtable fieldValues
;
1373 protected override void LoadExtraData (string name
, XmlNode node
)
1375 XmlAttribute xatt
= node
.Attributes
["fieldtype"];
1377 if (fieldTypes
== null)
1378 fieldTypes
= new Hashtable ();
1380 fieldTypes
[name
] = xatt
.Value
;
1383 xatt
= node
.Attributes
["value"];
1385 if (fieldValues
== null)
1386 fieldValues
= new Hashtable ();
1388 fieldValues
[name
] = xatt
.Value
;
1391 base.LoadExtraData (name
, node
);
1394 protected override void CompareToInner (string name
, XmlNode parent
, XMLNameGroup other
)
1396 base.CompareToInner (name
, parent
, other
);
1397 XMLFields fields
= (XMLFields
) other
;
1398 if (fieldTypes
!= null) {
1399 string ftype
= fieldTypes
[name
] as string;
1400 string oftype
= null;
1401 if (fields
.fieldTypes
!= null)
1402 oftype
= fields
.fieldTypes
[name
] as string;
1404 if (ftype
!= oftype
)
1405 AddWarning (parent
, "Field type is {0} and should be {1}", oftype
, ftype
);
1407 if (fieldValues
!= null) {
1408 string fvalue
= fieldValues
[name
] as string;
1409 string ofvalue
= null;
1410 if (fields
.fieldValues
!= null)
1411 ofvalue
= fields
.fieldValues
[name
] as string;
1413 if (fvalue
!= ofvalue
)
1414 AddWarning (parent
, "Field value is {0} and should be {1}", ofvalue
, fvalue
);
1418 protected override string ConvertToString (int att
)
1420 FieldAttributes fa
= (FieldAttributes
) att
;
1421 return fa
.ToString ();
1424 public override string GroupName
{
1425 get { return "fields"; }
1428 public override string Name
{
1429 get { return "field"; }
1433 class XMLParameters
: XMLNameGroup
1435 public override void LoadData (XmlNode node
)
1438 throw new ArgumentNullException ("node");
1440 if (node
.Name
!= GroupName
)
1441 throw new FormatException (String
.Format ("Expecting <{0}>", GroupName
));
1443 keys
= new Hashtable ();
1444 foreach (XmlNode n
in node
.ChildNodes
) {
1445 string name
= n
.Attributes
["name"].Value
;
1446 string key
= GetNodeKey (name
, n
);
1447 XMLParameter parm
= new XMLParameter ();
1449 keys
.Add (key
, parm
);
1450 LoadExtraData (key
, n
);
1454 public override string GroupName
{
1456 return "parameters";
1460 public override string Name
{
1466 public override string GetNodeKey (string name
, XmlNode node
)
1468 return node
.Attributes
["position"].Value
;
1471 public override void CompareTo (XmlDocument doc
, XmlNode parent
, object other
)
1473 this.document
= doc
;
1475 group = doc
.CreateElement (GroupName
, null);
1477 Hashtable okeys
= null;
1478 if (other
!= null && ((XMLParameters
) other
).keys
!= null) {
1479 okeys
= ((XMLParameters
) other
).keys
;
1482 XmlNode node
= null;
1483 bool onull
= (okeys
== null);
1485 foreach (DictionaryEntry entry
in keys
) {
1486 node
= doc
.CreateElement (Name
, null);
1487 group.AppendChild (node
);
1488 string key
= (string) entry
.Key
;
1489 XMLParameter parm
= (XMLParameter
) entry
.Value
;
1490 AddAttribute (node
, "name", parm
.Name
);
1492 if (!onull
&& HasKey (key
, okeys
)) {
1493 parm
.CompareTo (document
, node
, okeys
[key
]);
1494 counters
.AddPartialToPartial (parm
.Counters
);
1498 AddAttribute (node
, "presence", "missing");
1504 if (!onull
&& okeys
.Count
!= 0) {
1505 foreach (XMLParameter
value in okeys
.Values
) {
1506 node
= doc
.CreateElement (Name
, null);
1507 AddAttribute (node
, "name", value.Name
);
1508 AddAttribute (node
, "presence", "extra");
1509 group.AppendChild (node
);
1514 if (group.HasChildNodes
)
1515 parent
.AppendChild (group);
1519 class XMLProperties
: XMLMember
1521 Hashtable nameToMethod
= new Hashtable ();
1523 protected override void CompareToInner (string name
, XmlNode parent
, XMLNameGroup other
)
1525 Counters copy
= counters
;
1526 counters
= new Counters();
1528 XMLProperties oprop
= other
as XMLProperties
;
1529 if (oprop
!= null) {
1530 XMLMethods m
= nameToMethod
[name
] as XMLMethods
;
1531 XMLMethods om
= oprop
.nameToMethod
[name
] as XMLMethods
;
1532 if (m
!= null || om
!= null) {
1534 m
= new XMLMethods ();
1536 m
.CompareTo(document
, parent
, om
);
1537 counters
.AddPartialToPartial(m
.Counters
);
1541 base.CompareToInner (name
, parent
, other
);
1542 AddCountersAttributes(parent
);
1544 copy
.AddPartialToPartial(counters
);
1548 protected override void LoadExtraData (string name
, XmlNode node
)
1550 XmlNode orig
= node
;
1551 node
= node
.FirstChild
;
1552 while (node
!= null) {
1553 if (node
!= null && node
.Name
== "methods") {
1554 XMLMethods m
= new XMLMethods ();
1555 XmlNode parent
= node
.ParentNode
;
1556 string key
= GetNodeKey (name
, parent
);
1558 nameToMethod
[key
] = m
;
1561 node
= node
.NextSibling
;
1564 base.LoadExtraData (name
, orig
);
1567 public override string GetNodeKey (string name
, XmlNode node
)
1569 XmlAttributeCollection atts
= node
.Attributes
;
1570 return String
.Format ("{0}:{1}:{2}",
1571 (atts
["name"] != null ? atts
["name"].Value
: ""),
1572 (atts
["ptype"] != null ? atts
["ptype"].Value
: ""),
1573 (atts
["params"] != null ? atts
["params"].Value
: "")
1577 public override string GroupName
{
1578 get { return "properties"; }
1581 public override string Name
{
1582 get { return "property"; }
1586 class XMLEvents
: XMLMember
1588 Hashtable eventTypes
;
1589 Hashtable nameToMethod
= new Hashtable ();
1591 protected override void LoadExtraData (string name
, XmlNode node
)
1593 XmlAttribute xatt
= node
.Attributes
["eventtype"];
1595 if (eventTypes
== null)
1596 eventTypes
= new Hashtable ();
1598 eventTypes
[name
] = xatt
.Value
;
1601 XmlNode child
= node
.FirstChild
;
1602 while (child
!= null) {
1603 if (child
!= null && child
.Name
== "methods") {
1604 XMLMethods m
= new XMLMethods ();
1605 XmlNode parent
= child
.ParentNode
;
1606 string key
= GetNodeKey (name
, parent
);
1608 nameToMethod
[key
] = m
;
1611 child
= child
.NextSibling
;
1614 base.LoadExtraData (name
, node
);
1617 protected override void CompareToInner (string name
, XmlNode parent
, XMLNameGroup other
)
1619 Counters copy
= counters
;
1620 counters
= new Counters ();
1623 base.CompareToInner (name
, parent
, other
);
1624 AddCountersAttributes (parent
);
1625 if (eventTypes
== null)
1628 XMLEvents evt
= (XMLEvents
) other
;
1629 string etype
= eventTypes
[name
] as string;
1630 string oetype
= null;
1631 if (evt
.eventTypes
!= null)
1632 oetype
= evt
.eventTypes
[name
] as string;
1634 if (etype
!= oetype
)
1635 AddWarning (parent
, "Event type is {0} and should be {1}", oetype
, etype
);
1637 XMLMethods m
= nameToMethod
[name
] as XMLMethods
;
1638 XMLMethods om
= evt
.nameToMethod
[name
] as XMLMethods
;
1639 if (m
!= null || om
!= null) {
1641 m
= new XMLMethods ();
1643 m
.CompareTo (document
, parent
, om
);
1644 counters
.AddPartialToPartial (m
.Counters
);
1647 AddCountersAttributes (parent
);
1648 copy
.AddPartialToPartial (counters
);
1653 protected override string ConvertToString (int att
)
1655 EventAttributes ea
= (EventAttributes
) att
;
1656 return ea
.ToString ();
1659 public override string GroupName
{
1660 get { return "events"; }
1663 public override string Name
{
1664 get { return "event"; }
1668 class XMLMethods
: XMLMember
1670 Hashtable returnTypes
;
1671 Hashtable parameters
;
1672 Hashtable genericConstraints
;
1673 Hashtable signatureFlags
;
1685 protected override void LoadExtraData (string name
, XmlNode node
)
1687 XmlAttribute xatt
= node
.Attributes
["returntype"];
1689 if (returnTypes
== null)
1690 returnTypes
= new Hashtable ();
1692 returnTypes
[name
] = xatt
.Value
;
1695 SignatureFlags flags
= SignatureFlags
.None
;
1696 if (((XmlElement
) node
).GetAttribute ("abstract") == "true")
1697 flags
|= SignatureFlags
.Abstract
;
1698 if (((XmlElement
) node
).GetAttribute ("static") == "true")
1699 flags
|= SignatureFlags
.Static
;
1700 if (((XmlElement
) node
).GetAttribute ("virtual") == "true")
1701 flags
|= SignatureFlags
.Virtual
;
1702 if (((XmlElement
) node
).GetAttribute ("final") == "true")
1703 flags
|= SignatureFlags
.Final
;
1704 if (flags
!= SignatureFlags
.None
) {
1705 if (signatureFlags
== null)
1706 signatureFlags
= new Hashtable ();
1707 signatureFlags
[name
] = flags
;
1710 XmlNode parametersNode
= node
.SelectSingleNode ("parameters");
1711 if (parametersNode
!= null) {
1712 if (parameters
== null)
1713 parameters
= new Hashtable ();
1715 XMLParameters parms
= new XMLParameters ();
1716 parms
.LoadData (parametersNode
);
1718 parameters
[name
] = parms
;
1721 XmlNode genericNode
= node
.SelectSingleNode ("generic-method-constraints");
1722 if (genericNode
!= null) {
1723 if (genericConstraints
== null)
1724 genericConstraints
= new Hashtable ();
1725 XMLGenericMethodConstraints csts
= new XMLGenericMethodConstraints ();
1726 csts
.LoadData (genericNode
);
1727 genericConstraints
[name
] = csts
;
1730 base.LoadExtraData (name
, node
);
1733 public override string GetNodeKey (string name
, XmlNode node
)
1735 // for explicit/implicit operators we need to include the return
1736 // type in the key to allow matching; as a side-effect, differences
1737 // in return types will be reported as extra/missing methods
1739 // for regular methods we do not need to take into account the
1740 // return type for matching methods; differences in return types
1741 // will be reported as a warning on the method
1742 if (name
.StartsWith ("op_")) {
1743 XmlAttribute xatt
= node
.Attributes
["returntype"];
1744 string returnType
= xatt
!= null ? xatt
.Value
+ " " : string.Empty
;
1745 return returnType
+ name
;
1750 protected override void CompareToInner (string name
, XmlNode parent
, XMLNameGroup other
)
1752 // create backup of actual counters
1753 Counters copy
= counters
;
1754 // initialize counters for current method
1755 counters
= new Counters();
1758 base.CompareToInner(name
, parent
, other
);
1759 XMLMethods methods
= (XMLMethods
) other
;
1761 SignatureFlags flags
= signatureFlags
!= null &&
1762 signatureFlags
.ContainsKey (name
) ?
1763 (SignatureFlags
) signatureFlags
[name
] :
1764 SignatureFlags
.None
;
1765 SignatureFlags oflags
= methods
.signatureFlags
!= null &&
1766 methods
.signatureFlags
.ContainsKey (name
) ?
1767 (SignatureFlags
) methods
.signatureFlags
[name
] :
1768 SignatureFlags
.None
;
1770 if (flags
!= oflags
) {
1771 if (flags
== SignatureFlags
.None
)
1772 AddWarning (parent
, String
.Format ("should not be {0}", oflags
));
1773 else if (oflags
== SignatureFlags
.None
)
1774 AddWarning (parent
, String
.Format ("should be {0}", flags
));
1776 AddWarning (parent
, String
.Format ("{0} and should be {1}", oflags
, flags
));
1779 if (returnTypes
!= null) {
1780 string rtype
= returnTypes
[name
] as string;
1781 string ortype
= null;
1782 if (methods
.returnTypes
!= null)
1783 ortype
= methods
.returnTypes
[name
] as string;
1785 if (rtype
!= ortype
)
1786 AddWarning (parent
, "Return type is {0} and should be {1}", ortype
, rtype
);
1789 if (parameters
!= null) {
1790 XMLParameters parms
= parameters
[name
] as XMLParameters
;
1791 parms
.CompareTo (document
, parent
, methods
.parameters
[name
]);
1792 counters
.AddPartialToPartial (parms
.Counters
);
1795 // output counter attributes in result document
1796 AddCountersAttributes(parent
);
1798 // add temporary counters to actual counters
1799 copy
.AddPartialToPartial(counters
);
1800 // restore backup of actual counters
1805 protected override string ConvertToString (int att
)
1807 MethodAttributes ma
= (MethodAttributes
) att
;
1808 // ignore ReservedMasks
1809 ma
&= ~ MethodAttributes
.ReservedMask
;
1810 ma
&= ~ MethodAttributes
.VtableLayoutMask
;
1811 if ((ma
& MethodAttributes
.FamORAssem
) != 0)
1812 ma
= (ma
& ~ MethodAttributes
.FamORAssem
) | MethodAttributes
.Family
;
1814 // ignore the HasSecurity attribute for now
1815 if ((ma
& MethodAttributes
.HasSecurity
) != 0)
1816 ma
= (MethodAttributes
) (att
- (int) MethodAttributes
.HasSecurity
);
1818 // ignore the RequireSecObject attribute for now
1819 if ((ma
& MethodAttributes
.RequireSecObject
) != 0)
1820 ma
= (MethodAttributes
) (att
- (int) MethodAttributes
.RequireSecObject
);
1822 // we don't care if the implementation is forwarded through PInvoke
1823 if ((ma
& MethodAttributes
.PinvokeImpl
) != 0)
1824 ma
= (MethodAttributes
) (att
- (int) MethodAttributes
.PinvokeImpl
);
1826 return ma
.ToString ();
1829 public override string GroupName
{
1830 get { return "methods"; }
1833 public override string Name
{
1834 get { return "method"; }
1838 class XMLConstructors
: XMLMethods
1840 public override string GroupName
{
1841 get { return "constructors"; }
1844 public override string Name
{
1845 get { return "constructor"; }
1849 class XmlNodeComparer
: IComparer
1851 public static XmlNodeComparer Default
= new XmlNodeComparer ();
1853 public int Compare (object a
, object b
)
1855 XmlNode na
= (XmlNode
) a
;
1856 XmlNode nb
= (XmlNode
) b
;
1857 return String
.Compare (na
.Attributes
["name"].Value
, nb
.Attributes
["name"].Value
);