PageRenderTime 125ms CodeModel.GetById 23ms app.highlight 77ms RepoModel.GetById 1ms app.codeStats 1ms

/ICSharpCode.Decompiler/Ast/AstBuilder.cs

http://github.com/icsharpcode/ILSpy
C# | 1700 lines | 1460 code | 153 blank | 87 comment | 569 complexity | 50910808915b0c926ccbcfa8436d2756 MD5 | raw file

Large files files are truncated, but you can click here to view the full 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.Concurrent;
  21using System.Collections.Generic;
  22using System.Collections.ObjectModel;
  23using System.Diagnostics;
  24using System.IO;
  25using System.Linq;
  26using System.Runtime.CompilerServices;
  27using System.Runtime.InteropServices;
  28using System.Threading;
  29
  30using ICSharpCode.Decompiler;
  31using ICSharpCode.Decompiler.Ast.Transforms;
  32using ICSharpCode.Decompiler.ILAst;
  33using ICSharpCode.NRefactory.CSharp;
  34using ICSharpCode.NRefactory.Utils;
  35using Mono.Cecil;
  36using Mono.Cecil.Cil;
  37
  38namespace ICSharpCode.Decompiler.Ast
  39{
  40	using Ast = ICSharpCode.NRefactory.CSharp;
  41	using VarianceModifier = ICSharpCode.NRefactory.TypeSystem.VarianceModifier;
  42	
  43	[Flags]
  44	public enum ConvertTypeOptions
  45	{
  46		None = 0,
  47		IncludeNamespace = 1,
  48		IncludeTypeParameterDefinitions = 2,
  49		DoNotUsePrimitiveTypeNames = 4
  50	}
  51	
  52	public class AstBuilder
  53	{
  54		DecompilerContext context;
  55		SyntaxTree syntaxTree = new SyntaxTree();
  56		Dictionary<string, NamespaceDeclaration> astNamespaces = new Dictionary<string, NamespaceDeclaration>();
  57		bool transformationsHaveRun;
  58		
  59		public AstBuilder(DecompilerContext context)
  60		{
  61			if (context == null)
  62				throw new ArgumentNullException("context");
  63			this.context = context;
  64			this.DecompileMethodBodies = true;
  65		}
  66		
  67		public static bool MemberIsHidden(MemberReference member, DecompilerSettings settings)
  68		{
  69			MethodDefinition method = member as MethodDefinition;
  70			if (method != null) {
  71				if (method.IsGetter || method.IsSetter || method.IsAddOn || method.IsRemoveOn)
  72					return true;
  73				if (settings.AnonymousMethods && method.HasGeneratedName() && method.IsCompilerGenerated())
  74					return true;
  75			}
  76
  77			TypeDefinition type = member as TypeDefinition;
  78			if (type != null) {
  79				if (type.DeclaringType != null) {
  80					if (settings.AnonymousMethods && IsClosureType(type))
  81						return true;
  82					if (settings.YieldReturn && YieldReturnDecompiler.IsCompilerGeneratorEnumerator(type))
  83						return true;
  84					if (settings.AsyncAwait && AsyncDecompiler.IsCompilerGeneratedStateMachine(type))
  85						return true;
  86				} else if (type.IsCompilerGenerated()) {
  87					if (type.Name.StartsWith("<PrivateImplementationDetails>", StringComparison.Ordinal))
  88						return true;
  89					if (type.IsAnonymousType())
  90						return true;
  91				}
  92			}
  93			
  94			FieldDefinition field = member as FieldDefinition;
  95			if (field != null) {
  96				if (field.IsCompilerGenerated()) {
  97					if (settings.AnonymousMethods && IsAnonymousMethodCacheField(field))
  98						return true;
  99					if (settings.AutomaticProperties && IsAutomaticPropertyBackingField(field))
 100						return true;
 101					if (settings.SwitchStatementOnString && IsSwitchOnStringCache(field))
 102						return true;
 103				}
 104				// event-fields are not [CompilerGenerated]
 105				if (settings.AutomaticEvents && field.DeclaringType.Events.Any(ev => ev.Name == field.Name))
 106					return true;
 107			}
 108			
 109			return false;
 110		}
 111
 112		static bool IsSwitchOnStringCache(FieldDefinition field)
 113		{
 114			return field.Name.StartsWith("<>f__switch", StringComparison.Ordinal);
 115		}
 116
 117		static bool IsAutomaticPropertyBackingField(FieldDefinition field)
 118		{
 119			return field.HasGeneratedName() && field.Name.EndsWith("BackingField", StringComparison.Ordinal);
 120		}
 121
 122		static bool IsAnonymousMethodCacheField(FieldDefinition field)
 123		{
 124			return field.Name.StartsWith("CS$<>", StringComparison.Ordinal) || field.Name.StartsWith("<>f__am", StringComparison.Ordinal);
 125		}
 126
 127		static bool IsClosureType(TypeDefinition type)
 128		{
 129			return type.HasGeneratedName() && type.IsCompilerGenerated() && (type.Name.Contains("DisplayClass") || type.Name.Contains("AnonStorey"));
 130		}
 131		
 132		/// <summary>
 133		/// Runs the C# transformations on the compilation unit.
 134		/// </summary>
 135		public void RunTransformations()
 136		{
 137			RunTransformations(null);
 138		}
 139		
 140		public void RunTransformations(Predicate<IAstTransform> transformAbortCondition)
 141		{
 142			TransformationPipeline.RunTransformationsUntil(syntaxTree, transformAbortCondition, context);
 143			transformationsHaveRun = true;
 144		}
 145		
 146		/// <summary>
 147		/// Gets the abstract source tree.
 148		/// </summary>
 149		public SyntaxTree SyntaxTree {
 150			get { return syntaxTree; }
 151		}
 152		
 153		/// <summary>
 154		/// Generates C# code from the abstract source tree.
 155		/// </summary>
 156		/// <remarks>This method adds ParenthesizedExpressions into the AST, and will run transformations if <see cref="RunTransformations"/> was not called explicitly</remarks>
 157		public void GenerateCode(ITextOutput output)
 158		{
 159			if (!transformationsHaveRun)
 160				RunTransformations();
 161			
 162			syntaxTree.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true });
 163			var outputFormatter = new TextTokenWriter(output, context) { FoldBraces = context.Settings.FoldBraces };
 164			var formattingPolicy = context.Settings.CSharpFormattingOptions;
 165			syntaxTree.AcceptVisitor(new CSharpOutputVisitor(outputFormatter, formattingPolicy));
 166		}
 167		
 168		public void AddAssembly(AssemblyDefinition assemblyDefinition, bool onlyAssemblyLevel = false)
 169		{
 170			AddAssembly(assemblyDefinition.MainModule, onlyAssemblyLevel);
 171		}
 172		
 173		public void AddAssembly(ModuleDefinition moduleDefinition, bool onlyAssemblyLevel = false)
 174		{
 175			if (moduleDefinition.Assembly != null && moduleDefinition.Assembly.Name.Version != null) {
 176				syntaxTree.AddChild(
 177					new AttributeSection {
 178						AttributeTarget = "assembly",
 179						Attributes = {
 180							new NRefactory.CSharp.Attribute {
 181								Type = new SimpleType("AssemblyVersion")
 182									.WithAnnotation(new TypeReference(
 183										"System.Reflection", "AssemblyVersionAttribute",
 184										moduleDefinition, moduleDefinition.TypeSystem.CoreLibrary)),
 185								Arguments = {
 186									new PrimitiveExpression(moduleDefinition.Assembly.Name.Version.ToString())
 187								}
 188							}
 189						}
 190					}, EntityDeclaration.AttributeRole);
 191			}
 192			
 193			if (moduleDefinition.Assembly != null) {
 194				ConvertCustomAttributes(syntaxTree, moduleDefinition.Assembly, "assembly");
 195				ConvertSecurityAttributes(syntaxTree, moduleDefinition.Assembly, "assembly");
 196			}
 197			ConvertCustomAttributes(syntaxTree, moduleDefinition, "module");
 198			AddTypeForwarderAttributes(syntaxTree, moduleDefinition, "assembly");
 199			
 200			if (!onlyAssemblyLevel) {
 201				foreach (TypeDefinition typeDef in moduleDefinition.Types) {
 202					// Skip the <Module> class
 203					if (typeDef.Name == "<Module>") continue;
 204					// Skip any hidden types
 205					if (AstBuilder.MemberIsHidden(typeDef, context.Settings))
 206						continue;
 207
 208					AddType(typeDef);
 209				}
 210			}
 211		}
 212		
 213		void AddTypeForwarderAttributes(SyntaxTree astCompileUnit, ModuleDefinition module, string target)
 214		{
 215			if (!module.HasExportedTypes)
 216				return;
 217			foreach (ExportedType type in module.ExportedTypes) {
 218				if (type.IsForwarder) {
 219					var forwardedType = CreateTypeOfExpression(new TypeReference(type.Namespace, type.Name, module, type.Scope));
 220					astCompileUnit.AddChild(
 221						new AttributeSection {
 222							AttributeTarget = target,
 223							Attributes = {
 224								new NRefactory.CSharp.Attribute {
 225									Type = new SimpleType("TypeForwardedTo")
 226										.WithAnnotation(new TypeReference(
 227											"System.Runtime.CompilerServices", "TypeForwardedToAttribute",
 228											module, module.TypeSystem.CoreLibrary)),
 229									Arguments = { forwardedType }
 230								}
 231							}
 232						}, EntityDeclaration.AttributeRole);
 233				}
 234			}
 235		}
 236		
 237		NamespaceDeclaration GetCodeNamespace(string name)
 238		{
 239			if (string.IsNullOrEmpty(name)) {
 240				return null;
 241			}
 242			if (astNamespaces.ContainsKey(name)) {
 243				return astNamespaces[name];
 244			} else {
 245				// Create the namespace
 246				NamespaceDeclaration astNamespace = new NamespaceDeclaration { Name = name };
 247				syntaxTree.Members.Add(astNamespace);
 248				astNamespaces[name] = astNamespace;
 249				return astNamespace;
 250			}
 251		}
 252		
 253		public void AddType(TypeDefinition typeDef)
 254		{
 255			var astType = CreateType(typeDef);
 256			NamespaceDeclaration astNS = GetCodeNamespace(typeDef.Namespace);
 257			if (astNS != null) {
 258				astNS.Members.Add(astType);
 259			} else {
 260				syntaxTree.Members.Add(astType);
 261			}
 262		}
 263		
 264		public void AddMethod(MethodDefinition method)
 265		{
 266			AstNode node = method.IsConstructor ? (AstNode)CreateConstructor(method) : CreateMethod(method);
 267			syntaxTree.Members.Add(node);
 268		}
 269
 270		public void AddProperty(PropertyDefinition property)
 271		{
 272			syntaxTree.Members.Add(CreateProperty(property));
 273		}
 274		
 275		public void AddField(FieldDefinition field)
 276		{
 277			syntaxTree.Members.Add(CreateField(field));
 278		}
 279		
 280		public void AddEvent(EventDefinition ev)
 281		{
 282			syntaxTree.Members.Add(CreateEvent(ev));
 283		}
 284		
 285		/// <summary>
 286		/// Creates the AST for a type definition.
 287		/// </summary>
 288		/// <param name="typeDef"></param>
 289		/// <returns>TypeDeclaration or DelegateDeclaration.</returns>
 290		public EntityDeclaration CreateType(TypeDefinition typeDef)
 291		{
 292			// create type
 293			TypeDefinition oldCurrentType = context.CurrentType;
 294			context.CurrentType = typeDef;
 295			TypeDeclaration astType = new TypeDeclaration();
 296			ConvertAttributes(astType, typeDef);
 297			astType.AddAnnotation(typeDef);
 298			astType.Modifiers = ConvertModifiers(typeDef);
 299			astType.Name = CleanName(typeDef.Name);
 300			
 301			if (typeDef.IsEnum) {  // NB: Enum is value type
 302				astType.ClassType = ClassType.Enum;
 303				astType.Modifiers &= ~Modifiers.Sealed;
 304			} else if (typeDef.IsValueType) {
 305				astType.ClassType = ClassType.Struct;
 306				astType.Modifiers &= ~Modifiers.Sealed;
 307			} else if (typeDef.IsInterface) {
 308				astType.ClassType = ClassType.Interface;
 309				astType.Modifiers &= ~Modifiers.Abstract;
 310			} else {
 311				astType.ClassType = ClassType.Class;
 312			}
 313			
 314			IEnumerable<GenericParameter> genericParameters = typeDef.GenericParameters;
 315			if (typeDef.DeclaringType != null && typeDef.DeclaringType.HasGenericParameters)
 316				genericParameters = genericParameters.Skip(typeDef.DeclaringType.GenericParameters.Count);
 317			astType.TypeParameters.AddRange(MakeTypeParameters(genericParameters));
 318			astType.Constraints.AddRange(MakeConstraints(genericParameters));
 319			
 320			EntityDeclaration result = astType;
 321			if (typeDef.IsEnum) {
 322				long expectedEnumMemberValue = 0;
 323				bool forcePrintingInitializers = IsFlagsEnum(typeDef);
 324				TypeCode baseType = TypeCode.Int32;
 325				foreach (FieldDefinition field in typeDef.Fields) {
 326					if (!field.IsStatic) {
 327						// the value__ field
 328						if (field.FieldType != typeDef.Module.TypeSystem.Int32) {
 329							astType.AddChild(ConvertType(field.FieldType), Roles.BaseType);
 330							baseType = TypeAnalysis.GetTypeCode(field.FieldType);
 331						}
 332					} else {
 333						EnumMemberDeclaration enumMember = new EnumMemberDeclaration();
 334						ConvertCustomAttributes(enumMember, field);
 335						enumMember.AddAnnotation(field);
 336						enumMember.Name = CleanName(field.Name);
 337						long memberValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false);
 338						if (forcePrintingInitializers || memberValue != expectedEnumMemberValue) {
 339							enumMember.AddChild(new PrimitiveExpression(CSharpPrimitiveCast.Cast(baseType, field.Constant, false)), EnumMemberDeclaration.InitializerRole);
 340						}
 341						expectedEnumMemberValue = memberValue + 1;
 342						astType.AddChild(enumMember, Roles.TypeMemberRole);
 343					}
 344				}
 345			} else if (typeDef.BaseType != null && typeDef.BaseType.FullName == "System.MulticastDelegate") {
 346				DelegateDeclaration dd = new DelegateDeclaration();
 347				dd.Modifiers = astType.Modifiers & ~Modifiers.Sealed;
 348				dd.Name = astType.Name;
 349				dd.AddAnnotation(typeDef);
 350				astType.Attributes.MoveTo(dd.Attributes);
 351				astType.TypeParameters.MoveTo(dd.TypeParameters);
 352				astType.Constraints.MoveTo(dd.Constraints);
 353				foreach (var m in typeDef.Methods) {
 354					if (m.Name == "Invoke") {
 355						dd.ReturnType = ConvertType(m.ReturnType, m.MethodReturnType);
 356						dd.Parameters.AddRange(MakeParameters(m));
 357						ConvertAttributes(dd, m.MethodReturnType, m.Module);
 358					}
 359				}
 360				result = dd;
 361			} else {
 362				// Base type
 363				if (typeDef.BaseType != null && !typeDef.IsValueType && typeDef.BaseType.FullName != "System.Object") {
 364					astType.AddChild(ConvertType(typeDef.BaseType), Roles.BaseType);
 365				}
 366				foreach (var i in typeDef.Interfaces)
 367					astType.AddChild(ConvertType(i), Roles.BaseType);
 368				
 369				AddTypeMembers(astType, typeDef);
 370
 371				if (astType.Members.OfType<IndexerDeclaration>().Any(idx => idx.PrivateImplementationType.IsNull)) {
 372					// Remove the [DefaultMember] attribute if the class contains indexers
 373					foreach (AttributeSection section in astType.Attributes) {
 374						foreach (Ast.Attribute attr in section.Attributes) {
 375							TypeReference tr = attr.Type.Annotation<TypeReference>();
 376							if (tr != null && tr.Name == "DefaultMemberAttribute" && tr.Namespace == "System.Reflection") {
 377								attr.Remove();
 378							}
 379						}
 380						if (section.Attributes.Count == 0)
 381							section.Remove();
 382					}
 383				}
 384			}
 385
 386			context.CurrentType = oldCurrentType;
 387			return result;
 388		}
 389
 390		internal static string CleanName(string name)
 391		{
 392			int pos = name.LastIndexOf('`');
 393			if (pos >= 0)
 394				name = name.Substring(0, pos);
 395			pos = name.LastIndexOf('.');
 396			if (pos >= 0)
 397				name = name.Substring(pos + 1);
 398			return name;
 399		}
 400
 401		#region Create TypeOf Expression
 402		/// <summary>
 403		/// Creates a typeof-expression for the specified type.
 404		/// </summary>
 405		public static TypeOfExpression CreateTypeOfExpression(TypeReference type)
 406		{
 407			return new TypeOfExpression(AddEmptyTypeArgumentsForUnboundGenerics(ConvertType(type)));
 408		}
 409		
 410		static AstType AddEmptyTypeArgumentsForUnboundGenerics(AstType type)
 411		{
 412			TypeReference typeRef = type.Annotation<TypeReference>();
 413			if (typeRef == null)
 414				return type;
 415			TypeDefinition typeDef = typeRef.Resolve(); // need to resolve to figure out the number of type parameters
 416			if (typeDef == null || !typeDef.HasGenericParameters)
 417				return type;
 418			SimpleType sType = type as SimpleType;
 419			MemberType mType = type as MemberType;
 420			if (sType != null) {
 421				while (typeDef.GenericParameters.Count > sType.TypeArguments.Count) {
 422					sType.TypeArguments.Add(new SimpleType(""));
 423				}
 424			}
 425			
 426			if (mType != null) {
 427				AddEmptyTypeArgumentsForUnboundGenerics(mType.Target);
 428				
 429				int outerTypeParamCount = typeDef.DeclaringType == null ? 0 : typeDef.DeclaringType.GenericParameters.Count;
 430				
 431				while (typeDef.GenericParameters.Count - outerTypeParamCount > mType.TypeArguments.Count) {
 432					mType.TypeArguments.Add(new SimpleType(""));
 433				}
 434			}
 435			
 436			return type;
 437		}
 438		#endregion
 439		
 440		#region Convert Type Reference
 441		/// <summary>
 442		/// Converts a type reference.
 443		/// </summary>
 444		/// <param name="type">The Cecil type reference that should be converted into
 445		/// a type system type reference.</param>
 446		/// <param name="typeAttributes">Attributes associated with the Cecil type reference.
 447		/// This is used to support the 'dynamic' type.</param>
 448		public static AstType ConvertType(TypeReference type, ICustomAttributeProvider typeAttributes = null, ConvertTypeOptions options = ConvertTypeOptions.None)
 449		{
 450			int typeIndex = 0;
 451			return ConvertType(type, typeAttributes, ref typeIndex, options);
 452		}
 453		
 454		static AstType ConvertType(TypeReference type, ICustomAttributeProvider typeAttributes, ref int typeIndex, ConvertTypeOptions options)
 455		{
 456			while (type is OptionalModifierType || type is RequiredModifierType) {
 457				type = ((TypeSpecification)type).ElementType;
 458			}
 459			if (type == null) {
 460				return AstType.Null;
 461			}
 462			
 463			if (type is Mono.Cecil.ByReferenceType) {
 464				typeIndex++;
 465				// by reference type cannot be represented in C#; so we'll represent it as a pointer instead
 466				return ConvertType((type as Mono.Cecil.ByReferenceType).ElementType, typeAttributes, ref typeIndex, options)
 467					.MakePointerType();
 468			} else if (type is Mono.Cecil.PointerType) {
 469				typeIndex++;
 470				return ConvertType((type as Mono.Cecil.PointerType).ElementType, typeAttributes, ref typeIndex, options)
 471					.MakePointerType();
 472			} else if (type is Mono.Cecil.ArrayType) {
 473				typeIndex++;
 474				return ConvertType((type as Mono.Cecil.ArrayType).ElementType, typeAttributes, ref typeIndex, options)
 475					.MakeArrayType((type as Mono.Cecil.ArrayType).Rank);
 476			} else if (type is GenericInstanceType) {
 477				GenericInstanceType gType = (GenericInstanceType)type;
 478				if (gType.ElementType.Namespace == "System" && gType.ElementType.Name == "Nullable`1" && gType.GenericArguments.Count == 1) {
 479					typeIndex++;
 480					return new ComposedType {
 481						BaseType = ConvertType(gType.GenericArguments[0], typeAttributes, ref typeIndex, options),
 482						HasNullableSpecifier = true
 483					};
 484				}
 485				AstType baseType = ConvertType(gType.ElementType, typeAttributes, ref typeIndex, options & ~ConvertTypeOptions.IncludeTypeParameterDefinitions);
 486				List<AstType> typeArguments = new List<AstType>();
 487				foreach (var typeArgument in gType.GenericArguments) {
 488					typeIndex++;
 489					typeArguments.Add(ConvertType(typeArgument, typeAttributes, ref typeIndex, options));
 490				}
 491				ApplyTypeArgumentsTo(baseType, typeArguments);
 492				return baseType;
 493			} else if (type is GenericParameter) {
 494				return new SimpleType(type.Name);
 495			} else if (type.IsNested) {
 496				AstType typeRef = ConvertType(type.DeclaringType, typeAttributes, ref typeIndex, options & ~ConvertTypeOptions.IncludeTypeParameterDefinitions);
 497				string namepart = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name);
 498				MemberType memberType = new MemberType { Target = typeRef, MemberName = namepart };
 499				memberType.AddAnnotation(type);
 500				if ((options & ConvertTypeOptions.IncludeTypeParameterDefinitions) == ConvertTypeOptions.IncludeTypeParameterDefinitions) {
 501					AddTypeParameterDefininitionsTo(type, memberType);
 502				}
 503				return memberType;
 504			} else {
 505				string ns = type.Namespace ?? string.Empty;
 506				string name = type.Name;
 507				if (name == null)
 508					throw new InvalidOperationException("type.Name returned null. Type: " + type.ToString());
 509				
 510				if (name == "Object" && ns == "System" && HasDynamicAttribute(typeAttributes, typeIndex)) {
 511					return new PrimitiveType("dynamic");
 512				} else {
 513					if (ns == "System") {
 514						if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames)
 515						    != ConvertTypeOptions.DoNotUsePrimitiveTypeNames) {
 516							switch (name) {
 517								case "SByte":
 518									return new PrimitiveType("sbyte");
 519								case "Int16":
 520									return new PrimitiveType("short");
 521								case "Int32":
 522									return new PrimitiveType("int");
 523								case "Int64":
 524									return new PrimitiveType("long");
 525								case "Byte":
 526									return new PrimitiveType("byte");
 527								case "UInt16":
 528									return new PrimitiveType("ushort");
 529								case "UInt32":
 530									return new PrimitiveType("uint");
 531								case "UInt64":
 532									return new PrimitiveType("ulong");
 533								case "String":
 534									return new PrimitiveType("string");
 535								case "Single":
 536									return new PrimitiveType("float");
 537								case "Double":
 538									return new PrimitiveType("double");
 539								case "Decimal":
 540									return new PrimitiveType("decimal");
 541								case "Char":
 542									return new PrimitiveType("char");
 543								case "Boolean":
 544									return new PrimitiveType("bool");
 545								case "Void":
 546									return new PrimitiveType("void");
 547								case "Object":
 548									return new PrimitiveType("object");
 549							}
 550						}
 551					}
 552					
 553					name = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(name);
 554					
 555					AstType astType;
 556					if ((options & ConvertTypeOptions.IncludeNamespace) == ConvertTypeOptions.IncludeNamespace && ns.Length > 0) {
 557						string[] parts = ns.Split('.');
 558						AstType nsType = new SimpleType(parts[0]);
 559						for (int i = 1; i < parts.Length; i++) {
 560							nsType = new MemberType { Target = nsType, MemberName = parts[i] };
 561						}
 562						astType = new MemberType { Target = nsType, MemberName = name };
 563					} else {
 564						astType = new SimpleType(name);
 565					}
 566					astType.AddAnnotation(type);
 567					
 568					if ((options & ConvertTypeOptions.IncludeTypeParameterDefinitions) == ConvertTypeOptions.IncludeTypeParameterDefinitions) {
 569						AddTypeParameterDefininitionsTo(type, astType);
 570					}
 571					return astType;
 572				}
 573			}
 574		}
 575		
 576		static void AddTypeParameterDefininitionsTo(TypeReference type, AstType astType)
 577		{
 578			if (type.HasGenericParameters) {
 579				List<AstType> typeArguments = new List<AstType>();
 580				foreach (GenericParameter gp in type.GenericParameters) {
 581					typeArguments.Add(new SimpleType(gp.Name));
 582				}
 583				ApplyTypeArgumentsTo(astType, typeArguments);
 584			}
 585		}
 586		
 587		static void ApplyTypeArgumentsTo(AstType baseType, List<AstType> typeArguments)
 588		{
 589			SimpleType st = baseType as SimpleType;
 590			if (st != null) {
 591				st.TypeArguments.AddRange(typeArguments);
 592			}
 593			MemberType mt = baseType as MemberType;
 594			if (mt != null) {
 595				TypeReference type = mt.Annotation<TypeReference>();
 596				if (type != null) {
 597					int typeParameterCount;
 598					ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount);
 599					if (typeParameterCount > typeArguments.Count)
 600						typeParameterCount = typeArguments.Count;
 601					mt.TypeArguments.AddRange(typeArguments.GetRange(typeArguments.Count - typeParameterCount, typeParameterCount));
 602					typeArguments.RemoveRange(typeArguments.Count - typeParameterCount, typeParameterCount);
 603					if (typeArguments.Count > 0)
 604						ApplyTypeArgumentsTo(mt.Target, typeArguments);
 605				} else {
 606					mt.TypeArguments.AddRange(typeArguments);
 607				}
 608			}
 609		}
 610		
 611		const string DynamicAttributeFullName = "System.Runtime.CompilerServices.DynamicAttribute";
 612		
 613		static bool HasDynamicAttribute(ICustomAttributeProvider attributeProvider, int typeIndex)
 614		{
 615			if (attributeProvider == null || !attributeProvider.HasCustomAttributes)
 616				return false;
 617			foreach (CustomAttribute a in attributeProvider.CustomAttributes) {
 618				if (a.Constructor.DeclaringType.FullName == DynamicAttributeFullName) {
 619					if (a.ConstructorArguments.Count == 1) {
 620						CustomAttributeArgument[] values = a.ConstructorArguments[0].Value as CustomAttributeArgument[];
 621						if (values != null && typeIndex < values.Length && values[typeIndex].Value is bool)
 622							return (bool)values[typeIndex].Value;
 623					}
 624					return true;
 625				}
 626			}
 627			return false;
 628		}
 629		#endregion
 630		
 631		#region ConvertModifiers
 632		Modifiers ConvertModifiers(TypeDefinition typeDef)
 633		{
 634			Modifiers modifiers = Modifiers.None;
 635			if (typeDef.IsNestedPrivate)
 636				modifiers |= Modifiers.Private;
 637			else if (typeDef.IsNestedAssembly || typeDef.IsNestedFamilyAndAssembly || typeDef.IsNotPublic)
 638				modifiers |= Modifiers.Internal;
 639			else if (typeDef.IsNestedFamily)
 640				modifiers |= Modifiers.Protected;
 641			else if (typeDef.IsNestedFamilyOrAssembly)
 642				modifiers |= Modifiers.Protected | Modifiers.Internal;
 643			else if (typeDef.IsPublic || typeDef.IsNestedPublic)
 644				modifiers |= Modifiers.Public;
 645			
 646			if (typeDef.IsAbstract && typeDef.IsSealed)
 647				modifiers |= Modifiers.Static;
 648			else if (typeDef.IsAbstract)
 649				modifiers |= Modifiers.Abstract;
 650			else if (typeDef.IsSealed)
 651				modifiers |= Modifiers.Sealed;
 652			
 653			return modifiers;
 654		}
 655		
 656		Modifiers ConvertModifiers(FieldDefinition fieldDef)
 657		{
 658			Modifiers modifiers = Modifiers.None;
 659			if (fieldDef.IsPrivate)
 660				modifiers |= Modifiers.Private;
 661			else if (fieldDef.IsAssembly || fieldDef.IsFamilyAndAssembly)
 662				modifiers |= Modifiers.Internal;
 663			else if (fieldDef.IsFamily)
 664				modifiers |= Modifiers.Protected;
 665			else if (fieldDef.IsFamilyOrAssembly)
 666				modifiers |= Modifiers.Protected | Modifiers.Internal;
 667			else if (fieldDef.IsPublic)
 668				modifiers |= Modifiers.Public;
 669			
 670			if (fieldDef.IsLiteral) {
 671				modifiers |= Modifiers.Const;
 672			} else {
 673				if (fieldDef.IsStatic)
 674					modifiers |= Modifiers.Static;
 675				
 676				if (fieldDef.IsInitOnly)
 677					modifiers |= Modifiers.Readonly;
 678			}
 679			
 680			RequiredModifierType modreq = fieldDef.FieldType as RequiredModifierType;
 681			if (modreq != null && modreq.ModifierType.FullName == typeof(IsVolatile).FullName)
 682				modifiers |= Modifiers.Volatile;
 683			
 684			return modifiers;
 685		}
 686		
 687		Modifiers ConvertModifiers(MethodDefinition methodDef)
 688		{
 689			if (methodDef == null)
 690				return Modifiers.None;
 691			Modifiers modifiers = Modifiers.None;
 692			if (methodDef.IsPrivate)
 693				modifiers |= Modifiers.Private;
 694			else if (methodDef.IsAssembly || methodDef.IsFamilyAndAssembly)
 695				modifiers |= Modifiers.Internal;
 696			else if (methodDef.IsFamily)
 697				modifiers |= Modifiers.Protected;
 698			else if (methodDef.IsFamilyOrAssembly)
 699				modifiers |= Modifiers.Protected | Modifiers.Internal;
 700			else if (methodDef.IsPublic)
 701				modifiers |= Modifiers.Public;
 702			
 703			if (methodDef.IsStatic)
 704				modifiers |= Modifiers.Static;
 705			
 706			if (methodDef.IsAbstract) {
 707				modifiers |= Modifiers.Abstract;
 708				if (!methodDef.IsNewSlot)
 709					modifiers |= Modifiers.Override;
 710			} else if (methodDef.IsFinal) {
 711				if (!methodDef.IsNewSlot) {
 712					modifiers |= Modifiers.Sealed | Modifiers.Override;
 713				}
 714			} else if (methodDef.IsVirtual) {
 715				if (methodDef.IsNewSlot)
 716					modifiers |= Modifiers.Virtual;
 717				else
 718					modifiers |= Modifiers.Override;
 719			}
 720			if (!methodDef.HasBody && !methodDef.IsAbstract)
 721				modifiers |= Modifiers.Extern;
 722			
 723			return modifiers;
 724		}
 725
 726		#endregion
 727		
 728		void AddTypeMembers(TypeDeclaration astType, TypeDefinition typeDef)
 729		{
 730			// Nested types
 731			foreach (TypeDefinition nestedTypeDef in typeDef.NestedTypes) {
 732				if (MemberIsHidden(nestedTypeDef, context.Settings))
 733					continue;
 734				var nestedType = CreateType(nestedTypeDef);
 735				SetNewModifier(nestedType);
 736				astType.AddChild(nestedType, Roles.TypeMemberRole);
 737			}
 738			
 739			// Add fields
 740			foreach(FieldDefinition fieldDef in typeDef.Fields) {
 741				if (MemberIsHidden(fieldDef, context.Settings)) continue;
 742				astType.AddChild(CreateField(fieldDef), Roles.TypeMemberRole);
 743			}
 744			
 745			// Add events
 746			foreach(EventDefinition eventDef in typeDef.Events) {
 747				astType.AddChild(CreateEvent(eventDef), Roles.TypeMemberRole);
 748			}
 749
 750			// Add properties
 751			foreach(PropertyDefinition propDef in typeDef.Properties) {
 752				astType.Members.Add(CreateProperty(propDef));
 753			}
 754			
 755			// Add methods
 756			foreach(MethodDefinition methodDef in typeDef.Methods) {
 757				if (MemberIsHidden(methodDef, context.Settings)) continue;
 758				
 759				if (methodDef.IsConstructor)
 760					astType.Members.Add(CreateConstructor(methodDef));
 761				else
 762					astType.Members.Add(CreateMethod(methodDef));
 763			}
 764		}
 765
 766		EntityDeclaration CreateMethod(MethodDefinition methodDef)
 767		{
 768			MethodDeclaration astMethod = new MethodDeclaration();
 769			astMethod.AddAnnotation(methodDef);
 770			astMethod.ReturnType = ConvertType(methodDef.ReturnType, methodDef.MethodReturnType);
 771			astMethod.Name = CleanName(methodDef.Name);
 772			astMethod.TypeParameters.AddRange(MakeTypeParameters(methodDef.GenericParameters));
 773			astMethod.Parameters.AddRange(MakeParameters(methodDef));
 774			bool createMethodBody = false;
 775			// constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly
 776			if (!methodDef.IsVirtual || (methodDef.IsNewSlot && !methodDef.IsPrivate)) astMethod.Constraints.AddRange(MakeConstraints(methodDef.GenericParameters));
 777			if (!methodDef.DeclaringType.IsInterface) {
 778				if (IsExplicitInterfaceImplementation(methodDef)) {
 779					astMethod.PrivateImplementationType = ConvertType(methodDef.Overrides.First().DeclaringType);
 780				} else {
 781					astMethod.Modifiers = ConvertModifiers(methodDef);
 782					if (methodDef.IsVirtual == methodDef.IsNewSlot)
 783						SetNewModifier(astMethod);
 784				}
 785				createMethodBody = true;
 786			} else if (methodDef.IsStatic) {
 787				// decompile static method in interface
 788				astMethod.Modifiers = ConvertModifiers(methodDef);
 789				createMethodBody = true;
 790			}
 791			if (createMethodBody) {
 792				astMethod.Body = CreateMethodBody(methodDef, astMethod.Parameters);
 793				if (context.CurrentMethodIsAsync) {
 794					astMethod.Modifiers |= Modifiers.Async;
 795					context.CurrentMethodIsAsync = false;
 796				}
 797			}
 798			ConvertAttributes(astMethod, methodDef);
 799			if (methodDef.HasCustomAttributes && astMethod.Parameters.Count > 0) {
 800				foreach (CustomAttribute ca in methodDef.CustomAttributes) {
 801					if (ca.AttributeType.Name == "ExtensionAttribute" && ca.AttributeType.Namespace == "System.Runtime.CompilerServices") {
 802						astMethod.Parameters.First().ParameterModifier = ParameterModifier.This;
 803					}
 804				}
 805			}
 806			
 807			// Convert MethodDeclaration to OperatorDeclaration if possible
 808			if (methodDef.IsSpecialName && !methodDef.HasGenericParameters) {
 809				OperatorType? opType = OperatorDeclaration.GetOperatorType(methodDef.Name);
 810				if (opType.HasValue) {
 811					OperatorDeclaration op = new OperatorDeclaration();
 812					op.CopyAnnotationsFrom(astMethod);
 813					op.ReturnType = astMethod.ReturnType.Detach();
 814					op.OperatorType = opType.Value;
 815					op.Modifiers = astMethod.Modifiers;
 816					astMethod.Parameters.MoveTo(op.Parameters);
 817					astMethod.Attributes.MoveTo(op.Attributes);
 818					op.Body = astMethod.Body.Detach();
 819					return op;
 820				}
 821			}
 822			return astMethod;
 823		}
 824		
 825		bool IsExplicitInterfaceImplementation(MethodDefinition methodDef)
 826		{
 827			return methodDef.HasOverrides && methodDef.IsPrivate;
 828		}
 829
 830		IEnumerable<TypeParameterDeclaration> MakeTypeParameters(IEnumerable<GenericParameter> genericParameters)
 831		{
 832			foreach (var gp in genericParameters) {
 833				TypeParameterDeclaration tp = new TypeParameterDeclaration();
 834				tp.Name = CleanName(gp.Name);
 835				if (gp.IsContravariant)
 836					tp.Variance = VarianceModifier.Contravariant;
 837				else if (gp.IsCovariant)
 838					tp.Variance = VarianceModifier.Covariant;
 839				ConvertCustomAttributes(tp, gp);
 840				yield return tp;
 841			}
 842		}
 843		
 844		IEnumerable<Constraint> MakeConstraints(IEnumerable<GenericParameter> genericParameters)
 845		{
 846			foreach (var gp in genericParameters) {
 847				Constraint c = new Constraint();
 848				c.TypeParameter = new SimpleType(CleanName(gp.Name));
 849				// class/struct must be first
 850				if (gp.HasReferenceTypeConstraint)
 851					c.BaseTypes.Add(new PrimitiveType("class"));
 852				if (gp.HasNotNullableValueTypeConstraint)
 853					c.BaseTypes.Add(new PrimitiveType("struct"));
 854				
 855				foreach (var constraintType in gp.Constraints) {
 856					if (gp.HasNotNullableValueTypeConstraint && constraintType.FullName == "System.ValueType")
 857						continue;
 858					c.BaseTypes.Add(ConvertType(constraintType));
 859				}
 860				
 861				if (gp.HasDefaultConstructorConstraint && !gp.HasNotNullableValueTypeConstraint)
 862					c.BaseTypes.Add(new PrimitiveType("new")); // new() must be last
 863				if (c.BaseTypes.Any())
 864					yield return c;
 865			}
 866		}
 867		
 868		ConstructorDeclaration CreateConstructor(MethodDefinition methodDef)
 869		{
 870			ConstructorDeclaration astMethod = new ConstructorDeclaration();
 871			astMethod.AddAnnotation(methodDef);
 872			astMethod.Modifiers = ConvertModifiers(methodDef);
 873			if (methodDef.IsStatic) {
 874				// don't show visibility for static ctors
 875				astMethod.Modifiers &= ~Modifiers.VisibilityMask;
 876			}
 877			astMethod.Name = CleanName(methodDef.DeclaringType.Name);
 878			astMethod.Parameters.AddRange(MakeParameters(methodDef));
 879			astMethod.Body = CreateMethodBody(methodDef, astMethod.Parameters);
 880			ConvertAttributes(astMethod, methodDef);
 881			if (methodDef.IsStatic && methodDef.DeclaringType.IsBeforeFieldInit && !astMethod.Body.IsNull) {
 882				astMethod.Body.InsertChildAfter(null, new Comment(" Note: this type is marked as 'beforefieldinit'."), Roles.Comment);
 883			}
 884			return astMethod;
 885		}
 886
 887		Modifiers FixUpVisibility(Modifiers m)
 888		{
 889			Modifiers v = m & Modifiers.VisibilityMask;
 890			// If any of the modifiers is public, use that
 891			if ((v & Modifiers.Public) == Modifiers.Public)
 892				return Modifiers.Public | (m & ~Modifiers.VisibilityMask);
 893			// If both modifiers are private, no need to fix anything
 894			if (v == Modifiers.Private)
 895				return m;
 896			// Otherwise, use the other modifiers (internal and/or protected)
 897			return m & ~Modifiers.Private;
 898		}
 899
 900		EntityDeclaration CreateProperty(PropertyDefinition propDef)
 901		{
 902			PropertyDeclaration astProp = new PropertyDeclaration();
 903			astProp.AddAnnotation(propDef);
 904			var accessor = propDef.GetMethod ?? propDef.SetMethod;
 905			Modifiers getterModifiers = Modifiers.None;
 906			Modifiers setterModifiers = Modifiers.None;
 907			if (IsExplicitInterfaceImplementation(accessor)) {
 908				astProp.PrivateImplementationType = ConvertType(accessor.Overrides.First().DeclaringType);
 909			} else if (!propDef.DeclaringType.IsInterface) {
 910				getterModifiers = ConvertModifiers(propDef.GetMethod);
 911				setterModifiers = ConvertModifiers(propDef.SetMethod);
 912				astProp.Modifiers = FixUpVisibility(getterModifiers | setterModifiers);
 913				try {
 914					if (accessor.IsVirtual && !accessor.IsNewSlot && (propDef.GetMethod == null || propDef.SetMethod == null)) {
 915						foreach (var basePropDef in TypesHierarchyHelpers.FindBaseProperties(propDef)) {
 916							if (basePropDef.GetMethod != null && basePropDef.SetMethod != null) {
 917								var propVisibilityModifiers = ConvertModifiers(basePropDef.GetMethod) | ConvertModifiers(basePropDef.SetMethod);
 918								astProp.Modifiers = FixUpVisibility((astProp.Modifiers & ~Modifiers.VisibilityMask) | (propVisibilityModifiers & Modifiers.VisibilityMask));
 919								break;
 920							} else if ((basePropDef.GetMethod ?? basePropDef.SetMethod).IsNewSlot) {
 921								break;
 922							}
 923						}
 924					}
 925				} catch (ReferenceResolvingException) {
 926					// TODO: add some kind of notification (a comment?) about possible problems with decompiled code due to unresolved references.
 927				}
 928			}
 929			astProp.Name = CleanName(propDef.Name);
 930			astProp.ReturnType = ConvertType(propDef.PropertyType, propDef);
 931			
 932			if (propDef.GetMethod != null) {
 933				astProp.Getter = new Accessor();
 934				astProp.Getter.Body = CreateMethodBody(propDef.GetMethod);
 935				astProp.Getter.AddAnnotation(propDef.GetMethod);
 936				ConvertAttributes(astProp.Getter, propDef.GetMethod);
 937				
 938				if ((getterModifiers & Modifiers.VisibilityMask) != (astProp.Modifiers & Modifiers.VisibilityMask))
 939					astProp.Getter.Modifiers = getterModifiers & Modifiers.VisibilityMask;
 940			}
 941			if (propDef.SetMethod != null) {
 942				astProp.Setter = new Accessor();
 943				astProp.Setter.Body = CreateMethodBody(propDef.SetMethod);
 944				astProp.Setter.AddAnnotation(propDef.SetMethod);
 945				ConvertAttributes(astProp.Setter, propDef.SetMethod);
 946				ParameterDefinition lastParam = propDef.SetMethod.Parameters.LastOrDefault();
 947				if (lastParam != null) {
 948					ConvertCustomAttributes(astProp.Setter, lastParam, "param");
 949					if (lastParam.HasMarshalInfo) {
 950						astProp.Setter.Attributes.Add(new AttributeSection(ConvertMarshalInfo(lastParam, propDef.Module)) { AttributeTarget = "param" });
 951					}
 952				}
 953				
 954				if ((setterModifiers & Modifiers.VisibilityMask) != (astProp.Modifiers & Modifiers.VisibilityMask))
 955					astProp.Setter.Modifiers = setterModifiers & Modifiers.VisibilityMask;
 956			}
 957			ConvertCustomAttributes(astProp, propDef);
 958
 959			EntityDeclaration member = astProp;
 960			if(propDef.IsIndexer())
 961				member = ConvertPropertyToIndexer(astProp, propDef);
 962			if(!accessor.HasOverrides && !accessor.DeclaringType.IsInterface)
 963				if (accessor.IsVirtual == accessor.IsNewSlot)
 964					SetNewModifier(member);
 965			return member;
 966		}
 967
 968		IndexerDeclaration ConvertPropertyToIndexer(PropertyDeclaration astProp, PropertyDefinition propDef)
 969		{
 970			var astIndexer = new IndexerDeclaration();
 971			astIndexer.CopyAnnotationsFrom(astProp);
 972			astProp.Attributes.MoveTo(astIndexer.Attributes);
 973			astIndexer.Modifiers = astProp.Modifiers;
 974			astIndexer.PrivateImplementationType = astProp.PrivateImplementationType.Detach();
 975			astIndexer.ReturnType = astProp.ReturnType.Detach();
 976			astIndexer.Getter = astProp.Getter.Detach();
 977			astIndexer.Setter = astProp.Setter.Detach();
 978			astIndexer.Parameters.AddRange(MakeParameters(propDef.Parameters));
 979			return astIndexer;
 980		}
 981		
 982		EntityDeclaration CreateEvent(EventDefinition eventDef)
 983		{
 984			if (eventDef.AddMethod != null && eventDef.AddMethod.IsAbstract) {
 985				// An abstract event cannot be custom
 986				EventDeclaration astEvent = new EventDeclaration();
 987				ConvertCustomAttributes(astEvent, eventDef);
 988				astEvent.AddAnnotation(eventDef);
 989				astEvent.Variables.Add(new VariableInitializer(CleanName(eventDef.Name)));
 990				astEvent.ReturnType = ConvertType(eventDef.EventType, eventDef);
 991				if (!eventDef.DeclaringType.IsInterface)
 992					astEvent.Modifiers = ConvertModifiers(eventDef.AddMethod);
 993				return astEvent;
 994			} else {
 995				CustomEventDeclaration astEvent = new CustomEventDeclaration();
 996				ConvertCustomAttributes(astEvent, eventDef);
 997				astEvent.AddAnnotation(eventDef);
 998				astEvent.Name = CleanName(eventDef.Name);
 999				astEvent.ReturnType = ConvertType(eventDef.EventType, eventDef);
1000				if (eventDef.AddMethod == null || !IsExplicitInterfaceImplementation(eventDef.AddMethod))
1001					astEvent.Modifiers = ConvertModifiers(eventDef.AddMethod);
1002				else
1003					astEvent.PrivateImplementationType = ConvertType(eventDef.AddMethod.Overrides.First().DeclaringType);
1004				
1005				if (eventDef.AddMethod != null) {
1006					astEvent.AddAccessor = new Accessor {
1007						Body = CreateMethodBody(eventDef.AddMethod)
1008					}.WithAnnotation(eventDef.AddMethod);
1009					ConvertAttributes(astEvent.AddAccessor, eventDef.AddMethod);
1010				}
1011				if (eventDef.RemoveMethod != null) {
1012					astEvent.RemoveAccessor = new Accessor {
1013						Body = CreateMethodBody(eventDef.RemoveMethod)
1014					}.WithAnnotation(eventDef.RemoveMethod);
1015					ConvertAttributes(astEvent.RemoveAccessor, eventDef.RemoveMethod);
1016				}
1017				MethodDefinition accessor = eventDef.AddMethod ?? eventDef.RemoveMethod;
1018				if (accessor.IsVirtual == accessor.IsNewSlot) {
1019					SetNewModifier(astEvent);
1020				}
1021				return astEvent;
1022			}
1023		}
1024		
1025		public bool DecompileMethodBodies { get; set; }
1026		
1027		BlockStatement CreateMethodBody(MethodDefinition method, IEnumerable<ParameterDeclaration> parameters = null)
1028		{
1029			if (DecompileMethodBodies)
1030				return AstMethodBodyBuilder.CreateMethodBody(method, context, parameters);
1031			else
1032				return null;
1033		}
1034
1035		FieldDeclaration CreateField(FieldDefinition fieldDef)
1036		{
1037			FieldDeclaration astField = new FieldDeclaration();
1038			astField.AddAnnotation(fieldDef);
1039			VariableInitializer initializer = new VariableInitializer(CleanName(fieldDef.Name));
1040			astField.AddChild(initializer, Roles.Variable);
1041			astField.ReturnType = ConvertType(fieldDef.FieldType, fieldDef);
1042			astField.Modifiers = ConvertModifiers(fieldDef);
1043			if (fieldDef.HasConstant) {
1044				initializer.Initializer = CreateExpressionForConstant(fieldDef.Constant, fieldDef.FieldType, fieldDef.DeclaringType.IsEnum);
1045			}
1046			ConvertAttributes(astField, fieldDef);
1047			SetNewModifier(astField);
1048			return astField;
1049		}
1050		
1051		static Expression CreateExpressionForConstant(object constant, TypeReference type, bool isEnumMemberDeclaration = false)
1052		{
1053			if (constant == null) {
1054				if (type.IsValueType && !(type.Namespace == "System" && type.Name == "Nullable`1"))
1055					return new DefaultValueExpression(ConvertType(type));
1056				else
1057					return new NullReferenceExpression();
1058			} else {
1059				TypeCode c = Type.GetTypeCode(constant.GetType());
1060				if (c >= TypeCode.SByte && c <= TypeCode.UInt64 && !isEnumMemberDeclaration) {
1061					return MakePrimitive((long)CSharpPrimitiveCast.Cast(TypeCode.Int64, constant, false), type);
1062				} else {
1063					return new PrimitiveExpression(constant);
1064				}
1065			}
1066		}
1067		
1068		public static IEnumerable<ParameterDeclaration> MakeParameters(MethodDefinition method, bool isLambda = false)
1069		{
1070			var parameters = MakeParameters(method.Parameters, isLambda);
1071			if (method.CallingConvention == MethodCallingConvention.VarArg) {
1072				return parameters.Concat(new[] { new ParameterDeclaration { Type = new PrimitiveType("__arglist") } });
1073			} else {
1074				return parameters;
1075			}
1076		}
1077		
1078		public static IEnumerable<ParameterDeclaration> MakeParameters(IEnumerable<ParameterDefinition> paramCol, bool isLambda = false)
1079		{
1080			foreach(ParameterDefinition paramDef in paramCol) {
1081				ParameterDeclaration astParam = new ParameterDeclaration();
1082				astParam.AddAnnotation(paramDef);
1083				if (!(isLambda && paramDef.ParameterType.ContainsAnonymousType()))
1084					astParam.Type = ConvertType(paramDef.ParameterType, paramDef);
1085				astParam.Name = paramDef.Name;
1086				
1087				if (paramDef.ParameterType is ByReferenceType) {
1088					astParam.ParameterModifier = (!paramDef.IsIn && paramDef.IsOut) ? ParameterModifier.Out : ParameterModifier.Ref;
1089					ComposedType ct = astParam.Type as ComposedType;
1090					if (ct != null && ct.PointerRank > 0)
1091						ct.PointerRank--;
1092				}
1093				
1094				if (paramDef.HasCustomAttributes) {
1095					foreach (CustomAttribute ca in paramDef.CustomAttributes) {
1096						if (ca.AttributeType.Name == "ParamArrayAttribute" && ca.AttributeType.Namespace == "System")
1097							astParam.ParameterModifier = ParameterModifier.Params;
1098					}
1099				}
1100				if (paramDef.IsOptional) {
1101					astParam.DefaultExpression = CreateExpressionForConstant(paramDef.Constant, paramDef.ParameterType);
1102				}
1103				
1104				ConvertCustomAttributes(astParam, paramDef);
1105				ModuleDefinition module = ((MethodDefinition)paramDef.Method).Module;
1106				if (paramDef.HasMarshalInfo) {
1107					astParam.Attributes.Add(new AttributeSection(ConvertMarshalInfo(paramDef, module)));
1108				}
1109				if (astParam.ParameterModifier != ParameterModifier.Out) {
1110					if (paramDef.IsIn)
1111						astParam.Attributes.Add(new AttributeSection(CreateNonCustomAttribute(typeof(InAttribute), module)));
1112					if (paramDef.IsOut)
1113						astParam.Attributes.Add(new AttributeSection(CreateNonCustomAttribute(typeof(OutAttribute), module)));
1114				}
1115				yield return astParam;
1116			}
1117		}
1118		
1119		#region ConvertAttributes
1120		void ConvertAttributes(EntityDeclaration attributedNode, TypeDefinition typeDefinition)
1121		{
1122			ConvertCustomAttributes(attributedNode, typeDefinition);
1123			ConvertSecurityAttributes(attributedNode, typeDefinition);
1124			
1125			// Handle the non-custom attributes:
1126			#region SerializableAttribute
1127			if (typeDefinition.IsSerializable)
1128				attributedNode.Attributes.Add(new AttributeSection(CreateNonCustomAttribute(typeof(SerializableAttribute))));
1129			#endregion
1130			
1131			#region ComImportAttribute
1132			if (typeDefinition.IsImport)
1133				attributedNode.Attributes.Add(new AttributeSection(CreateNonCustomAttribute(typeof(ComImportAttribute))));
1134			#endregion
1135			
1136			#region StructLayoutAttribute
1137			LayoutKind layoutKind = LayoutKind.Auto;
1138			switch (typeDefinition.Attributes & TypeAttributes.LayoutMask) {
1139				case TypeAttributes.SequentialLayout:
1140					layoutKind = LayoutKind.Sequential;
1141					break;
1142				case TypeAttributes.ExplicitLayout:
1143					layoutKind = LayoutKind.Explicit;
1144					break;
1145			}
1146			CharSet charSet = CharSet.None;
1147			switch (typeDefinition.Attributes & TypeAttributes.StringFormatMask) {
1148				case TypeAttributes.AnsiClass:
1149					charSet = CharSet.Ansi;
1150					break;
1151				case TypeAttributes.AutoClass:
1152					charSet = CharSet.Auto;
1153					break;
1154				case TypeAttributes.UnicodeClass:
1155					charSet = CharSet.Unicode;
1156					break;
1157			}
1158			LayoutKind defaultLayoutKind = (typeDefinition.IsValueType && !typeDefinition.IsEnum) ? LayoutKind.Sequential: LayoutKind.Auto;
1159			if (layoutKind != defaultLayoutKind || charSet != CharSet.Ansi || typeDefinition.PackingSize > 0 || typeDefinition.ClassSize > 0) {
1160				var structLayout = CreateNonCustomAttribute(typeof(StructLayoutAttribute));
1161				structLayout.Arguments.Add(new IdentifierExpression("LayoutKind").Member(layoutKind.ToString()));
1162				if (charSet != CharSet.Ansi) {
1163					structLayout.AddNamedArgument("CharSet", new IdentifierExpression("CharSet").Member(charSet.ToString()));
1164				}
1165				if (typeDefinition.PackingSize > 0) {
1166					structLayout.AddNamedArgument("Pack", new PrimitiveExpression((int)typeDefinition.PackingSize));
1167				}
1168				if (typeDefinition.ClassSize > 0) {
1169					structLayout.AddNamedArgument("Size", new PrimitiveExpression((int)typeDefinition.ClassSize));
1170				}
1171				attributedNode.Attributes.Add(new AttributeSection(structLayout));
1172			}
1173			#endregion
1174		}
1175		
1176		void ConvertAttributes(EntityDeclaration attributedNode, MethodDefinition methodDefinition)
1177		{
1178			ConvertCustomAttributes(attributedNode, methodDefinition);
1179			ConvertSecurityAttributes(attributedNode, methodDefinition);
1180			
1181			MethodImplAttributes implAttributes = methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask;
1182			
1183			#region DllImportAttribute
1184			if (methodDefinition.HasPInvokeInfo && methodDefinition.PInvokeInfo != null) {
1185				PInvokeInfo info = methodDefinition.PInvokeInfo;
1186				Ast.Attribute dllImport = CreateNonCustomAttribute(typeof(DllImportAttribute));
1187				dllImport.Arguments.Add(new PrimitiveExpression(info.Module.Name));
1188				
1189				if (info.IsBestFitDisabled)
1190					dllImport.AddNamedArgument("BestFitMapping", new PrimitiveExpression(false));
1191				if (info.IsBestFitEnabled)
1192					dllImport.AddNamedArgument("BestFitMapping", new PrimitiveExpression(true));
1193				
1194				CallingConvention callingConvention;
1195				switch (info.Attributes & PInvokeAttributes.CallConvMask) {
1196					case PInvokeAttributes.CallConvCdecl:
1197						callingConvention = CallingConvention.Cdecl;
1198						break;
1199					case PInvokeAttributes.CallConvFastcall:
1200						callingConvention = CallingConvention.FastCall;
1201						break;
1202					case PInvokeAttributes.CallConvStdCall:
1203						callingConvention = CallingConvention.StdCall;
1204						break;
1205					case PInvokeAttributes.CallConvThiscall:
1206						callingConvention = CallingConvention.ThisCall;
1207						break;
1208					case PInvokeAttributes.CallConvWinapi:
1209						callingConvention = CallingConvention.Winapi;
1210						break;
1211					default:
1212						throw new NotSupportedException("unknown calling convention");
1213				}
1214				if (callingConvention != CallingConvention.Winapi)
1215					dllImport.AddNamedArgument("CallingConvention", new IdentifierExpression("CallingConvention").Member(callingConvention.ToString()));
1216				
1217				CharSet charSet = CharSet.None;
1218				switch (info.Attributes & PInvokeAttributes.CharSetMask) {
1219					case PInvokeAttributes.CharSetAnsi:
1220						charSet = CharSet.Ansi;
1221						break;
1222					case PInvokeAttributes.CharSetAuto:
1223						charSet = CharSet.Auto;
1224						break;
1225					case PInvokeAttributes.CharSetUnicode:
1226						charSet = CharSet.Unicode;
1227						break;
1228				}
1229				if (charSet != CharSet.None)
1230					dllImport.AddNamedArgument("CharSet", new IdentifierExpression("CharSet").Member(charSet.ToString()));
1231				
1232				if (!string.IsNullOrEmpty(info.EntryPoint) && info.EntryPoint != methodDefinition.Name)
1233					dllImport.AddNamedArgument("EntryPoint", new PrimitiveExpression(info.EntryPoint));
1234				
1235				if (info.IsNoMangle)
1236					dllImport.AddNamedArgument("ExactSpelling", new PrimitiveExpression(true));
1237				
1238				if ((implAttributes & MethodImplAttributes.PreserveSig) == MethodImplAttributes.PreserveSig)
1239					implAttributes &= ~MethodImplAttributes.PreserveSig;
1240				else
1241					dllImport.AddNamedArgument("PreserveSig", new PrimitiveExpression(false));
1242				
1243				if (info.SupportsLastError)
1244					dllImport.AddNamedArgument("SetLastError", new PrimitiveExpression(true));
1245				
1246				if (info.IsThrowOnUnmappableCharDisabled)
1247					dllImport.AddNamedArgument("ThrowOnUnmappableChar", new PrimitiveExpression(false));
1248				if (info.IsThrowOnUnmappableCharEnabled)
1249					dllImport.AddNamedArgument("ThrowOnUnmappableChar", new PrimitiveExpression(true));
1250				
1251				attributedNode.Attributes.Add(new AttributeSection(dllImport));
1252			}
1253			#endregion
1254			
1255			#region PreserveSigAttribute
1256			if (implAttributes == MethodImplAttributes.PreserveSig) {
1257				attributedNode.Attributes.Add(new AttributeSection(CreateNonCustomAttribute(typeof(PreserveSigAttribute))));
1258				implAttributes = 0;
1259			}
1260			#endregion
1261			
1262			#region MethodImplAttribute
1263			if (implAttributes != 0) {
1264				Ast.Attribute methodImpl = CreateNonCustomAttribute(typeof(MethodImplAttribute));
1265				TypeReference methodImplOptions = new TypeReference(
1266					"System.Runtime.CompilerServices", "MethodImplOptions",
1267					methodDefinition.Module, methodDefinition.Module.TypeSystem.CoreLibrary);
1268				methodImpl.Arguments.Add(MakePrimitive((long)implAttributes, methodImplOptions));
1269				attributedNode.Attributes.Add(new AttributeSection(methodImpl));
1270			}
1271			#endregion
1272			
1273			ConvertAttributes(attributedNode, methodDefinition.MethodReturnType, methodDefinition.Module);
1274		}
1275		
1276		void ConvertAttributes(EntityDeclaration attributedNode, MethodReturnType methodReturnType, ModuleDefinition module)
1277		{
1278			ConvertCustomAttributes(attributedNode, methodReturnType, "return");
1279			if (methodReturnType.HasMarshalInfo) {
1280				var marshalInfo = ConvertMarshalInfo(methodReturnType, module);
1281				attributedNode.Attributes.Add(new AttributeSection(marshalInfo) { AttributeTarget = "return" });
1282			}
1283		}
1284		
1285		internal static void ConvertAttributes(EntityDeclaration attributedN

Large files files are truncated, but you can click here to view the full file