Remove IVT from System.ServiceModel on MonoDroid, MonoTouch profiles.
[mono.git] / mcs / tools / linker / Mono.Linker / XApiReader.cs
1 //
2 // XApiReader.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@novell.com)
6 //
7 // (C) 2007 Novell, Inc.
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.Collections;
31 using System.Text;
32 using System.Xml.XPath;
33
34 using Mono.Cecil;
35
36 namespace Mono.Linker {
37
38         public class XApiReader {
39
40                 static readonly string _name = "name";
41                 static readonly string _ns = string.Empty;
42
43                 LinkContext _context;
44                 XPathDocument _document;
45                 IXApiVisitor _visitor;
46
47                 AssemblyDefinition _assembly;
48                 string _namespace;
49                 Stack _types = new Stack ();
50                 StringBuilder _signature;
51
52                 public XApiReader (XPathDocument document, IXApiVisitor visitor)
53                 {
54                         _document = document;
55                         _visitor = visitor;
56                 }
57
58                 public void Process (LinkContext context)
59                 {
60                         _context = context;
61                         ProcessAssemblies (_document.CreateNavigator ());
62                 }
63
64                 void OnAssembly (XPathNavigator nav)
65                 {
66                         _assembly = GetAssembly (nav);
67
68                         _visitor.OnAssembly (nav, _assembly);
69
70                         ProcessAttributes (nav);
71                         ProcessNamespaces (nav);
72                 }
73
74                 AssemblyDefinition GetAssembly (XPathNavigator nav)
75                 {
76                         AssemblyNameReference name = new AssemblyNameReference ();
77                         name.Name = GetName (nav);
78                         name.Version = new Version (GetAttribute (nav, "version"));
79
80                         AssemblyDefinition assembly = _context.Resolve (name);
81                         ProcessReferences (assembly);
82                         return assembly;
83                 }
84
85                 void ProcessReferences (AssemblyDefinition assembly)
86                 {
87                         foreach (AssemblyNameReference name in assembly.MainModule.AssemblyReferences)
88                                 _context.Resolve (name);
89                 }
90
91                 void OnAttribute (XPathNavigator nav)
92                 {
93                         _visitor.OnAttribute (nav);
94                 }
95
96                 void PushType (TypeDefinition type)
97                 {
98                         _types.Push (type);
99                 }
100
101                 TypeDefinition PeekType ()
102                 {
103                         return (TypeDefinition) _types.Peek ();
104                 }
105
106                 TypeDefinition PopType ()
107                 {
108                         return (TypeDefinition) _types.Pop ();
109                 }
110
111                 void OnNamespace (XPathNavigator nav)
112                 {
113                         _namespace = GetName (nav);
114
115                         ProcessClasses (nav);
116                 }
117
118                 void OnClass (XPathNavigator nav)
119                 {
120                         string name = GetClassName (nav);
121
122                         TypeDefinition type = _assembly.MainModule.Types [name];
123                         if (type == null)
124                                 return;
125
126                         _visitor.OnClass (nav, type);
127
128                         PushType (type);
129
130                         ProcessAttributes (nav);
131                         ProcessInterfaces (nav);
132                         ProcessFields (nav);
133                         ProcessMethods (nav);
134                         ProcessConstructors (nav);
135                         ProcessProperties (nav);
136                         ProcessEvents (nav);
137                         ProcessClasses (nav);
138
139                         PopType ();
140                 }
141
142                 string GetClassName (XPathNavigator nav)
143                 {
144                         if (IsNestedClass ())
145                                 return PeekType ().FullName + "/" + GetName (nav);
146
147                         return _namespace + "." + GetName (nav);
148                 }
149
150                 bool IsNestedClass ()
151                 {
152                         return _types.Count > 0;
153                 }
154
155                 void OnField (XPathNavigator nav)
156                 {
157                         TypeDefinition declaring = PeekType ();
158
159                         FieldDefinition field = declaring.Fields.GetField (GetName (nav));
160                         if (field != null)
161                                 _visitor.OnField (nav, field);
162
163                         ProcessAttributes (nav);
164                 }
165
166                 void OnInterface (XPathNavigator nav)
167                 {
168                         string name = GetName (nav);
169
170                         TypeDefinition type = _context.GetType (GetTypeName (name));
171                         if (type != null)
172                                 _visitor.OnInterface (nav, type);
173                 }
174
175                 void OnMethod (XPathNavigator nav)
176                 {
177                         InitMethodSignature (nav);
178
179                         ProcessParameters (nav);
180
181                         string signature = GetMethodSignature ();
182
183                         MethodDefinition method = GetMethod (signature);
184                         if (method != null)
185                                 _visitor.OnMethod (nav, method);
186
187                         ProcessAttributes (nav);
188                 }
189
190                 MethodDefinition GetMethod (string signature)
191                 {
192                         return GetMethod (PeekType ().Methods, signature);
193                 }
194
195                 MethodDefinition GetConstructor (string signature)
196                 {
197                         return GetMethod (PeekType ().Constructors, signature);
198                 }
199
200                 static MethodDefinition GetMethod (ICollection methods, string signature)
201                 {
202                         foreach (MethodDefinition method in methods)
203                                 if (signature == GetSignature (method))
204                                         return method;
205
206                         return null;
207                 }
208
209                 static string GetSignature (MethodDefinition method)
210                 {
211                         return method.ToString ().Replace ("<", "[").Replace (">", "]");
212                 }
213
214                 string GetMethodSignature ()
215                 {
216                         _signature.Append (")");
217                         return _signature.ToString ();
218                 }
219
220                 void InitMethodSignature (XPathNavigator nav)
221                 {
222                         _signature = new StringBuilder ();
223
224                         string returntype = GetAttribute (nav, "returntype");
225                         if (returntype == null || returntype.Length == 0)
226                                 returntype = Constants.Void;
227
228                         _signature.Append (NormalizeTypeName (returntype));
229                         _signature.Append (" ");
230                         _signature.Append (PeekType ().FullName);
231                         _signature.Append ("::");
232
233                         string name = GetName (nav);
234                         _signature.Append (GetMethodName (name));
235
236                         _signature.Append ("(");
237                 }
238
239                 static string GetMethodName (string name)
240                 {
241                         return GetStringBefore (name, "(");
242                 }
243
244                 static string NormalizeTypeName (string name)
245                 {
246                         return name.Replace ("+", "/").Replace ("<", "[").Replace (">", "]");
247                 }
248
249                 static string GetTypeName (string name)
250                 {
251                         return GetStringBefore (NormalizeTypeName (name), "[");
252                 }
253
254                 static string GetStringBefore (string str, string marker)
255                 {
256                         int pos = str.IndexOf (marker);
257                         if (pos == -1)
258                                 return str;
259
260                         return str.Substring (0, pos);
261                 }
262
263                 void OnParameter (XPathNavigator nav)
264                 {
265                         string type = GetAttribute (nav, "type");
266                         int pos = int.Parse (GetAttribute (nav, "position"));
267
268                         if (pos > 0)
269                                 _signature.Append (",");
270                         _signature.Append (NormalizeTypeName (type));
271                 }
272
273                 void OnConstructor (XPathNavigator nav)
274                 {
275                         InitMethodSignature (nav);
276
277                         ProcessParameters (nav);
278
279                         string signature = GetMethodSignature ();
280
281                         MethodDefinition ctor = GetConstructor (signature);
282                         if (ctor != null)
283                                 _visitor.OnConstructor (nav, ctor);
284
285                         ProcessAttributes (nav);
286                 }
287
288                 void OnProperty (XPathNavigator nav)
289                 {
290                         string name = GetName (nav);
291                         TypeDefinition type = PeekType ();
292
293                         PropertyDefinition [] props = type.Properties.GetProperties (name);
294                         if (props != null && props.Length > 0)
295                                 _visitor.OnProperty (nav, props [0]);
296
297                         ProcessAttributes (nav);
298                         ProcessMethods (nav);
299                 }
300
301                 void OnEvent (XPathNavigator nav)
302                 {
303                         string name = GetName (nav);
304                         TypeDefinition type = PeekType ();
305
306                         EventDefinition evt = type.Events.GetEvent (name);
307                         if (evt != null)
308                                 _visitor.OnEvent (nav, evt);
309
310                         ProcessAttributes (nav);
311                 }
312
313                 void ProcessAssemblies (XPathNavigator nav)
314                 {
315                         ProcessChildren (nav, "assemblies//assembly", new OnChildren (OnAssembly));
316                 }
317
318                 void ProcessAttributes (XPathNavigator nav)
319                 {
320                         ProcessChildren (nav, "attributes//attribute", new OnChildren (OnAttribute));
321                 }
322
323                 void ProcessNamespaces (XPathNavigator nav)
324                 {
325                         ProcessChildren (nav, "namespaces//namespace", new OnChildren (OnNamespace));
326                 }
327
328                 void ProcessClasses (XPathNavigator nav)
329                 {
330                         ProcessChildren (nav, "classes//class", new OnChildren (OnClass));
331                 }
332
333                 void ProcessInterfaces (XPathNavigator nav)
334                 {
335                         ProcessChildren (nav, "intefaces//interface", new OnChildren (OnInterface));
336                 }
337
338                 void ProcessFields (XPathNavigator nav)
339                 {
340                         ProcessChildren (nav, "fields//field", new OnChildren (OnField));
341                 }
342
343                 void ProcessMethods (XPathNavigator nav)
344                 {
345                         ProcessChildren (nav, "methods//method", new OnChildren (OnMethod));
346                 }
347
348                 void ProcessConstructors (XPathNavigator nav)
349                 {
350                         ProcessChildren (nav, "constructors//constructor", new OnChildren (OnConstructor));
351                 }
352
353                 void ProcessParameters (XPathNavigator nav)
354                 {
355                         ProcessChildren (nav, "parameters//parameter", new OnChildren (OnParameter));
356                 }
357
358                 void ProcessProperties (XPathNavigator nav)
359                 {
360                         ProcessChildren (nav, "properties//property", new OnChildren (OnProperty));
361                 }
362
363                 void ProcessEvents (XPathNavigator nav)
364                 {
365                         ProcessChildren (nav, "events//event", new OnChildren (OnEvent));
366                 }
367
368                 static void ProcessChildren (XPathNavigator nav, string children, OnChildren action)
369                 {
370                         XPathNodeIterator iterator = nav.Select (children);
371                         while (iterator.MoveNext ())
372                                 action (iterator.Current);
373                 }
374
375                 delegate void OnChildren (XPathNavigator nav);
376
377                 static string GetName (XPathNavigator nav)
378                 {
379                         return GetAttribute (nav, _name);
380                 }
381
382                 static string GetAttribute (XPathNavigator nav, string attribute)
383                 {
384                         return nav.GetAttribute (attribute, _ns);
385                 }
386         }
387 }