PageRenderTime 657ms CodeModel.GetById 17ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 627ms

/ICSharpCode.Decompiler/Ast/CecilTypeResolveContext.cs

http://github.com/icsharpcode/ILSpy
C# | 189 lines | 145 code | 21 blank | 23 comment | 20 complexity | e60f28b2646011884fe4d0665dc474ac MD5 | raw file
  1// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
  2// 
  3// Permission is hereby granted, free of charge, to any person obtaining a copy of this
  4// software and associated documentation files (the "Software"), to deal in the Software
  5// without restriction, including without limitation the rights to use, copy, modify, merge,
  6// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
  7// to whom the Software is furnished to do so, subject to the following conditions:
  8// 
  9// The above copyright notice and this permission notice shall be included in all copies or
 10// substantial portions of the Software.
 11// 
 12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 13// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
 15// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 16// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 17// DEALINGS IN THE SOFTWARE.
 18
 19using System;
 20using System.Collections.Generic;
 21using System.Linq;
 22using ICSharpCode.NRefactory;
 23using ICSharpCode.NRefactory.TypeSystem;
 24using Mono.Cecil;
 25
 26namespace ICSharpCode.Decompiler.Ast
 27{
 28	/// <summary>
 29	/// ITypeResolveContext implementation that lazily loads types from Cecil.
 30	/// </summary>
 31	public class CecilTypeResolveContext : AbstractAnnotatable, ISynchronizedTypeResolveContext, IProjectContent
 32	{
 33		readonly ModuleDefinition module;
 34		readonly string[] namespaces;
 35		readonly CecilLoader loader;
 36		Dictionary<TypeDefinition, WeakReference> dict = new Dictionary<TypeDefinition, WeakReference>();
 37		int countUntilNextCleanup = 4;
 38		
 39		public CecilTypeResolveContext(ModuleDefinition module)
 40		{
 41			this.loader = new CecilLoader();
 42			this.loader.IncludeInternalMembers = true;
 43			this.module = module;
 44			this.namespaces = module.Types.Select(t => t.Namespace).Distinct().ToArray();
 45			
 46			List<IAttribute> assemblyAttributes = new List<IAttribute>();
 47			foreach (var attr in module.Assembly.CustomAttributes) {
 48				assemblyAttributes.Add(loader.ReadAttribute(attr));
 49			}
 50			this.AssemblyAttributes = assemblyAttributes.AsReadOnly();
 51		}
 52		
 53		ITypeDefinition GetClass(TypeDefinition cecilType)
 54		{
 55			lock (dict) {
 56				WeakReference wr;
 57				ITypeDefinition type;
 58				if (dict.TryGetValue(cecilType, out wr)) {
 59					type = (ITypeDefinition)wr.Target;
 60				} else {
 61					wr = null;
 62					type = null;
 63				}
 64				if (type == null) {
 65					type = loader.LoadType(cecilType, this);
 66				}
 67				if (wr == null) {
 68					if (--countUntilNextCleanup <= 0)
 69						CleanupDict();
 70					wr = new WeakReference(type);
 71					dict.Add(cecilType, wr);
 72				} else {
 73					wr.Target = type;
 74				}
 75				return type;
 76			}
 77		}
 78		
 79		void CleanupDict()
 80		{
 81			List<TypeDefinition> deletedKeys = new List<TypeDefinition>();
 82			foreach (var pair in dict) {
 83				if (!pair.Value.IsAlive) {
 84					deletedKeys.Add(pair.Key);
 85				}
 86			}
 87			foreach (var key in deletedKeys) {
 88				dict.Remove(key);
 89			}
 90			countUntilNextCleanup = dict.Count + 4;
 91		}
 92		
 93		public string AssemblyName {
 94			get { return module.Assembly.Name.Name; }
 95		}
 96		
 97		public IList<IAttribute> ModuleAttributes { get; private set; }
 98		
 99		public IList<IAttribute> AssemblyAttributes { get; private set; }
100		
101		public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer)
102		{
103			if (typeParameterCount > 0)
104				name = name + "`" + typeParameterCount.ToString();
105			if (nameComparer == StringComparer.Ordinal) {
106				TypeDefinition cecilType = module.GetType(nameSpace, name);
107				if (cecilType != null)
108					return GetClass(cecilType);
109				else
110					return null;
111			}
112			foreach (TypeDefinition cecilType in module.Types) {
113				if (nameComparer.Equals(name, cecilType.Name)
114				    && nameComparer.Equals(nameSpace, cecilType.Namespace)
115				    && cecilType.GenericParameters.Count == typeParameterCount)
116				{
117					return GetClass(cecilType);
118				}
119			}
120			return null;
121		}
122		
123		public ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode)
124		{
125			return GetTypeDefinition("System", ReflectionHelper.GetShortNameByTypeCode(typeCode), 0, StringComparer.Ordinal);
126		}
127		
128		public IEnumerable<ITypeDefinition> GetTypes()
129		{
130			foreach (TypeDefinition cecilType in module.Types) {
131				yield return GetClass(cecilType);
132			}
133		}
134		
135		public IEnumerable<ITypeDefinition> GetTypes(string nameSpace, StringComparer nameComparer)
136		{
137			foreach (TypeDefinition cecilType in module.Types) {
138				if (nameComparer.Equals(nameSpace, cecilType.Namespace))
139					yield return GetClass(cecilType);
140			}
141		}
142		
143		public IEnumerable<string> GetNamespaces()
144		{
145			return namespaces;
146		}
147		
148		public string GetNamespace(string nameSpace, StringComparer nameComparer)
149		{
150			foreach (string ns in namespaces) {
151				if (nameComparer.Equals(ns, nameSpace))
152					return ns;
153			}
154			return null;
155		}
156		
157		ICSharpCode.NRefactory.Utils.CacheManager ITypeResolveContext.CacheManager {
158			get {
159				// We don't support caching
160				return null;
161			}
162		}
163		
164		ISynchronizedTypeResolveContext ITypeResolveContext.Synchronize()
165		{
166			// This class is logically immutable
167			return this;
168		}
169		
170		void IDisposable.Dispose()
171		{
172			// exit from Synchronize() block
173		}
174		
175		IEnumerable<IParsedFile> IProjectContent.Files {
176			get { return new IParsedFile[0]; }
177		}
178		
179		void IProjectContent.UpdateProjectContent(IParsedFile oldFile, IParsedFile newFile)
180		{
181			throw new NotSupportedException();
182		}
183		
184		IParsedFile IProjectContent.GetFile(string fileName)
185		{
186			return null;
187		}
188	}
189}