Merge pull request #1624 from esdrubal/getprocesstimes
[mono.git] / mcs / tools / corcompare / mono-api-html / ClassComparer.cs
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:
14 //
15 // The above copyright notice and this permission notice shall be
16 // included in all copies or substantial portions of the Software.
17 //
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.
25 //
26
27 using System;
28 using System.Collections.Generic;
29 using System.IO;
30 using System.Linq;
31 using System.Xml.Linq;
32
33 namespace Xamarin.ApiDiff {
34
35         public class ClassComparer : Comparer {
36
37                 InterfaceComparer icomparer;
38                 ConstructorComparer ccomparer;
39                 FieldComparer fcomparer;
40                 PropertyComparer pcomparer;
41                 EventComparer ecomparer;
42                 MethodComparer mcomparer;
43                 ClassComparer kcomparer;
44
45                 public ClassComparer ()
46                 {
47                         icomparer = new InterfaceComparer ();
48                         ccomparer = new ConstructorComparer ();
49                         fcomparer = new FieldComparer ();
50                         pcomparer = new PropertyComparer ();
51                         ecomparer = new EventComparer ();
52                         mcomparer = new MethodComparer ();
53                 }
54
55                 public override void SetContext (XElement current)
56                 {
57                         State.Type = current.GetAttribute ("name");
58                         State.BaseType = current.GetAttribute ("base");
59                 }
60
61                 public void Compare (XElement source, XElement target)
62                 {
63                         var s = source.Element ("classes");
64                         var t = target.Element ("classes");
65                         if (XNode.DeepEquals (s, t))
66                                 return;
67                         Compare (s.Elements ("class"), t.Elements ("class"));
68                 }
69
70                 public override void Added (XElement target)
71                 {
72                         string name = target.Attribute ("name").Value;
73                         if (State.IgnoreNew.Any (re => re.IsMatch (name)))
74                                 return;
75                         Output.WriteLine ("<h3>New Type {0}.{1}</h3>", State.Namespace, name);
76                         Output.WriteLine ("<pre>");
77                         if (State.Colorize)
78                                 Output.WriteLine ("<font color='green'>");
79                         State.Indent = 0;
80                         AddedInner (target);
81                         if (State.Colorize)
82                                 Output.WriteLine ("</font>");
83                         Output.WriteLine ("</pre>");
84                 }
85
86                 public void AddedInner (XElement target)
87                 {
88                         SetContext (target);
89                         if (target.IsTrue ("serializable"))
90                                 Indent ().WriteLine ("[Serializable]");
91
92                         var type = target.Attribute ("type").Value;
93
94                         if (type == "enum") {
95                                 // check if [Flags] is present
96                                 var cattrs = target.Element ("attributes");
97                                 if (cattrs != null) {
98                                         foreach (var ca in cattrs.Elements ("attribute")) {
99                                                 if (ca.GetAttribute ("name") == "System.FlagsAttribute") {
100                                                         Indent ().WriteLine ("[Flags]");
101                                                         break;
102                                                 }
103                                         }
104                                 }
105                         }
106
107                         Indent ().Write ("public");
108
109                         if (type != "enum") {
110                                 bool seal = target.IsTrue ("sealed");
111                                 bool abst = target.IsTrue ("abstract");
112                                 if (seal && abst)
113                                         Output.Write (" static");
114                                 else if (seal && type != "struct")
115                                         Output.Write (" sealed");
116                                 else if (abst && type != "interface")
117                                         Output.Write (" abstract");
118                         }
119
120                         Output.Write (' ');
121                         Output.Write (type);
122                         Output.Write (' ');
123                         Output.Write (target.GetAttribute ("name"));
124
125                         var baseclass = target.GetAttribute ("base");
126                         if ((type != "enum") && (type != "struct")) {
127                                 if (baseclass != null) {
128                                         if (baseclass == "System.Object") {
129                                                 // while true we do not need to be reminded every time...
130                                                 baseclass = null;
131                                         } else {
132                                                 Output.Write (" : ");
133                                                 Output.Write (baseclass);
134                                         }
135                                 }
136                         }
137
138                         // interfaces on enums are "standard" not user provided - so we do not want to show them
139                         if (type != "enum") {
140                                 var i = target.Element ("interfaces");
141                                 if (i != null) {
142                                         var interfaces = new List<string> ();
143                                         foreach (var iface in i.Elements ("interface"))
144                                                 interfaces.Add (icomparer.GetDescription (iface));
145                                         Output.Write ((baseclass == null) ? " : " : ", ");
146                                         Output.Write (String.Join (", ", interfaces));
147                                 }
148                         }
149
150                         Output.WriteLine (" {");
151
152                         var t = target.Element ("constructors");
153                         if (t != null) {
154                                 Indent ().WriteLine ("\t// constructors");
155                                 foreach (var ctor in t.Elements ("constructor"))
156                                         ccomparer.Added (ctor);
157                         }
158
159                         t = target.Element ("fields");
160                         if (t != null) {
161                                 if (type != "enum")
162                                         Indent ().WriteLine ("\t// fields");
163                                 else
164                                         SetContext (target);
165                                 foreach (var field in t.Elements ("field"))
166                                         fcomparer.Added (field);
167                         }
168
169                         t = target.Element ("properties");
170                         if (t != null) {
171                                 Indent ().WriteLine ("\t// properties");
172                                 foreach (var property in t.Elements ("property"))
173                                         pcomparer.Added (property);
174                         }
175
176                         t = target.Element ("events");
177                         if (t != null) {
178                                 Indent ().WriteLine ("\t// events");
179                                 foreach (var evnt in t.Elements ("event"))
180                                         ecomparer.Added (evnt);
181                         }
182
183                         t = target.Element ("methods");
184                         if (t != null) {
185                                 Indent ().WriteLine ("\t// methods");
186                                 foreach (var method in t.Elements ("method"))
187                                         mcomparer.Added (method);
188                         }
189
190                         t = target.Element ("classes");
191                         if (t != null) {
192                                 Output.WriteLine ();
193                                 Indent ().WriteLine ("\t// inner types");
194                                 kcomparer = new NestedClassComparer ();
195                                 State.Indent++;
196                                 foreach (var inner in t.Elements ("class"))
197                                         kcomparer.AddedInner (inner);
198                                 State.Indent--;
199                         }
200                         Indent ().WriteLine ("}");
201                 }
202
203                 public override void Modified (XElement source, XElement target, ApiChanges diff)
204                 {
205                         // hack - there could be changes that we're not monitoring (e.g. attributes properties)
206                         var output = Output;
207                         State.Output = new StringWriter ();
208
209                         var sb = source.GetAttribute ("base");
210                         var tb = target.GetAttribute ("base");
211                         if (sb != tb) {
212                                 Output.Write ("Modified base type: ");
213                                 Output.WriteLine (new ApiChange ().AppendModified (sb, tb, true).Member.ToString ());
214                         }
215
216                         ccomparer.Compare (source, target);
217                         icomparer.Compare (source, target);
218                         fcomparer.Compare (source, target);
219                         pcomparer.Compare (source, target);
220                         ecomparer.Compare (source, target);
221                         mcomparer.Compare (source, target);
222
223                         var si = source.Element ("classes");
224                         if (si != null) {
225                                 var ti = target.Element ("classes");
226                                 kcomparer = new NestedClassComparer ();
227                                 kcomparer.Compare (si.Elements ("class"), ti == null ? null : ti.Elements ("class"));
228                         }
229
230                         var s = (Output as StringWriter).ToString ();
231                         State.Output = output;
232                         if (s.Length > 0) {
233                                 Output.WriteLine ("<h3>Type Changed: {0}.{1}</h3>", State.Namespace, GetTypeName (target));
234                                 Output.WriteLine (s);
235                         }
236                 }
237
238                 public override void Removed (XElement source)
239                 {
240                         Output.WriteLine ("<h3>Removed Type {0}.{1}", State.Namespace, GetTypeName (source));
241                 }
242
243                 public virtual string GetTypeName (XElement type)
244                 {
245                         return type.GetAttribute ("name");
246                 }
247         }
248
249         public class NestedClassComparer : ClassComparer {
250
251                 public override void SetContext (XElement current)
252                 {
253                 }
254
255                 public override string GetTypeName (XElement type)
256                 {
257                         return State.Type + "." + base.GetTypeName (type);
258                 }
259         }
260 }