PageRenderTime 2ms CodeModel.GetById 19ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

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

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