PageRenderTime 2183ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/main/src/core/MonoDevelop.Core/MonoDevelop.Projects.Dom/DomCecilCompilationUnit.cs

https://github.com/jfcantin/monodevelop
C# | 292 lines | 207 code | 34 blank | 51 comment | 25 complexity | bcdcb14f46502ad22c7b89500750d939 MD5 | raw file
  1. //
  2. // DomCecilCompilationUnit.cs
  3. //
  4. // Author:
  5. // Mike Krüger <mkrueger@novell.com>
  6. //
  7. // Copyright (C) 2008 Novell, Inc (http://www.novell.com)
  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. using System;
  29. using System.IO;
  30. using System.Collections.Generic;
  31. using System.Xml;
  32. using MonoDevelop.Projects.Dom;
  33. using Mono.Cecil;
  34. using MonoDevelop.Core;
  35. using MonoDevelop.Core.Assemblies;
  36. namespace MonoDevelop.Projects.Dom
  37. {
  38. public class DomCecilCompilationUnit : CompilationUnit
  39. {
  40. bool loadMonotouchDocumentation = true;
  41. AssemblyDefinition assemblyDefinition;
  42. public AssemblyDefinition AssemblyDefinition {
  43. get {
  44. return assemblyDefinition;
  45. }
  46. }
  47. public class Module
  48. {
  49. public ModuleDefinition ModuleDefinition {
  50. get;
  51. set;
  52. }
  53. List<IType> types = new List<IType> ();
  54. public List<IType> Types {
  55. get {
  56. return types;
  57. }
  58. }
  59. public Module (ModuleDefinition moduleDefinition)
  60. {
  61. this.ModuleDefinition = moduleDefinition;
  62. }
  63. }
  64. List<Module> modules = new List<Module> ();
  65. public IEnumerable<Module> Modules {
  66. get {
  67. return modules;
  68. }
  69. }
  70. //
  71. // public DomCecilCompilationUnit (AssemblyDefinition assemblyDefinition) : this (true, true, assemblyDefinition)
  72. // {
  73. // }
  74. public DomCecilCompilationUnit (AssemblyDefinition assemblyDefinition, bool loadInternals, bool instantiateTypeParameter) : base (assemblyDefinition.Name.FullName)
  75. {
  76. this.assemblyDefinition = assemblyDefinition;
  77. foreach (ModuleDefinition moduleDefinition in assemblyDefinition.Modules) {
  78. AddModuleDefinition (moduleDefinition, loadInternals, instantiateTypeParameter);
  79. }
  80. foreach (CustomAttribute attr in assemblyDefinition.CustomAttributes) {
  81. Add (new DomCecilAttribute (attr));
  82. }
  83. }
  84. public static AssemblyDefinition ReadAssembly (string fileName, bool useCustomResolver = true)
  85. {
  86. ReaderParameters parameters = new ReaderParameters ();
  87. if (useCustomResolver)
  88. parameters.AssemblyResolver = new SimpleAssemblyResolver (Path.GetDirectoryName (fileName));
  89. using (var stream = new MemoryStream (File.ReadAllBytes (fileName))) {
  90. return AssemblyDefinition.ReadAssembly (stream, parameters);
  91. }
  92. }
  93. /* public static DomCecilCompilationUnit Load (string fileName)
  94. {
  95. return Load (fileName, true);
  96. }
  97. public static DomCecilCompilationUnit Load (string fileName, bool keepDefinitions)
  98. {
  99. return Load (fileName, true, true);
  100. }
  101. public static DomCecilCompilationUnit Load (string fileName, bool keepDefinitions, bool loadInternals)
  102. {
  103. return
  104. Load (fileName, true, true, false);
  105. }
  106. */
  107. public static DomCecilCompilationUnit Load (string fileName, bool loadInternals, bool instantiateTypeParameter, bool customResolver = true)
  108. {
  109. if (String.IsNullOrEmpty (fileName))
  110. return null;
  111. DomCecilCompilationUnit result = new DomCecilCompilationUnit (ReadAssembly (fileName, customResolver), loadInternals, instantiateTypeParameter);
  112. result.fileName = fileName;
  113. return result;
  114. }
  115. class SimpleAssemblyResolver : IAssemblyResolver
  116. {
  117. string lookupPath;
  118. Dictionary<string, AssemblyDefinition> cache = new Dictionary<string, AssemblyDefinition> ();
  119. public SimpleAssemblyResolver (string lookupPath)
  120. {
  121. this.lookupPath = lookupPath;
  122. }
  123. public AssemblyDefinition InternalResolve (string fullName)
  124. {
  125. AssemblyDefinition result;
  126. if (cache.TryGetValue (fullName, out result))
  127. return result;
  128. var name = AssemblyNameReference.Parse (fullName);
  129. // need to handle different file extension casings. Some dlls from windows tend to end with .Dll or .DLL rather than '.dll'
  130. foreach (string file in Directory.GetFiles (lookupPath, name.Name + ".*")) {
  131. string ext = Path.GetExtension (file);
  132. if (string.IsNullOrEmpty (ext))
  133. continue;
  134. ext = ext.ToUpper ();
  135. if (ext == ".DLL" || ext == ".EXE") {
  136. result = ReadAssembly (file);
  137. break;
  138. }
  139. }
  140. if (result == null) {
  141. var framework = Services.ProjectService.DefaultTargetFramework;
  142. var assemblyName = Runtime.SystemAssemblyService.DefaultAssemblyContext.GetAssemblyFullName (fullName, framework);
  143. if (assemblyName == null)
  144. return null;
  145. var location = Runtime.SystemAssemblyService.DefaultAssemblyContext.GetAssemblyLocation (assemblyName, framework);
  146. if (!string.IsNullOrEmpty (location) && File.Exists (location)) {
  147. result = ReadAssembly (location);
  148. }
  149. }
  150. if (result != null)
  151. cache [fullName] = result;
  152. return result;
  153. }
  154. #region IAssemblyResolver implementation
  155. public AssemblyDefinition Resolve (AssemblyNameReference name)
  156. {
  157. return InternalResolve (name.FullName) ?? GlobalAssemblyResolver.Instance.Resolve (name);
  158. }
  159. public AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters)
  160. {
  161. return InternalResolve (name.FullName) ?? GlobalAssemblyResolver.Instance.Resolve (name, parameters);
  162. }
  163. public AssemblyDefinition Resolve (string fullName)
  164. {
  165. return InternalResolve (fullName) ?? GlobalAssemblyResolver.Instance.Resolve (fullName);
  166. }
  167. public AssemblyDefinition Resolve (string fullName, ReaderParameters parameters)
  168. {
  169. return InternalResolve (fullName) ?? GlobalAssemblyResolver.Instance.Resolve (fullName, parameters);
  170. }
  171. #endregion
  172. }
  173. public static bool IsInternal (MonoDevelop.Projects.Dom.Modifiers mods)
  174. {
  175. return (mods & MonoDevelop.Projects.Dom.Modifiers.Internal) == MonoDevelop.Projects.Dom.Modifiers.Internal ||
  176. (mods & MonoDevelop.Projects.Dom.Modifiers.Private) == MonoDevelop.Projects.Dom.Modifiers.Private ||
  177. (mods & MonoDevelop.Projects.Dom.Modifiers.ProtectedAndInternal) == MonoDevelop.Projects.Dom.Modifiers.ProtectedAndInternal;
  178. }
  179. void AddModuleDefinition (ModuleDefinition moduleDefinition, bool loadInternal, bool instantiateTypeParameter)
  180. {
  181. InstantiatedParamResolver resolver = new InstantiatedParamResolver ();
  182. Module module = new Module (moduleDefinition);
  183. foreach (TypeDefinition type in moduleDefinition.Types) {
  184. if (!loadInternal && IsInternal (DomCecilType.GetModifiers (type.Attributes)))
  185. continue;
  186. // if (type.Name == "SimplePropertyDescriptor")
  187. // System.Console.WriteLine(type.Attributes + "/" + DomCecilType.GetModifiers (type.Attributes) + "/" + IsInternal (DomCecilType.GetModifiers (type.Attributes)));
  188. DomCecilType loadType = new DomCecilType (type, loadInternal, loadMonotouchDocumentation);
  189. if (instantiateTypeParameter) {
  190. resolver.Visit (loadType, null);
  191. resolver.ClearTypes ();
  192. }
  193. loadMonotouchDocumentation &= loadType.LoadMonotouchDocumentation;
  194. Add (loadType);
  195. module.Types.Add (loadType);
  196. }
  197. this.modules.Add (module);
  198. }
  199. class InstantiatedParamResolver : AbstractDomVisitor<object, object>
  200. {
  201. Dictionary<string, IType> argTypes = new Dictionary<string, IType> ();
  202. public InstantiatedParamResolver ()
  203. {
  204. }
  205. public void ClearTypes ()
  206. {
  207. this.argTypes.Clear ();
  208. }
  209. public override object Visit (IType type, object data)
  210. {
  211. foreach (TypeParameter p in type.TypeParameters)
  212. argTypes[p.Name] = type;
  213. foreach (IMember member in type.Members) {
  214. CheckReturnType (member.ReturnType);
  215. member.AcceptVisitor (this, data);
  216. }
  217. return null;
  218. }
  219. public override object Visit (IEvent evt, object data)
  220. {
  221. return null;
  222. }
  223. public override object Visit (IField field, object data)
  224. {
  225. return null;
  226. }
  227. public override object Visit (IMethod method, object data)
  228. {
  229. foreach (IParameter param in method.Parameters) {
  230. CheckReturnType (param.ReturnType);
  231. }
  232. return null;
  233. }
  234. public override object Visit (IProperty property, object data)
  235. {
  236. foreach (IParameter param in property.Parameters) {
  237. CheckReturnType (param.ReturnType);
  238. }
  239. return null;
  240. }
  241. void CheckReturnType (IReturnType type)
  242. {
  243. if (type == null)
  244. return;
  245. IType resultType;
  246. if (argTypes.TryGetValue (type.FullName, out resultType)) {
  247. DomReturnType returnType = (DomReturnType)type;
  248. // Console.Write ("Convert:" + returnType);
  249. string returnTypeName = returnType.FullName;
  250. returnType.SetType (resultType);
  251. returnType.Parts.Add (new ReturnTypePart (returnTypeName, null));
  252. // Console.WriteLine (" to:" + returnType);
  253. }
  254. }
  255. }
  256. }
  257. }