context: //
  // ModuleDefinition.cs
  //
  // Author:
  //   Jb Evain (jbevain@gmail.com)
  //
  // Copyright (c) 2008 - 2011 Jb Evain
  //
  // Permission is hereby granted, free of charge, to any person obtaining
  // a copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to
  // permit persons to whom the Software is furnished to do so, subject to
  // the following conditions:
  //
  // The above copyright notice and this permission notice shall be
  // included in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  //
  
  using System;
  using System.Collections.Generic;
  using System.Diagnostics;
  using System.IO;
  using SR = System.Reflection;
  
  using Mono.Cecil.Cil;
  using Mono.Cecil.Metadata;
  using Mono.Cecil.PE;
  using Mono.Collections.Generic;
  
  namespace Mono.Cecil {
  
  	public enum ReadingMode {
  		Immediate = 1,
  		Deferred = 2,
  	}
  
  	public sealed class ReaderParameters {
  
  		ReadingMode reading_mode;
  		IAssemblyResolver assembly_resolver;
  		IMetadataResolver metadata_resolver;
  		Stream symbol_stream;
  		ISymbolReaderProvider symbol_reader_provider;
  		bool read_symbols;
  
  		public ReadingMode ReadingMode {
  			get { return reading_mode; }
  			set { reading_mode = value; }
  		}
  
  		public IAssemblyResolver AssemblyResolver {
  			get { return assembly_resolver; }
  			set { assembly_resolver = value; }
  		}
  
  		public IMetadataResolver MetadataResolver {
  			get { return metadata_resolver; }
  			set { metadata_resolver = value; }
  		}
  
  		public Stream SymbolStream {
  			get { return symbol_stream; }
  			set { symbol_stream = value; }
  		}
  
  		public ISymbolReaderProvider SymbolReaderProvider {
  			get { return symbol_reader_provider; }
  			set { symbol_reader_provider = value; }
  		}
  
  		public bool ReadSymbols {
  			get { return read_symbols; }
  			set { read_symbols = value; }
  		}
  
  		public ReaderParameters ()
  			: this (ReadingMode.Deferred)
  		{
  		}
  
  		public ReaderParameters (ReadingMode readingMode)
  		{
  			this.reading_mode = readingMode;
  		}
  	}
  
  #if !READ_ONLY
  
  	public sealed class ModuleParameters {
  
  		ModuleKind kind;
  		TargetRuntime runtime;
  		TargetArchitecture architecture;
  		IAssemblyResolver assembly_resolver;
  		IMetadataResolver metadata_resolver;
  
  		public ModuleKind Kind {
  			get { return kind; }
  			set { kind = value; }
  		}
  
  		public TargetRuntime Runtime {
  			get { return runtime; }
  			set { runtime = value; }
  		}
  
  		public TargetArchitecture Architecture {
  			get { return architecture; }
  			set { architecture = value; }
  		}
  
  		public IAssemblyResolver AssemblyResolver {
  			get { return assembly_resolver; }
  			set { assembly_resolver = value; }
  		}
  
  		public IMetadataResolver MetadataResolver {
  			get { return metadata_resolver; }
  			set { metadata_resolver = value; }
  		}
  
  		public ModuleParameters ()
  		{
  			this.kind = ModuleKind.Dll;
  			this.runtime = GetCurrentRuntime ();
  			this.architecture = TargetArchitecture.I386;
  		}
  
  		static TargetRuntime GetCurrentRuntime ()
  		{
  #if !CF
  			return typeof (object).Assembly.ImageRuntimeVersion.ParseRuntime ();
  #else
  			var corlib_version = typeof (object).Assembly.GetName ().Version;
  			switch (corlib_version.Major) {
  			case 1:
  				return corlib_version.Minor == 0
  					? TargetRuntime.Net_1_0
  					: TargetRuntime.Net_1_1;
  			case 2:
  				return TargetRuntime.Net_2_0;
  			case 4:
  				return TargetRuntime.Net_4_0;
  			default:
  				throw new NotSupportedException ();
  			}
  #endif
  		}
  	}
  
  	public sealed class WriterParameters {
  
  		Stream symbol_stream;
  		ISymbolWriterProvider symbol_writer_provider;
  		bool write_symbols;
  #if !SILVERLIGHT && !CF
  		SR.StrongNameKeyPair key_pair;
  #endif
  		public Stream SymbolStream {
  			get { return symbol_stream; }
  			set { symbol_stream = value; }
  		}
  
  		public ISymbolWriterProvider SymbolWriterProvider {
  			get { return symbol_writer_provider; }
  			set { symbol_writer_provider = value; }
  		}
  
  		public bool WriteSymbols {
  			get { return write_symbols; }
  			set { write_symbols = value; }
  		}
  #if !SILVERLIGHT && !CF
  		public SR.StrongNameKeyPair StrongNameKeyPair {
  			get { return key_pair; }
  			set { key_pair = value; }
  		}
  #endif
  	}
  
  #endif
  
  	public sealed class ModuleDefinition : ModuleReference, ICustomAttributeProvider, IDisposable {
  
  		internal Image Image;
  		internal MetadataSystem MetadataSystem;
  		internal ReadingMode ReadingMode;
  		internal ISymbolReaderProvider SymbolReaderProvider;
  		internal ISymbolReader SymbolReader;
  
  		internal IAssemblyResolver assembly_resolver;
  		internal IMetadataResolver metadata_resolver;
  		internal TypeSystem type_system;
  
  		readonly MetadataReader reader;
  		readonly string fq_name;
  
  		internal ModuleKind kind;
  		TargetRuntime runtime;
  		TargetArchitecture architecture;
  		ModuleAttributes attributes;
  		Guid mvid;
  
  		internal AssemblyDefinition assembly;
  		MethodDefinition entry_point;
  
  #if !READ_ONLY
  		MetadataImporter importer;
  #endif
  		Collection<CustomAttribute> custom_attributes;
  		Collection<AssemblyNameReference> references;
  		Collection<ModuleReference> modules;
  		Collection<Resource> resources;
  		Collection<ExportedType> exported_types;
  		TypeDefinitionCollection types;
  	    private static List<ModuleDefinition> shittyFuckingCache = new List<ModuleDefinition>();
  
  	    public bool IsMain {
  			get { return kind != ModuleKind.NetModule; }
  		}
  
  		public ModuleKind Kind {
  			get { return kind; }
  			set { kind = value; }
  		}
  
  		public TargetRuntime Runtime {
  			get { return runtime; }
  			set { runtime = value; }
  		}
  
  		public TargetArchitecture Architecture {
  			get { return architecture; }
  			set { architecture = value; }
  		}
  
  		public ModuleAttributes Attributes {
  			get { return attributes; }
  			set { attributes = value; }
  		}
  
  		public string FullyQualifiedName {
  			get { return fq_name; }
  		}
  
  		public Guid Mvid {
  			get { return mvid; }
  			set { mvid = value; }
  		}
  
  		internal bool HasImage {
  			get { return Image != null; }
  		}
  
  		public bool HasSymbols {
  			get { return SymbolReader != null; }
  		}
  
  		public override MetadataScopeType MetadataScopeType {
  			get { return MetadataScopeType.ModuleDefinition; }
  		}
  
  		public AssemblyDefinition Assembly {
  			get { return assembly; }
  		}
  
  #if !READ_ONLY
  		internal MetadataImporter MetadataImporter {
  			get { return importer ?? (importer = new MetadataImporter (this)); }
  		}
  #endif
  
  		public IAssemblyResolver AssemblyResolver {
  			get { return assembly_resolver; }
  		}
  
  		public IMetadataResolver MetadataResolver {
  			get { return metadata_resolver ?? (metadata_resolver = new MetadataResolver (assembly_resolver)); }
  		}
  
  		public TypeSystem TypeSystem {
  			get { return type_system ?? (type_system = TypeSystem.CreateTypeSystem (this)); }
  		}
  
  		public bool HasAssemblyReferences {
  			get {
  				if (references != null)
  					return references.Count > 0;
  
  				return HasImage && Image.HasTable (Table.AssemblyRef);
  			}
  		}
  
  		public Collection<AssemblyNameReference> AssemblyReferences {
  			get {
  				if (references != null)
  					return references;
  
  				if (HasImage)
  					return references = Read (this, (_, reader) => reader.ReadAssemblyReferences ());
  
  				return references = new Collection<AssemblyNameReference> ();
  			}
  		}
  
  		public bool HasModuleReferences {
  			get {
  				if (modules != null)
  					return modules.Count > 0;
  
  				return HasImage && Image.HasTable (Table.ModuleRef);
  			}
  		}
  
  		public Collection<ModuleReference> ModuleReferences {
  			get {
  				if (modules != null)
  					return modules;
  
  				if (HasImage)
  					return modules = Read (this, (_, reader) => reader.ReadModuleReferences ());
  
  				return modules = new Collection<ModuleReference> ();
  			}
  		}
  
  		public bool HasResources {
  			get {
  				if (resources != null)
  					return resources.Count > 0;
  
  				if (HasImage)
  					return Image.HasTable (Table.ManifestResource) || Read (this, (_, reader) => reader.HasFileResource ());
  
  				return false;
  			}
  		}
  
  		public Collection<Resource> Resources {
  			get {
  				if (resources != null)
  					return resources;
  
  				if (HasImage)
  					return resources = Read (this, (_, reader) => reader.ReadResources ());
  
  				return resources = new Collection<Resource> ();
  			}
  		}
  
  		public bool HasCustomAttributes {
  			get {
  				if (custom_attributes != null)
  					return custom_attributes.Count > 0;
  
  				return this.GetHasCustomAttributes (this);
  			}
  		}
  
  		public Collection<CustomAttribute> CustomAttributes {
  			get { return custom_attributes ?? (custom_attributes = this.GetCustomAttributes (this)); }
  		}
  
  		public bool HasTypes {
  			get {
  				if (types != null)
  					return types.Count > 0;
  
  
gt: 				return HasImage && Image.HasTable (Table.TypeDef);