[mono-api-html] Prettier output when dealing with arrays ([] or [][]), nullable ...
[mono.git] / mcs / tools / corcompare / mono-api-html / Helpers.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.Text;
29 using System.Xml.Linq;
30
31 namespace Xamarin.ApiDiff {
32
33         public static class Helper {
34
35                 public static bool IsTrue (this XElement self, string name)
36                 {
37                         return (self.GetAttribute (name) == "true");
38                 }
39
40                 public static string GetAttribute (this XElement self, string name)
41                 {
42                         var n = self.Attribute (name);
43                         if (n == null)
44                                 return null;
45                         return n.Value;
46                 }
47
48                 // null == no obsolete, String.Empty == no description
49                 public static string GetObsoleteMessage (this XElement self)
50                 {
51                         var cattrs = self.Element ("attributes");
52                         if (cattrs == null)
53                                 return null;
54
55                         foreach (var ca in cattrs.Elements ("attribute")) {
56                                 if (ca.GetAttribute ("name") != "System.ObsoleteAttribute")
57                                         continue;
58                                 var props = ca.Element ("properties");
59                                 if (props == null)
60                                         return String.Empty; // no description
61                                 foreach (var p in props.Elements ("property")) {
62                                         if (p.GetAttribute ("name") != "Message")
63                                                 continue;
64                                         return p.GetAttribute ("value");
65                                 }
66                         }
67                         return null;
68                 }
69
70                 // make it beautiful (.NET -> C#)
71                 public static string GetTypeName (this XElement self, string name)
72                 {
73                         string type = self.GetAttribute (name);
74                         if (type == null)
75                                 return null;
76
77                         StringBuilder sb = null;
78                         bool is_nullable = false;
79                         if (type.StartsWith ("System.Nullable`1[", StringComparison.Ordinal)) {
80                                 is_nullable = true;
81                                 sb = new StringBuilder (type, 18, type.Length - 19, 1024);
82                         } else {
83                                 sb = new StringBuilder (type);
84                         }
85
86                         bool is_ref = (sb [sb.Length - 1] == '&');
87                         if (is_ref)
88                                 sb.Remove (sb.Length - 1, 1);
89
90                         int array = 0;
91                         while ((sb [sb.Length - 1] == ']') && (sb [sb.Length - 2] == '[')) {
92                                 sb.Remove (sb.Length - 2, 2);
93                                 array++;
94                         }
95
96                         bool is_pointer = (sb [sb.Length - 1] == '*');
97                         if (is_pointer)
98                                 sb.Remove (sb.Length - 1, 1);
99
100                         type = GetTypeName (sb.Replace ('+', '.').ToString ());
101                         sb.Length = 0;
102                         if (is_ref)
103                                 sb.Append (self.GetAttribute ("direction")).Append (' ');
104
105                         sb.Append (type);
106
107                         while (array-- > 0)
108                                 sb.Append ("[]");
109                         if (is_nullable)
110                                 sb.Append ('?');
111                         if (is_pointer)
112                                 sb.Append ('*');
113                         return sb.ToString ();
114                 }
115
116                 static string GetTypeName (string type)
117                 {
118                         int pos = type.IndexOf ('`');
119                         if (pos >= 0) {
120                                 int end = type.LastIndexOf (']');
121                                 string subtype = type.Substring (pos + 3, end - pos - 3);
122                                 return type.Substring (0, pos) + "&lt;" + GetTypeName (subtype) + "&gt;";
123                         }
124
125                         switch (type) {
126                         case "System.String":
127                                 return "string";
128                         case "System.Int32":
129                                 return "int";
130                         case "System.UInt32":
131                                 return "uint";
132                         case "System.Int64":
133                                 return "long";
134                         case "System.UInt64":
135                                 return "ulong";
136                         case "System.Void":
137                                 return "void";
138                         case "System.Boolean":
139                                 return "bool";
140                         case "System.Object":
141                                 return "object";
142                         case "System.Single":
143                                 return "float";
144                         case "System.Double":
145                                 return "double";
146                         case "System.Byte":
147                                 return "byte";
148                         case "System.SByte":
149                                 return "sbyte";
150                         case "System.Int16":
151                                 return "short";
152                         case "System.UInt16":
153                                 return "ushort";
154                         case "System.Char":
155                                 return "char";
156                         default:
157                                 if (type.StartsWith (State.Namespace, StringComparison.Ordinal))
158                                         type = type.Substring (State.Namespace.Length + 1);
159                                 return type;
160                         }
161                 }
162         }
163 }