[mono-api-html] Output nested type correctly (was missing the declaring type name)
[mono-project.git] / mcs / tools / corcompare / mono-api-html / ClassComparer.cs
blobbdf22fea4895b2917e0884e0d7d62a11457739f2
1 //
2 // Authors
3 // Sebastien Pouliot <sebastien@xamarin.com>
4 //
5 // Copyright 2013 Xamarin Inc. http://www.xamarin.com
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining
8 // a copy of this software and associated documentation files (the
9 // "Software"), to deal in the Software without restriction, including
10 // without limitation the rights to use, copy, modify, merge, publish,
11 // distribute, sublicense, and/or sell copies of the Software, and to
12 // permit persons to whom the Software is furnished to do so, subject to
13 // the following conditions:
15 // The above copyright notice and this permission notice shall be
16 // included in all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 using System;
28 using System.Collections.Generic;
29 using System.IO;
30 using System.Xml.Linq;
32 namespace Xamarin.ApiDiff {
34 public class ClassComparer : Comparer {
36 InterfaceComparer icomparer;
37 ConstructorComparer ccomparer;
38 FieldComparer fcomparer;
39 PropertyComparer pcomparer;
40 EventComparer ecomparer;
41 MethodComparer mcomparer;
42 ClassComparer kcomparer;
44 public ClassComparer ()
46 icomparer = new InterfaceComparer ();
47 ccomparer = new ConstructorComparer ();
48 fcomparer = new FieldComparer ();
49 pcomparer = new PropertyComparer ();
50 ecomparer = new EventComparer ();
51 mcomparer = new MethodComparer ();
54 public override void SetContext (XElement current)
56 State.Type = current.GetAttribute ("name");
57 State.BaseType = current.GetAttribute ("base");
60 public void Compare (XElement source, XElement target)
62 var s = source.Element ("classes");
63 var t = target.Element ("classes");
64 if (XNode.DeepEquals (s, t))
65 return;
66 Compare (s.Elements ("class"), t.Elements ("class"));
69 public override void Added (XElement target)
71 Output.WriteLine ("<h3>New Type {0}.{1}</h3>", State.Namespace, target.Attribute ("name").Value);
72 Output.WriteLine ("<pre>");
73 State.Indent = 0;
74 AddedInner (target);
75 Output.WriteLine ("</pre>");
78 public void AddedInner (XElement target)
80 SetContext (target);
81 if (target.IsTrue ("serializable"))
82 Indent ().WriteLine ("[Serializable]");
84 var type = target.Attribute ("type").Value;
86 if (type == "enum") {
87 // check if [Flags] is present
88 var cattrs = target.Element ("attributes");
89 if (cattrs != null) {
90 foreach (var ca in cattrs.Elements ("attribute")) {
91 if (ca.GetAttribute ("name") == "System.FlagsAttribute") {
92 Indent ().WriteLine ("[Flags]");
93 break;
99 Indent ().Write ("public");
101 if (type != "enum") {
102 bool seal = target.IsTrue ("sealed");
103 bool abst = target.IsTrue ("abstract");
104 if (seal && abst)
105 Output.Write (" static");
106 else if (seal && type != "struct")
107 Output.Write (" sealed");
108 else if (abst && type != "interface")
109 Output.Write (" abstract");
112 Output.Write (' ');
113 Output.Write (type);
114 Output.Write (' ');
115 Output.Write (target.GetAttribute ("name"));
117 var baseclass = target.GetAttribute ("base");
118 if ((type != "enum") && (type != "struct")) {
119 if (baseclass != null) {
120 if (baseclass == "System.Object") {
121 // while true we do not need to be reminded every time...
122 baseclass = null;
123 } else {
124 Output.Write (" : ");
125 Output.Write (baseclass);
130 // interfaces on enums are "standard" not user provided - so we do not want to show them
131 if (type != "enum") {
132 var i = target.Element ("interfaces");
133 if (i != null) {
134 var interfaces = new List<string> ();
135 foreach (var iface in i.Elements ("interface"))
136 interfaces.Add (icomparer.GetDescription (iface));
137 Output.Write ((baseclass == null) ? " : " : ", ");
138 Output.Write (String.Join (", ", interfaces));
142 Output.WriteLine (" {");
144 var t = target.Element ("constructors");
145 if (t != null) {
146 Indent ().WriteLine ("\t// constructors");
147 foreach (var ctor in t.Elements ("constructor"))
148 ccomparer.Added (ctor);
151 t = target.Element ("fields");
152 if (t != null) {
153 if (type != "enum")
154 Indent ().WriteLine ("\t// fields");
155 else
156 SetContext (target);
157 foreach (var field in t.Elements ("field"))
158 fcomparer.Added (field);
161 t = target.Element ("properties");
162 if (t != null) {
163 Indent ().WriteLine ("\t// properties");
164 foreach (var property in t.Elements ("property"))
165 pcomparer.Added (property);
168 t = target.Element ("events");
169 if (t != null) {
170 Indent ().WriteLine ("\t// events");
171 foreach (var evnt in t.Elements ("event"))
172 ecomparer.Added (evnt);
175 t = target.Element ("methods");
176 if (t != null) {
177 Indent ().WriteLine ("\t// methods");
178 foreach (var method in t.Elements ("method"))
179 mcomparer.Added (method);
182 t = target.Element ("classes");
183 if (t != null) {
184 Output.WriteLine ();
185 Indent ().WriteLine ("\t// inner types");
186 kcomparer = new NestedClassComparer ();
187 State.Indent++;
188 foreach (var inner in t.Elements ("class"))
189 kcomparer.AddedInner (inner);
190 State.Indent--;
192 Indent ().WriteLine ("}");
195 public override void Modified (XElement source, XElement target)
197 // hack - there could be changes that we're not monitoring (e.g. attributes properties)
198 var output = Output;
199 State.Output = new StringWriter ();
201 ccomparer.Compare (source, target);
202 icomparer.Compare (source, target);
203 fcomparer.Compare (source, target);
204 pcomparer.Compare (source, target);
205 ecomparer.Compare (source, target);
206 mcomparer.Compare (source, target);
208 var si = source.Element ("classes");
209 if (si != null) {
210 var ti = target.Element ("classes");
211 kcomparer = new NestedClassComparer ();
212 kcomparer.Compare (si.Elements ("class"), ti == null ? null : ti.Elements ("class"));
215 var s = (Output as StringWriter).ToString ();
216 State.Output = output;
217 if (s.Length > 0) {
218 Output.WriteLine ("<h3>Type Changed: {0}.{1}</h3>", State.Namespace, GetTypeName (target));
219 Output.WriteLine (s);
223 public override void Removed (XElement source)
225 Output.WriteLine ("<h3>Removed Type {0}.{1}", State.Namespace, GetTypeName (source));
228 public virtual string GetTypeName (XElement type)
230 return type.GetAttribute ("name");
234 public class NestedClassComparer : ClassComparer {
236 public override void SetContext (XElement current)
240 public override string GetTypeName (XElement type)
242 return State.Type + "." + base.GetTypeName (type);