5 // Jb Evain (jbevain@novell.com)
7 // (C) 2007 Novell, Inc.
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
30 using System.Collections;
33 using System.Xml.XPath;
37 namespace Mono.Linker {
39 public class XApiReader {
41 static readonly string _name = "name";
42 static readonly string _ns = string.Empty;
45 XPathDocument _document;
46 IXApiVisitor _visitor;
48 AssemblyDefinition _assembly;
50 Stack _types = new Stack ();
51 StringBuilder _signature;
53 public XApiReader (XPathDocument document, IXApiVisitor visitor)
59 public void Process (LinkContext context)
62 ProcessAssemblies (_document.CreateNavigator ());
65 void OnAssembly (XPathNavigator nav)
67 _assembly = GetAssembly (nav);
69 _visitor.OnAssembly (nav, _assembly);
71 ProcessAttributes (nav);
72 ProcessNamespaces (nav);
75 AssemblyDefinition GetAssembly (XPathNavigator nav)
77 AssemblyNameReference name = new AssemblyNameReference (
79 new Version (GetAttribute (nav, "version")));
81 AssemblyDefinition assembly = _context.Resolve (name);
82 ProcessReferences (assembly);
86 void ProcessReferences (AssemblyDefinition assembly)
88 foreach (AssemblyNameReference name in assembly.MainModule.AssemblyReferences)
89 _context.Resolve (name);
92 void OnAttribute (XPathNavigator nav)
94 _visitor.OnAttribute (nav);
97 void PushType (TypeDefinition type)
102 TypeDefinition PeekType ()
104 return (TypeDefinition) _types.Peek ();
107 TypeDefinition PopType ()
109 return (TypeDefinition) _types.Pop ();
112 void OnNamespace (XPathNavigator nav)
114 _namespace = GetName (nav);
116 ProcessClasses (nav);
119 void OnClass (XPathNavigator nav)
121 string name = GetClassName (nav);
123 TypeDefinition type = _assembly.MainModule.GetType (name);
127 _visitor.OnClass (nav, type);
131 ProcessAttributes (nav);
132 ProcessInterfaces (nav);
134 ProcessMethods (nav);
135 ProcessConstructors (nav);
136 ProcessProperties (nav);
138 ProcessClasses (nav);
143 string GetClassName (XPathNavigator nav)
145 if (IsNestedClass ())
146 return PeekType ().FullName + "/" + GetName (nav);
148 return _namespace + "." + GetName (nav);
151 bool IsNestedClass ()
153 return _types.Count > 0;
156 void OnField (XPathNavigator nav)
158 TypeDefinition declaring = PeekType ();
160 FieldDefinition field = declaring.Fields.FirstOrDefault (f => f.Name == GetName (nav));
162 _visitor.OnField (nav, field);
164 ProcessAttributes (nav);
167 void OnInterface (XPathNavigator nav)
169 string name = GetName (nav);
171 TypeDefinition type = _context.GetType (GetTypeName (name));
173 _visitor.OnInterface (nav, type);
176 void OnMethod (XPathNavigator nav)
178 InitMethodSignature (nav);
180 ProcessParameters (nav);
182 string signature = GetMethodSignature ();
184 MethodDefinition method = GetMethod (signature);
186 _visitor.OnMethod (nav, method);
188 ProcessAttributes (nav);
191 MethodDefinition GetMethod (string signature)
193 return GetMethod (PeekType ().Methods, signature);
196 static MethodDefinition GetMethod (ICollection methods, string signature)
198 foreach (MethodDefinition method in methods)
199 if (signature == GetSignature (method))
205 static string GetSignature (MethodDefinition method)
207 return method.ToString ().Replace ("<", "[").Replace (">", "]");
210 string GetMethodSignature ()
212 _signature.Append (")");
213 return _signature.ToString ();
216 void InitMethodSignature (XPathNavigator nav)
218 _signature = new StringBuilder ();
220 string returntype = GetAttribute (nav, "returntype");
221 if (returntype == null || returntype.Length == 0)
222 returntype = "System.Void";
224 _signature.Append (NormalizeTypeName (returntype));
225 _signature.Append (" ");
226 _signature.Append (PeekType ().FullName);
227 _signature.Append ("::");
229 string name = GetName (nav);
230 _signature.Append (GetMethodName (name));
232 _signature.Append ("(");
235 static string GetMethodName (string name)
237 return GetStringBefore (name, "(");
240 static string NormalizeTypeName (string name)
242 return name.Replace ("+", "/").Replace ("<", "[").Replace (">", "]");
245 static string GetTypeName (string name)
247 return GetStringBefore (NormalizeTypeName (name), "[");
250 static string GetStringBefore (string str, string marker)
252 int pos = str.IndexOf (marker);
256 return str.Substring (0, pos);
259 void OnParameter (XPathNavigator nav)
261 string type = GetAttribute (nav, "type");
262 int pos = int.Parse (GetAttribute (nav, "position"));
265 _signature.Append (",");
266 _signature.Append (NormalizeTypeName (type));
269 void OnConstructor (XPathNavigator nav)
271 InitMethodSignature (nav);
273 ProcessParameters (nav);
275 string signature = GetMethodSignature ();
277 MethodDefinition ctor = GetMethod (signature);
279 _visitor.OnConstructor (nav, ctor);
281 ProcessAttributes (nav);
284 void OnProperty (XPathNavigator nav)
286 string name = GetName (nav);
287 TypeDefinition type = PeekType ();
289 var property = type.Properties.FirstOrDefault (p => p.Name == name);
290 if (property != null)
291 _visitor.OnProperty (nav, property);
293 ProcessAttributes (nav);
294 ProcessMethods (nav);
297 void OnEvent (XPathNavigator nav)
299 string name = GetName (nav);
300 TypeDefinition type = PeekType ();
302 EventDefinition evt = type.Events.FirstOrDefault (e => e.Name == name);
304 _visitor.OnEvent (nav, evt);
306 ProcessAttributes (nav);
309 void ProcessAssemblies (XPathNavigator nav)
311 ProcessChildren (nav, "assemblies//assembly", new OnChildren (OnAssembly));
314 void ProcessAttributes (XPathNavigator nav)
316 ProcessChildren (nav, "attributes//attribute", new OnChildren (OnAttribute));
319 void ProcessNamespaces (XPathNavigator nav)
321 ProcessChildren (nav, "namespaces//namespace", new OnChildren (OnNamespace));
324 void ProcessClasses (XPathNavigator nav)
326 ProcessChildren (nav, "classes//class", new OnChildren (OnClass));
329 void ProcessInterfaces (XPathNavigator nav)
331 ProcessChildren (nav, "intefaces//interface", new OnChildren (OnInterface));
334 void ProcessFields (XPathNavigator nav)
336 ProcessChildren (nav, "fields//field", new OnChildren (OnField));
339 void ProcessMethods (XPathNavigator nav)
341 ProcessChildren (nav, "methods//method", new OnChildren (OnMethod));
344 void ProcessConstructors (XPathNavigator nav)
346 ProcessChildren (nav, "constructors//constructor", new OnChildren (OnConstructor));
349 void ProcessParameters (XPathNavigator nav)
351 ProcessChildren (nav, "parameters//parameter", new OnChildren (OnParameter));
354 void ProcessProperties (XPathNavigator nav)
356 ProcessChildren (nav, "properties//property", new OnChildren (OnProperty));
359 void ProcessEvents (XPathNavigator nav)
361 ProcessChildren (nav, "events//event", new OnChildren (OnEvent));
364 static void ProcessChildren (XPathNavigator nav, string children, OnChildren action)
366 XPathNodeIterator iterator = nav.Select (children);
367 while (iterator.MoveNext ())
368 action (iterator.Current);
371 delegate void OnChildren (XPathNavigator nav);
373 static string GetName (XPathNavigator nav)
375 return GetAttribute (nav, _name);
378 static string GetAttribute (XPathNavigator nav, string attribute)
380 return nav.GetAttribute (attribute, _ns);