3 // Sebastien Pouliot <sebastien@xamarin.com>
5 // Copyright 2013 Xamarin Inc. http://www.xamarin.com
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.
28 using System
.Collections
.Generic
;
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
))
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>");
75 Output
.WriteLine ("</pre>");
78 public void AddedInner (XElement target
)
81 if (target
.IsTrue ("serializable"))
82 Indent ().WriteLine ("[Serializable]");
84 var type
= target
.Attribute ("type").Value
;
87 // check if [Flags] is present
88 var cattrs
= target
.Element ("attributes");
90 foreach (var ca
in cattrs
.Elements ("attribute")) {
91 if (ca
.GetAttribute ("name") == "System.FlagsAttribute") {
92 Indent ().WriteLine ("[Flags]");
99 Indent ().Write ("public");
101 if (type
!= "enum") {
102 bool seal
= target
.IsTrue ("sealed");
103 bool abst
= target
.IsTrue ("abstract");
105 Output
.Write (" static");
106 else if (seal
&& type
!= "struct")
107 Output
.Write (" sealed");
108 else if (abst
&& type
!= "interface")
109 Output
.Write (" abstract");
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...
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");
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");
146 Indent ().WriteLine ("\t// constructors");
147 foreach (var ctor
in t
.Elements ("constructor"))
148 ccomparer
.Added (ctor
);
151 t
= target
.Element ("fields");
154 Indent ().WriteLine ("\t// fields");
157 foreach (var field
in t
.Elements ("field"))
158 fcomparer
.Added (field
);
161 t
= target
.Element ("properties");
163 Indent ().WriteLine ("\t// properties");
164 foreach (var property
in t
.Elements ("property"))
165 pcomparer
.Added (property
);
168 t
= target
.Element ("events");
170 Indent ().WriteLine ("\t// events");
171 foreach (var evnt
in t
.Elements ("event"))
172 ecomparer
.Added (evnt
);
175 t
= target
.Element ("methods");
177 Indent ().WriteLine ("\t// methods");
178 foreach (var method
in t
.Elements ("method"))
179 mcomparer
.Added (method
);
182 t
= target
.Element ("classes");
185 Indent ().WriteLine ("\t// inner types");
186 kcomparer
= new NestedClassComparer ();
188 foreach (var inner
in t
.Elements ("class"))
189 kcomparer
.AddedInner (inner
);
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)
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");
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
;
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
);