c8a6e0a777262a1b43807f0decb5a5a58d315484
[mono.git] / mcs / tools / corcompare / mono-api-html / FieldComparer.cs
1 // 
2 // Authors
3 //    Sebastien Pouliot  <sebastien@xamarin.com>
4 //
5 // Copyright 2013-2014 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.Linq;
30 using System.Reflection;
31 using System.Text;
32 using System.Xml.Linq;
33
34 namespace Xamarin.ApiDiff {
35
36         public class FieldComparer : MemberComparer {
37
38                 public override string GroupName {
39                         get { return "fields"; }
40                 }
41
42                 public override string ElementName {
43                         get { return "field"; }
44                 }
45
46                 void RenderFieldAttributes (FieldAttributes source, FieldAttributes target, ApiChange change)
47                 {
48                         // the visibility values are the same for MethodAttributes and FieldAttributes, so just use the same method.
49                         RenderVisibility ((MethodAttributes) source, (MethodAttributes) target, change);
50                         // same for the static flag
51                         RenderStatic ((MethodAttributes) source, (MethodAttributes) target, change);
52
53                         var srcLiteral = (source & FieldAttributes.Literal) != 0;
54                         var tgtLiteral = (target & FieldAttributes.Literal) != 0;
55
56                         if (srcLiteral) {
57                                 if (tgtLiteral) {
58                                         change.Append ("const ");
59                                 } else {
60                                         change.AppendRemoved ("const", true).Append (" ");
61                                 }
62                         } else if (tgtLiteral) {
63                                 change.AppendAdded ("const", true).Append (" ");
64                         }
65
66                         var srcInitOnly = (source & FieldAttributes.InitOnly) != 0;
67                         var tgtInitOnly = (target & FieldAttributes.InitOnly) != 0;
68                         if (srcInitOnly) {
69                                 if (tgtInitOnly) {
70                                         change.Append ("readonly ");
71                                 } else {
72                                         change.AppendRemoved ("readonly", false).Append (" ");
73                                 }
74                         } else if (tgtInitOnly) {
75                                 change.AppendAdded ("readonly", true).Append (" ");
76                         }
77                 }
78
79                 public override bool Equals (XElement source, XElement target, ApiChanges changes)
80                 {
81                         if (base.Equals (source, target, changes))
82                                 return true;
83
84                         var name = source.GetAttribute ("name");
85                         var srcValue = source.GetAttribute ("value");
86                         var tgtValue = target.GetAttribute ("value");
87                         var change = new ApiChange ();
88                         change.Header = "Modified " + GroupName;
89
90                         if (State.BaseType == "System.Enum") {
91                                 change.Append (name).Append (" = ");
92                                 if (srcValue != tgtValue) {
93                                         change.AppendModified (srcValue, tgtValue, true);
94                                 } else {
95                                         change.Append (srcValue);
96                                 }
97                         } else {
98                                 RenderFieldAttributes (source.GetFieldAttributes (), target.GetFieldAttributes (), change);
99
100                                 var srcType = source.GetTypeName ("fieldtype");
101                                 var tgtType = target.GetTypeName ("fieldtype");
102
103                                 if (srcType != tgtType) {
104                                         change.AppendModified (srcType, tgtType, true);
105                                 } else {
106                                         change.Append (srcType);
107                                 }
108                                 change.Append (" ");
109                                 change.Append (name);
110
111                                 if (srcType == "string" && srcValue != null)
112                                         srcValue = "\"" + srcValue + "\"";
113
114                                 if (tgtType == "string" && tgtValue != null)
115                                         tgtValue = "\"" + tgtValue + "\"";
116
117                                 if (srcValue != tgtValue) {
118                                         change.Append (" = ");
119                                         if (srcValue == null)
120                                                 srcValue = "null";
121                                         if (tgtValue == null)
122                                                 tgtValue = "null";
123                                         change.AppendModified (srcValue, tgtValue, true);
124                                 } else if (srcValue != null) {
125                                         change.Append (" = ");
126                                         change.Append (srcValue);
127                                 }
128                                 change.Append (";");
129                         }
130
131                         changes.Add (source, target, change);
132
133                         return false;
134                 }
135
136                 public override string GetDescription (XElement e)
137                 {
138                         var sb = new StringBuilder ();
139
140                         string name = e.GetAttribute ("name");
141                         string value = e.GetAttribute ("value");
142
143                         if (State.BaseType == "System.Enum") {
144                                 sb.Append (name).Append (" = ").Append (value).Append (',');
145                         } else {
146                                 var attribs = e.Attribute ("attrib");
147                                 if (attribs != null) {
148                                         var attr = (FieldAttributes)Int32.Parse (attribs.Value);
149                                         if ((attr & FieldAttributes.Public) != FieldAttributes.Public) {
150                                                 sb.Append ("protected ");
151                                         } else {
152                                                 sb.Append ("public ");
153                                         }
154
155                                         if ((attr & FieldAttributes.Static) != 0)
156                                                 sb.Append ("static ");
157
158                                         if ((attr & FieldAttributes.Literal) != 0)
159                                                 sb.Append ("const ");
160                                 }
161
162                                 string ftype = e.GetTypeName ("fieldtype");
163                                 sb.Append (ftype).Append (' ');
164                                 sb.Append (name);
165                                 if (ftype == "string" && e.Attribute ("value") != null) {
166                                         if (value == null)
167                                                 sb.Append (" = null");
168                                         else
169                                                 sb.Append (" = \"").Append (value).Append ('"');
170                                 }
171                                 sb.Append (';');
172                         }
173
174                         return sb.ToString ();
175                 }
176
177                 public override void BeforeAdding (IEnumerable<XElement> list)
178                 {
179                         first = true;
180                         if (State.BaseType == "System.Enum") {
181                                 Output.WriteLine ("<p>Added value{0}:</p><pre>", list.Count () > 1 ? "s" : String.Empty);
182                                 if (State.Colorize)
183                                         Output.Write ("<font color='green'>");
184                         } else {
185                                 base.BeforeAdding (list);
186                         }
187                 }
188
189                 public override void BeforeRemoving (IEnumerable<XElement> list)
190                 {
191                         first = true;
192                         if (State.BaseType == "System.Enum") {
193                                 Output.WriteLine ("<p>Removed value{0}:</p><pre>", list.Count () > 1 ? "s" : String.Empty);
194                                 if (State.Colorize)
195                                         Output.Write ("<font color='red'>");
196                         } else {
197                                 base.BeforeRemoving (list);
198                         }
199                 }
200         }
201 }