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;
32 using System.Xml.XPath;
36 namespace Mono.Linker {
38 public class XApiReader {
40 static readonly string _name = "name";
41 static readonly string _ns = string.Empty;
44 XPathDocument _document;
45 IXApiVisitor _visitor;
47 AssemblyDefinition _assembly;
49 Stack _types = new Stack ();
50 StringBuilder _signature;
52 public XApiReader (XPathDocument document, IXApiVisitor visitor)
58 public void Process (LinkContext context)
61 ProcessAssemblies (_document.CreateNavigator ());
64 void OnAssembly (XPathNavigator nav)
66 _assembly = GetAssembly (nav);
68 _visitor.OnAssembly (nav, _assembly);
70 ProcessAttributes (nav);
71 ProcessNamespaces (nav);
74 AssemblyDefinition GetAssembly (XPathNavigator nav)
76 AssemblyNameReference name = new AssemblyNameReference ();
77 name.Name = GetName (nav);
78 name.Version = new Version (GetAttribute (nav, "version"));
80 AssemblyDefinition assembly = _context.Resolve (name);
81 ProcessReferences (assembly);
85 void ProcessReferences (AssemblyDefinition assembly)
87 foreach (AssemblyNameReference name in assembly.MainModule.AssemblyReferences)
88 _context.Resolve (name);
91 void OnAttribute (XPathNavigator nav)
93 _visitor.OnAttribute (nav);
96 void PushType (TypeDefinition type)
101 TypeDefinition PeekType ()
103 return (TypeDefinition) _types.Peek ();
106 TypeDefinition PopType ()
108 return (TypeDefinition) _types.Pop ();
111 void OnNamespace (XPathNavigator nav)
113 _namespace = GetName (nav);
115 ProcessClasses (nav);
118 void OnClass (XPathNavigator nav)
120 string name = GetClassName (nav);
122 TypeDefinition type = _assembly.MainModule.Types [name];
126 _visitor.OnClass (nav, type);
130 ProcessAttributes (nav);
131 ProcessInterfaces (nav);
133 ProcessMethods (nav);
134 ProcessConstructors (nav);
135 ProcessProperties (nav);
137 ProcessClasses (nav);
142 string GetClassName (XPathNavigator nav)
144 if (IsNestedClass ())
145 return PeekType ().FullName + "/" + GetName (nav);
147 return _namespace + "." + GetName (nav);
150 bool IsNestedClass ()
152 return _types.Count > 0;
155 void OnField (XPathNavigator nav)
157 TypeDefinition declaring = PeekType ();
159 FieldDefinition field = declaring.Fields.GetField (GetName (nav));
161 _visitor.OnField (nav, field);
163 ProcessAttributes (nav);
166 void OnInterface (XPathNavigator nav)
168 string name = GetName (nav);
170 TypeDefinition type = _context.GetType (GetTypeName (name));
172 _visitor.OnInterface (nav, type);
175 void OnMethod (XPathNavigator nav)
177 InitMethodSignature (nav);
179 ProcessParameters (nav);
181 string signature = GetMethodSignature ();
183 MethodDefinition method = GetMethod (signature);
185 _visitor.OnMethod (nav, method);
187 ProcessAttributes (nav);
190 MethodDefinition GetMethod (string signature)
192 return GetMethod (PeekType ().Methods, signature);
195 MethodDefinition GetConstructor (string signature)
197 return GetMethod (PeekType ().Constructors, signature);
200 static MethodDefinition GetMethod (ICollection methods, string signature)
202 foreach (MethodDefinition method in methods)
203 if (signature == GetSignature (method))
209 static string GetSignature (MethodDefinition method)
211 return method.ToString ().Replace ("<", "[").Replace (">", "]");
214 string GetMethodSignature ()
216 _signature.Append (")");
217 return _signature.ToString ();
220 void InitMethodSignature (XPathNavigator nav)
222 _signature = new StringBuilder ();
224 string returntype = GetAttribute (nav, "returntype");
225 if (returntype == null || returntype.Length == 0)
226 returntype = Constants.Void;
228 _signature.Append (NormalizeTypeName (returntype));
229 _signature.Append (" ");
230 _signature.Append (PeekType ().FullName);
231 _signature.Append ("::");
233 string name = GetName (nav);
234 _signature.Append (GetMethodName (name));
236 _signature.Append ("(");
239 static string GetMethodName (string name)
241 return GetStringBefore (name, "(");
244 static string NormalizeTypeName (string name)
246 return name.Replace ("+", "/").Replace ("<", "[").Replace (">", "]");
249 static string GetTypeName (string name)
251 return GetStringBefore (NormalizeTypeName (name), "[");
254 static string GetStringBefore (string str, string marker)
256 int pos = str.IndexOf (marker);
260 return str.Substring (0, pos);
263 void OnParameter (XPathNavigator nav)
265 string type = GetAttribute (nav, "type");
266 int pos = int.Parse (GetAttribute (nav, "position"));
269 _signature.Append (",");
270 _signature.Append (NormalizeTypeName (type));
273 void OnConstructor (XPathNavigator nav)
275 InitMethodSignature (nav);
277 ProcessParameters (nav);
279 string signature = GetMethodSignature ();
281 MethodDefinition ctor = GetConstructor (signature);
283 _visitor.OnConstructor (nav, ctor);
285 ProcessAttributes (nav);
288 void OnProperty (XPathNavigator nav)
290 string name = GetName (nav);
291 TypeDefinition type = PeekType ();
293 PropertyDefinition [] props = type.Properties.GetProperties (name);
294 if (props != null && props.Length > 0)
295 _visitor.OnProperty (nav, props [0]);
297 ProcessAttributes (nav);
298 ProcessMethods (nav);
301 void OnEvent (XPathNavigator nav)
303 string name = GetName (nav);
304 TypeDefinition type = PeekType ();
306 EventDefinition evt = type.Events.GetEvent (name);
308 _visitor.OnEvent (nav, evt);
310 ProcessAttributes (nav);
313 void ProcessAssemblies (XPathNavigator nav)
315 ProcessChildren (nav, "assemblies//assembly", new OnChildren (OnAssembly));
318 void ProcessAttributes (XPathNavigator nav)
320 ProcessChildren (nav, "attributes//attribute", new OnChildren (OnAttribute));
323 void ProcessNamespaces (XPathNavigator nav)
325 ProcessChildren (nav, "namespaces//namespace", new OnChildren (OnNamespace));
328 void ProcessClasses (XPathNavigator nav)
330 ProcessChildren (nav, "classes//class", new OnChildren (OnClass));
333 void ProcessInterfaces (XPathNavigator nav)
335 ProcessChildren (nav, "intefaces//interface", new OnChildren (OnInterface));
338 void ProcessFields (XPathNavigator nav)
340 ProcessChildren (nav, "fields//field", new OnChildren (OnField));
343 void ProcessMethods (XPathNavigator nav)
345 ProcessChildren (nav, "methods//method", new OnChildren (OnMethod));
348 void ProcessConstructors (XPathNavigator nav)
350 ProcessChildren (nav, "constructors//constructor", new OnChildren (OnConstructor));
353 void ProcessParameters (XPathNavigator nav)
355 ProcessChildren (nav, "parameters//parameter", new OnChildren (OnParameter));
358 void ProcessProperties (XPathNavigator nav)
360 ProcessChildren (nav, "properties//property", new OnChildren (OnProperty));
363 void ProcessEvents (XPathNavigator nav)
365 ProcessChildren (nav, "events//event", new OnChildren (OnEvent));
368 static void ProcessChildren (XPathNavigator nav, string children, OnChildren action)
370 XPathNodeIterator iterator = nav.Select (children);
371 while (iterator.MoveNext ())
372 action (iterator.Current);
375 delegate void OnChildren (XPathNavigator nav);
377 static string GetName (XPathNavigator nav)
379 return GetAttribute (nav, _name);
382 static string GetAttribute (XPathNavigator nav, string attribute)
384 return nav.GetAttribute (attribute, _ns);