Merge pull request #3240 from alexanderkyte/aot_compiler_leaks
[mono.git] / mcs / tools / 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                         if (!State.IgnoreNonbreaking) {
49                                 var srcNotSerialized = (source & FieldAttributes.NotSerialized) == FieldAttributes.NotSerialized;
50                                 var tgtNotSerialized = (target & FieldAttributes.NotSerialized) == FieldAttributes.NotSerialized;
51                                 if (srcNotSerialized != tgtNotSerialized) {
52                                         // this is not a breaking change, so only render it if it changed.
53                                         if (srcNotSerialized) {
54                                                 change.AppendRemoved ("[NonSerialized]\n");
55                                         } else {
56                                                 change.AppendAdded ("[NonSerialized]\n");
57                                         }
58                                 }
59                         }
60
61                         // the visibility values are the same for MethodAttributes and FieldAttributes, so just use the same method.
62                         RenderVisibility ((MethodAttributes) source, (MethodAttributes) target, change);
63                         // same for the static flag
64                         RenderStatic ((MethodAttributes) source, (MethodAttributes) target, change);
65
66                         var srcLiteral = (source & FieldAttributes.Literal) != 0;
67                         var tgtLiteral = (target & FieldAttributes.Literal) != 0;
68
69                         if (srcLiteral) {
70                                 if (tgtLiteral) {
71                                         change.Append ("const ");
72                                 } else {
73                                         change.AppendRemoved ("const", true).Append (" ");
74                                 }
75                         } else if (tgtLiteral) {
76                                 change.AppendAdded ("const", true).Append (" ");
77                         }
78
79                         var srcInitOnly = (source & FieldAttributes.InitOnly) != 0;
80                         var tgtInitOnly = (target & FieldAttributes.InitOnly) != 0;
81                         if (srcInitOnly) {
82                                 if (tgtInitOnly) {
83                                         change.Append ("readonly ");
84                                 } else {
85                                         change.AppendRemoved ("readonly", false).Append (" ");
86                                 }
87                         } else if (tgtInitOnly) {
88                                 change.AppendAdded ("readonly", true).Append (" ");
89                         }
90                 }
91
92                 public override bool Equals (XElement source, XElement target, ApiChanges changes)
93                 {
94                         if (base.Equals (source, target, changes))
95                                 return true;
96
97                         var name = source.GetAttribute ("name");
98                         var srcValue = source.GetAttribute ("value");
99                         var tgtValue = target.GetAttribute ("value");
100                         var change = new ApiChange ();
101                         change.Header = "Modified " + GroupName;
102
103                         if (State.BaseType == "System.Enum") {
104                                 change.Append (name).Append (" = ");
105                                 if (srcValue != tgtValue) {
106                                         change.AppendModified (srcValue, tgtValue, true);
107                                 } else {
108                                         change.Append (srcValue);
109                                 }
110                         } else {
111                                 RenderFieldAttributes (source.GetFieldAttributes (), target.GetFieldAttributes (), change);
112
113                                 var srcType = source.GetTypeName ("fieldtype");
114                                 var tgtType = target.GetTypeName ("fieldtype");
115
116                                 if (srcType != tgtType) {
117                                         change.AppendModified (srcType, tgtType, true);
118                                 } else {
119                                         change.Append (srcType);
120                                 }
121                                 change.Append (" ");
122                                 change.Append (name);
123
124                                 if (srcType == "string" && srcValue != null)
125                                         srcValue = "\"" + srcValue + "\"";
126
127                                 if (tgtType == "string" && tgtValue != null)
128                                         tgtValue = "\"" + tgtValue + "\"";
129
130                                 if (srcValue != tgtValue) {
131                                         change.Append (" = ");
132                                         if (srcValue == null)
133                                                 srcValue = "null";
134                                         if (tgtValue == null)
135                                                 tgtValue = "null";
136                                         change.AppendModified (srcValue, tgtValue, true);
137                                 } else if (srcValue != null) {
138                                         change.Append (" = ");
139                                         change.Append (srcValue);
140                                 }
141                                 change.Append (";");
142                         }
143
144                         changes.Add (source, target, change);
145
146                         return false;
147                 }
148
149                 public override string GetDescription (XElement e)
150                 {
151                         var sb = new StringBuilder ();
152
153                         string name = e.GetAttribute ("name");
154                         string value = e.GetAttribute ("value");
155
156                         if (State.BaseType == "System.Enum") {
157                                 sb.Append (name).Append (" = ").Append (value).Append (',');
158                         } else {
159                                 var attribs = e.Attribute ("attrib");
160                                 if (attribs != null) {
161                                         var attr = (FieldAttributes)Int32.Parse (attribs.Value);
162                                         if ((attr & FieldAttributes.Public) != FieldAttributes.Public) {
163                                                 sb.Append ("protected ");
164                                         } else {
165                                                 sb.Append ("public ");
166                                         }
167
168                                         if ((attr & FieldAttributes.Static) != 0)
169                                                 sb.Append ("static ");
170
171                                         if ((attr & FieldAttributes.Literal) != 0)
172                                                 sb.Append ("const ");
173                                 }
174
175                                 string ftype = e.GetTypeName ("fieldtype");
176                                 sb.Append (ftype).Append (' ');
177                                 sb.Append (name);
178                                 if (ftype == "string" && e.Attribute ("value") != null) {
179                                         if (value == null)
180                                                 sb.Append (" = null");
181                                         else
182                                                 sb.Append (" = \"").Append (value).Append ('"');
183                                 }
184                                 sb.Append (';');
185                         }
186
187                         return sb.ToString ();
188                 }
189
190                 public override void BeforeAdding (IEnumerable<XElement> list)
191                 {
192                         first = true;
193                         if (State.BaseType == "System.Enum") {
194                                 Output.WriteLine ("<div>");
195                                 Output.WriteLine ("<p>Added value{0}:</p>", list.Count () > 1 ? "s" : String.Empty);
196                                 Output.WriteLine ("<pre class='added' data-is-non-breaking>");
197                         } else {
198                                 base.BeforeAdding (list);
199                         }
200                 }
201
202                 public override void BeforeRemoving (IEnumerable<XElement> list)
203                 {
204                         first = true;
205                         if (State.BaseType == "System.Enum") {
206                                 Output.WriteLine ("<p>Removed value{0}:</p>", list.Count () > 1 ? "s" : String.Empty);
207                                 Output.WriteLine ("<pre class='removed' data-is-breaking>");
208                         } else {
209                                 base.BeforeRemoving (list);
210                         }
211                 }
212         }
213 }