diff options
Diffstat (limited to 'ICSharpCode.Decompiler/Ast/AstBuilder.cs')
-rw-r--r-- | ICSharpCode.Decompiler/Ast/AstBuilder.cs | 1687 |
1 files changed, 0 insertions, 1687 deletions
diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs deleted file mode 100644 index 9a53237a..00000000 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ /dev/null @@ -1,1687 +0,0 @@ -// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team -// -// 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.Concurrent; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Threading; - -using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Ast.Transforms; -using ICSharpCode.Decompiler.ILAst; -using ICSharpCode.NRefactory.CSharp; -using ICSharpCode.NRefactory.Utils; -using Mono.Cecil; -using Mono.Cecil.Cil; - -namespace ICSharpCode.Decompiler.Ast -{ - using Ast = NRefactory.CSharp; - using VarianceModifier = NRefactory.TypeSystem.VarianceModifier; - - [Flags] - public enum ConvertTypeOptions - { - None = 0, - IncludeNamespace = 1, - IncludeTypeParameterDefinitions = 2, - DoNotUsePrimitiveTypeNames = 4 - } - - public class AstBuilder - { - DecompilerContext context; - SyntaxTree syntaxTree = new SyntaxTree(); - Dictionary<string, NamespaceDeclaration> astNamespaces = new Dictionary<string, NamespaceDeclaration>(); - bool transformationsHaveRun; - - public AstBuilder(DecompilerContext context) - { - if (context == null) - throw new ArgumentNullException("context"); - this.context = context; - DecompileMethodBodies = true; - } - - public static bool MemberIsHidden(MemberReference member, DecompilerSettings settings) - { - MethodDefinition method = member as MethodDefinition; - if (method != null) { - if (method.IsGetter || method.IsSetter || method.IsAddOn || method.IsRemoveOn) - return true; - if (settings.AnonymousMethods && method.HasGeneratedName() && method.IsCompilerGenerated()) - return true; - } - - TypeDefinition type = member as TypeDefinition; - if (type != null) { - if (type.DeclaringType != null) { - if (settings.AnonymousMethods && IsClosureType(type)) - return true; - if (settings.YieldReturn && YieldReturnDecompiler.IsCompilerGeneratorEnumerator(type)) - return true; - if (settings.AsyncAwait && AsyncDecompiler.IsCompilerGeneratedStateMachine(type)) - return true; - } else if (type.IsCompilerGenerated()) { - if (type.Name.StartsWith("<PrivateImplementationDetails>", StringComparison.Ordinal)) - return true; - if (type.IsAnonymousType()) - return true; - } - } - - FieldDefinition field = member as FieldDefinition; - if (field != null) { - if (field.IsCompilerGenerated()) { - if (settings.AnonymousMethods && IsAnonymousMethodCacheField(field)) - return true; - if (settings.AutomaticProperties && IsAutomaticPropertyBackingField(field)) - return true; - if (settings.SwitchStatementOnString && IsSwitchOnStringCache(field)) - return true; - } - // event-fields are not [CompilerGenerated] - if (settings.AutomaticEvents && field.DeclaringType.Events.Any(ev => ev.Name == field.Name)) - return true; - } - - return false; - } - - static bool IsSwitchOnStringCache(FieldDefinition field) - { - return field.Name.StartsWith("<>f__switch", StringComparison.Ordinal); - } - - static bool IsAutomaticPropertyBackingField(FieldDefinition field) - { - return field.HasGeneratedName() && field.Name.EndsWith("BackingField", StringComparison.Ordinal); - } - - static bool IsAnonymousMethodCacheField(FieldDefinition field) - { - return field.Name.StartsWith("CS$<>", StringComparison.Ordinal) || field.Name.StartsWith("<>f__am", StringComparison.Ordinal); - } - - static bool IsClosureType(TypeDefinition type) - { - return type.HasGeneratedName() && type.IsCompilerGenerated() && (type.Name.Contains("DisplayClass") || type.Name.Contains("AnonStorey")); - } - - /// <summary> - /// Runs the C# transformations on the compilation unit. - /// </summary> - public void RunTransformations() - { - RunTransformations(null); - } - - public void RunTransformations(Predicate<IAstTransform> transformAbortCondition) - { - TransformationPipeline.RunTransformationsUntil(syntaxTree, transformAbortCondition, context); - transformationsHaveRun = true; - } - - /// <summary> - /// Gets the abstract source tree. - /// </summary> - public SyntaxTree SyntaxTree { - get { return syntaxTree; } - } - - /// <summary> - /// Generates C# code from the abstract source tree. - /// </summary> - public void GenerateCode(ITextOutput output) - { - if (!transformationsHaveRun) - RunTransformations(); - - syntaxTree.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true }); - var outputFormatter = new TextTokenWriter(output, context) { FoldBraces = context.Settings.FoldBraces }; - var formattingPolicy = context.Settings.CSharpFormattingOptions; - syntaxTree.AcceptVisitor(new CSharpOutputVisitor(outputFormatter, formattingPolicy)); - } - - public void AddAssembly(AssemblyDefinition assemblyDefinition, bool onlyAssemblyLevel = false) - { - AddAssembly(assemblyDefinition.MainModule, onlyAssemblyLevel); - } - - public void AddAssembly(ModuleDefinition moduleDefinition, bool onlyAssemblyLevel = false) - { - if (moduleDefinition.Assembly != null && moduleDefinition.Assembly.Name.Version != null) { - syntaxTree.AddChild( - new AttributeSection { - AttributeTarget = "assembly", - Attributes = { - new NRefactory.CSharp.Attribute { - Type = new SimpleType("AssemblyVersion") - .WithAnnotation(new TypeReference( - "System.Reflection", "AssemblyVersionAttribute", - moduleDefinition, moduleDefinition.TypeSystem.Corlib)), - Arguments = { - new PrimitiveExpression(moduleDefinition.Assembly.Name.Version.ToString()) - } - } - } - }, EntityDeclaration.AttributeRole); - } - - if (moduleDefinition.Assembly != null) { - ConvertCustomAttributes(syntaxTree, moduleDefinition.Assembly, "assembly"); - ConvertSecurityAttributes(syntaxTree, moduleDefinition.Assembly, "assembly"); - } - ConvertCustomAttributes(syntaxTree, moduleDefinition, "module"); - AddTypeForwarderAttributes(syntaxTree, moduleDefinition, "assembly"); - - if (!onlyAssemblyLevel) { - foreach (TypeDefinition typeDef in moduleDefinition.Types) { - // Skip the <Module> class - if (typeDef.Name == "<Module>") continue; - // Skip any hidden types - if (MemberIsHidden(typeDef, context.Settings)) - continue; - - AddType(typeDef); - } - } - } - - void AddTypeForwarderAttributes(SyntaxTree astCompileUnit, ModuleDefinition module, string target) - { - if (!module.HasExportedTypes) - return; - foreach (ExportedType type in module.ExportedTypes) { - if (type.IsForwarder) { - var forwardedType = CreateTypeOfExpression(new TypeReference(type.Namespace, type.Name, module, type.Scope)); - astCompileUnit.AddChild( - new AttributeSection { - AttributeTarget = target, - Attributes = { - new NRefactory.CSharp.Attribute { - Type = new SimpleType("TypeForwardedTo") - .WithAnnotation(new TypeReference( - "System.Runtime.CompilerServices", "TypeForwardedToAttribute", - module, module.TypeSystem.Corlib)), - Arguments = { forwardedType } - } - } - }, EntityDeclaration.AttributeRole); - } - } - } - - NamespaceDeclaration GetCodeNamespace(string name) - { - if (string.IsNullOrEmpty(name)) { - return null; - } - if (astNamespaces.ContainsKey(name)) { - return astNamespaces[name]; - } else { - // Create the namespace - NamespaceDeclaration astNamespace = new NamespaceDeclaration { Name = name }; - syntaxTree.Members.Add(astNamespace); - astNamespaces[name] = astNamespace; - return astNamespace; - } - } - - public void AddType(TypeDefinition typeDef) - { - var astType = CreateType(typeDef); - NamespaceDeclaration astNS = GetCodeNamespace(typeDef.Namespace); - if (astNS != null) { - astNS.Members.Add(astType); - } else { - syntaxTree.Members.Add(astType); - } - } - - public void AddMethod(MethodDefinition method) - { - AstNode node = method.IsConstructor ? (AstNode)CreateConstructor(method) : CreateMethod(method); - syntaxTree.Members.Add(node); - } - - public void AddProperty(PropertyDefinition property) - { - syntaxTree.Members.Add(CreateProperty(property)); - } - - public void AddField(FieldDefinition field) - { - syntaxTree.Members.Add(CreateField(field)); - } - - public void AddEvent(EventDefinition ev) - { - syntaxTree.Members.Add(CreateEvent(ev)); - } - - /// <summary> - /// Creates the AST for a type definition. - /// </summary> - /// <param name="typeDef"></param> - /// <returns>TypeDeclaration or DelegateDeclaration.</returns> - public EntityDeclaration CreateType(TypeDefinition typeDef) - { - // create type - TypeDefinition oldCurrentType = context.CurrentType; - context.CurrentType = typeDef; - TypeDeclaration astType = new TypeDeclaration(); - ConvertAttributes(astType, typeDef); - astType.AddAnnotation(typeDef); - astType.Modifiers = ConvertModifiers(typeDef); - astType.Name = CleanName(typeDef.Name); - - if (typeDef.IsEnum) { // NB: Enum is value type - astType.ClassType = ClassType.Enum; - astType.Modifiers &= ~Modifiers.Sealed; - } else if (typeDef.IsValueType) { - astType.ClassType = ClassType.Struct; - astType.Modifiers &= ~Modifiers.Sealed; - } else if (typeDef.IsInterface) { - astType.ClassType = ClassType.Interface; - astType.Modifiers &= ~Modifiers.Abstract; - } else { - astType.ClassType = ClassType.Class; - } - - IEnumerable<GenericParameter> genericParameters = typeDef.GenericParameters; - if (typeDef.DeclaringType != null && typeDef.DeclaringType.HasGenericParameters) - genericParameters = genericParameters.Skip(typeDef.DeclaringType.GenericParameters.Count); - astType.TypeParameters.AddRange(MakeTypeParameters(genericParameters)); - astType.Constraints.AddRange(MakeConstraints(genericParameters)); - - EntityDeclaration result = astType; - if (typeDef.IsEnum) { - long expectedEnumMemberValue = 0; - bool forcePrintingInitializers = IsFlagsEnum(typeDef); - TypeCode baseType = TypeCode.Int32; - foreach (FieldDefinition field in typeDef.Fields) { - if (!field.IsStatic) { - // the value__ field - if (field.FieldType != typeDef.Module.TypeSystem.Int32) { - astType.AddChild(ConvertType(field.FieldType), Roles.BaseType); - baseType = TypeAnalysis.GetTypeCode(field.FieldType); - } - } else { - EnumMemberDeclaration enumMember = new EnumMemberDeclaration(); - enumMember.AddAnnotation(field); - enumMember.Name = CleanName(field.Name); - long memberValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false); - if (forcePrintingInitializers || memberValue != expectedEnumMemberValue) { - enumMember.AddChild(new PrimitiveExpression(CSharpPrimitiveCast.Cast(baseType, field.Constant, false)), EnumMemberDeclaration.InitializerRole); - } - expectedEnumMemberValue = memberValue + 1; - astType.AddChild(enumMember, Roles.TypeMemberRole); - } - } - } else if (typeDef.BaseType != null && typeDef.BaseType.FullName == "System.MulticastDelegate") { - DelegateDeclaration dd = new DelegateDeclaration(); - dd.Modifiers = astType.Modifiers & ~Modifiers.Sealed; - dd.Name = astType.Name; - dd.AddAnnotation(typeDef); - astType.Attributes.MoveTo(dd.Attributes); - astType.TypeParameters.MoveTo(dd.TypeParameters); - astType.Constraints.MoveTo(dd.Constraints); - foreach (var m in typeDef.Methods) { - if (m.Name == "Invoke") { - dd.ReturnType = ConvertType(m.ReturnType, m.MethodReturnType); - dd.Parameters.AddRange(MakeParameters(m)); - ConvertAttributes(dd, m.MethodReturnType, m.Module); - } - } - result = dd; - } else { - // Base type - if (typeDef.BaseType != null && !typeDef.IsValueType && typeDef.BaseType.FullName != "System.Object") { - astType.AddChild(ConvertType(typeDef.BaseType), Roles.BaseType); - } - foreach (var i in typeDef.Interfaces) - astType.AddChild(ConvertType(i), Roles.BaseType); - - AddTypeMembers(astType, typeDef); - - if (astType.Members.OfType<IndexerDeclaration>().Any(idx => idx.PrivateImplementationType.IsNull)) { - // Remove the [DefaultMember] attribute if the class contains indexers - foreach (AttributeSection section in astType.Attributes) { - foreach (Ast.Attribute attr in section.Attributes) { - TypeReference tr = attr.Type.Annotation<TypeReference>(); - if (tr != null && tr.Name == "DefaultMemberAttribute" && tr.Namespace == "System.Reflection") { - attr.Remove(); - } - } - if (section.Attributes.Count == 0) - section.Remove(); - } - } - } - - context.CurrentType = oldCurrentType; - return result; - } - - internal static string CleanName(string name) - { - int pos = name.LastIndexOf('`'); - if (pos >= 0) - name = name.Substring(0, pos); - pos = name.LastIndexOf('.'); - if (pos >= 0) - name = name.Substring(pos + 1); - return name; - } - - #region Create TypeOf Expression - /// <summary> - /// Creates a typeof-expression for the specified type. - /// </summary> - public static TypeOfExpression CreateTypeOfExpression(TypeReference type) - { - return new TypeOfExpression(AddEmptyTypeArgumentsForUnboundGenerics(ConvertType(type))); - } - - static AstType AddEmptyTypeArgumentsForUnboundGenerics(AstType type) - { - TypeReference typeRef = type.Annotation<TypeReference>(); - if (typeRef == null) - return type; - TypeDefinition typeDef = typeRef.Resolve(); // need to resolve to figure out the number of type parameters - if (typeDef == null || !typeDef.HasGenericParameters) - return type; - SimpleType sType = type as SimpleType; - MemberType mType = type as MemberType; - if (sType != null) { - while (typeDef.GenericParameters.Count > sType.TypeArguments.Count) { - sType.TypeArguments.Add(new SimpleType("")); - } - } - - if (mType != null) { - AddEmptyTypeArgumentsForUnboundGenerics(mType.Target); - - int outerTypeParamCount = typeDef.DeclaringType == null ? 0 : typeDef.DeclaringType.GenericParameters.Count; - - while (typeDef.GenericParameters.Count - outerTypeParamCount > mType.TypeArguments.Count) { - mType.TypeArguments.Add(new SimpleType("")); - } - } - - return type; - } - #endregion - - #region Convert Type Reference - /// <summary> - /// Converts a type reference. - /// </summary> - public static AstType ConvertType(TypeReference type, ICustomAttributeProvider typeAttributes = null, ConvertTypeOptions options = ConvertTypeOptions.None) - { - int typeIndex = 0; - return ConvertType(type, typeAttributes, ref typeIndex, options); - } - - static AstType ConvertType(TypeReference type, ICustomAttributeProvider typeAttributes, ref int typeIndex, ConvertTypeOptions options) - { - while (type is OptionalModifierType || type is RequiredModifierType) { - type = ((TypeSpecification)type).ElementType; - } - if (type == null) { - return AstType.Null; - } - - if (type is ByReferenceType) { - typeIndex++; - // by reference type cannot be represented in C#; so we'll represent it as a pointer instead - return ConvertType((type as ByReferenceType).ElementType, typeAttributes, ref typeIndex, options) - .MakePointerType(); - } else if (type is PointerType) { - typeIndex++; - return ConvertType((type as PointerType).ElementType, typeAttributes, ref typeIndex, options) - .MakePointerType(); - } else if (type is ArrayType) { - typeIndex++; - return ConvertType((type as ArrayType).ElementType, typeAttributes, ref typeIndex, options) - .MakeArrayType((type as ArrayType).Rank); - } else if (type is GenericInstanceType) { - GenericInstanceType gType = (GenericInstanceType)type; - if (gType.ElementType.Namespace == "System" && gType.ElementType.Name == "Nullable`1" && gType.GenericArguments.Count == 1) { - typeIndex++; - return new ComposedType { - BaseType = ConvertType(gType.GenericArguments[0], typeAttributes, ref typeIndex, options), - HasNullableSpecifier = true - }; - } - AstType baseType = ConvertType(gType.ElementType, typeAttributes, ref typeIndex, options & ~ConvertTypeOptions.IncludeTypeParameterDefinitions); - List<AstType> typeArguments = new List<AstType>(); - foreach (var typeArgument in gType.GenericArguments) { - typeIndex++; - typeArguments.Add(ConvertType(typeArgument, typeAttributes, ref typeIndex, options)); - } - ApplyTypeArgumentsTo(baseType, typeArguments); - return baseType; - } else if (type is GenericParameter) { - return new SimpleType(type.Name); - } else if (type.IsNested) { - AstType typeRef = ConvertType(type.DeclaringType, typeAttributes, ref typeIndex, options & ~ConvertTypeOptions.IncludeTypeParameterDefinitions); - string namepart = NRefactory.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name); - MemberType memberType = new MemberType { Target = typeRef, MemberName = namepart }; - memberType.AddAnnotation(type); - if ((options & ConvertTypeOptions.IncludeTypeParameterDefinitions) == ConvertTypeOptions.IncludeTypeParameterDefinitions) { - AddTypeParameterDefininitionsTo(type, memberType); - } - return memberType; - } else { - string ns = type.Namespace ?? string.Empty; - string name = type.Name; - if (name == null) - throw new InvalidOperationException("type.Name returned null. Type: " + type.ToString()); - - if (name == "Object" && ns == "System" && HasDynamicAttribute(typeAttributes, typeIndex)) { - return new PrimitiveType("dynamic"); - } else { - if (ns == "System") { - if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames) - != ConvertTypeOptions.DoNotUsePrimitiveTypeNames) { - switch (name) { - case "SByte": - return new PrimitiveType("sbyte"); - case "Int16": - return new PrimitiveType("short"); - case "Int32": - return new PrimitiveType("int"); - case "Int64": - return new PrimitiveType("long"); - case "Byte": - return new PrimitiveType("byte"); - case "UInt16": - return new PrimitiveType("ushort"); - case "UInt32": - return new PrimitiveType("uint"); - case "UInt64": - return new PrimitiveType("ulong"); - case "String": - return new PrimitiveType("string"); - case "Single": - return new PrimitiveType("float"); - case "Double": - return new PrimitiveType("double"); - case "Decimal": - return new PrimitiveType("decimal"); - case "Char": - return new PrimitiveType("char"); - case "Boolean": - return new PrimitiveType("bool"); - case "Void": - return new PrimitiveType("void"); - case "Object": - return new PrimitiveType("object"); - } - } - } - - name = NRefactory.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(name); - - AstType astType; - if ((options & ConvertTypeOptions.IncludeNamespace) == ConvertTypeOptions.IncludeNamespace && ns.Length > 0) { - string[] parts = ns.Split('.'); - AstType nsType = new SimpleType(parts[0]); - for (int i = 1; i < parts.Length; i++) { - nsType = new MemberType { Target = nsType, MemberName = parts[i] }; - } - astType = new MemberType { Target = nsType, MemberName = name }; - } else { - astType = new SimpleType(name); - } - astType.AddAnnotation(type); - - if ((options & ConvertTypeOptions.IncludeTypeParameterDefinitions) == ConvertTypeOptions.IncludeTypeParameterDefinitions) { - AddTypeParameterDefininitionsTo(type, astType); - } - return astType; - } - } - } - - static void AddTypeParameterDefininitionsTo(TypeReference type, AstType astType) - { - if (type.HasGenericParameters) { - List<AstType> typeArguments = new List<AstType>(); - foreach (GenericParameter gp in type.GenericParameters) { - typeArguments.Add(new SimpleType(gp.Name)); - } - ApplyTypeArgumentsTo(astType, typeArguments); - } - } - - static void ApplyTypeArgumentsTo(AstType baseType, List<AstType> typeArguments) - { - SimpleType st = baseType as SimpleType; - if (st != null) { - st.TypeArguments.AddRange(typeArguments); - } - MemberType mt = baseType as MemberType; - if (mt != null) { - TypeReference type = mt.Annotation<TypeReference>(); - if (type != null) { - int typeParameterCount; - NRefactory.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount); - if (typeParameterCount > typeArguments.Count) - typeParameterCount = typeArguments.Count; - mt.TypeArguments.AddRange(typeArguments.GetRange(typeArguments.Count - typeParameterCount, typeParameterCount)); - typeArguments.RemoveRange(typeArguments.Count - typeParameterCount, typeParameterCount); - if (typeArguments.Count > 0) - ApplyTypeArgumentsTo(mt.Target, typeArguments); - } else { - mt.TypeArguments.AddRange(typeArguments); - } - } - } - - const string DynamicAttributeFullName = "System.Runtime.CompilerServices.DynamicAttribute"; - - static bool HasDynamicAttribute(ICustomAttributeProvider attributeProvider, int typeIndex) - { - if (attributeProvider == null || !attributeProvider.HasCustomAttributes) - return false; - foreach (CustomAttribute a in attributeProvider.CustomAttributes) { - if (a.Constructor.DeclaringType.FullName == DynamicAttributeFullName) { - if (a.ConstructorArguments.Count == 1) { - CustomAttributeArgument[] values = a.ConstructorArguments[0].Value as CustomAttributeArgument[]; - if (values != null && typeIndex < values.Length && values[typeIndex].Value is bool) - return (bool)values[typeIndex].Value; - } - return true; - } - } - return false; - } - #endregion - - #region ConvertModifiers - Modifiers ConvertModifiers(TypeDefinition typeDef) - { - Modifiers modifiers = Modifiers.None; - if (typeDef.IsNestedPrivate) - modifiers |= Modifiers.Private; - else if (typeDef.IsNestedAssembly || typeDef.IsNestedFamilyAndAssembly || typeDef.IsNotPublic) - modifiers |= Modifiers.Internal; - else if (typeDef.IsNestedFamily) - modifiers |= Modifiers.Protected; - else if (typeDef.IsNestedFamilyOrAssembly) - modifiers |= Modifiers.Protected | Modifiers.Internal; - else if (typeDef.IsPublic || typeDef.IsNestedPublic) - modifiers |= Modifiers.Public; - - if (typeDef.IsAbstract && typeDef.IsSealed) - modifiers |= Modifiers.Static; - else if (typeDef.IsAbstract) - modifiers |= Modifiers.Abstract; - else if (typeDef.IsSealed) - modifiers |= Modifiers.Sealed; - - return modifiers; - } - - Modifiers ConvertModifiers(FieldDefinition fieldDef) - { - Modifiers modifiers = Modifiers.None; - if (fieldDef.IsPrivate) - modifiers |= Modifiers.Private; - else if (fieldDef.IsAssembly || fieldDef.IsFamilyAndAssembly) - modifiers |= Modifiers.Internal; - else if (fieldDef.IsFamily) - modifiers |= Modifiers.Protected; - else if (fieldDef.IsFamilyOrAssembly) - modifiers |= Modifiers.Protected | Modifiers.Internal; - else if (fieldDef.IsPublic) - modifiers |= Modifiers.Public; - - if (fieldDef.IsLiteral) { - modifiers |= Modifiers.Const; - } else { - if (fieldDef.IsStatic) - modifiers |= Modifiers.Static; - - if (fieldDef.IsInitOnly) - modifiers |= Modifiers.Readonly; - } - - RequiredModifierType modreq = fieldDef.FieldType as RequiredModifierType; - if (modreq != null && modreq.ModifierType.FullName == typeof(IsVolatile).FullName) - modifiers |= Modifiers.Volatile; - - return modifiers; - } - - Modifiers ConvertModifiers(MethodDefinition methodDef) - { - if (methodDef == null) - return Modifiers.None; - Modifiers modifiers = Modifiers.None; - if (methodDef.IsPrivate) - modifiers |= Modifiers.Private; - else if (methodDef.IsAssembly || methodDef.IsFamilyAndAssembly) - modifiers |= Modifiers.Internal; - else if (methodDef.IsFamily) - modifiers |= Modifiers.Protected; - else if (methodDef.IsFamilyOrAssembly) - modifiers |= Modifiers.Protected | Modifiers.Internal; - else if (methodDef.IsPublic) - modifiers |= Modifiers.Public; - - if (methodDef.IsStatic) - modifiers |= Modifiers.Static; - - if (methodDef.IsAbstract) { - modifiers |= Modifiers.Abstract; - if (!methodDef.IsNewSlot) - modifiers |= Modifiers.Override; - } else if (methodDef.IsFinal) { - if (!methodDef.IsNewSlot) { - modifiers |= Modifiers.Sealed | Modifiers.Override; - } - } else if (methodDef.IsVirtual) { - if (methodDef.IsNewSlot) - modifiers |= Modifiers.Virtual; - else - modifiers |= Modifiers.Override; - } - if (!methodDef.HasBody && !methodDef.IsAbstract) - modifiers |= Modifiers.Extern; - - return modifiers; - } - - #endregion - - void AddTypeMembers(TypeDeclaration astType, TypeDefinition typeDef) - { - // Nested types - foreach (TypeDefinition nestedTypeDef in typeDef.NestedTypes) { - if (MemberIsHidden(nestedTypeDef, context.Settings)) - continue; - var nestedType = CreateType(nestedTypeDef); - SetNewModifier(nestedType); - astType.AddChild(nestedType, Roles.TypeMemberRole); - } - - // Add fields - foreach(FieldDefinition fieldDef in typeDef.Fields) { - if (MemberIsHidden(fieldDef, context.Settings)) continue; - astType.AddChild(CreateField(fieldDef), Roles.TypeMemberRole); - } - - // Add events - foreach(EventDefinition eventDef in typeDef.Events) { - astType.AddChild(CreateEvent(eventDef), Roles.TypeMemberRole); - } - - // Add properties - foreach(PropertyDefinition propDef in typeDef.Properties) { - astType.Members.Add(CreateProperty(propDef)); - } - - // Add methods - foreach(MethodDefinition methodDef in typeDef.Methods) { - if (MemberIsHidden(methodDef, context.Settings)) continue; - - if (methodDef.IsConstructor) - astType.Members.Add(CreateConstructor(methodDef)); - else - astType.Members.Add(CreateMethod(methodDef)); - } - } - - EntityDeclaration CreateMethod(MethodDefinition methodDef) - { - MethodDeclaration astMethod = new MethodDeclaration(); - astMethod.AddAnnotation(methodDef); - astMethod.ReturnType = ConvertType(methodDef.ReturnType, methodDef.MethodReturnType); - astMethod.Name = CleanName(methodDef.Name); - astMethod.TypeParameters.AddRange(MakeTypeParameters(methodDef.GenericParameters)); - astMethod.Parameters.AddRange(MakeParameters(methodDef)); - // constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly - if (!methodDef.IsVirtual || (methodDef.IsNewSlot && !methodDef.IsPrivate)) astMethod.Constraints.AddRange(MakeConstraints(methodDef.GenericParameters)); - if (!methodDef.DeclaringType.IsInterface) { - if (IsExplicitInterfaceImplementation(methodDef)) { - astMethod.PrivateImplementationType = ConvertType(methodDef.Overrides.First().DeclaringType); - } else { - astMethod.Modifiers = ConvertModifiers(methodDef); - if (methodDef.IsVirtual == methodDef.IsNewSlot) - SetNewModifier(astMethod); - } - astMethod.Body = CreateMethodBody(methodDef, astMethod.Parameters); - if (context.CurrentMethodIsAsync) { - astMethod.Modifiers |= Modifiers.Async; - context.CurrentMethodIsAsync = false; - } - } - ConvertAttributes(astMethod, methodDef); - if (methodDef.HasCustomAttributes && astMethod.Parameters.Count > 0) { - foreach (CustomAttribute ca in methodDef.CustomAttributes) { - if (ca.AttributeType.Name == "ExtensionAttribute" && ca.AttributeType.Namespace == "System.Runtime.CompilerServices") { - astMethod.Parameters.First().ParameterModifier = ParameterModifier.This; - } - } - } - - // Convert MethodDeclaration to OperatorDeclaration if possible - if (methodDef.IsSpecialName && !methodDef.HasGenericParameters) { - OperatorType? opType = OperatorDeclaration.GetOperatorType(methodDef.Name); - if (opType.HasValue) { - OperatorDeclaration op = new OperatorDeclaration(); - op.CopyAnnotationsFrom(astMethod); - op.ReturnType = astMethod.ReturnType.Detach(); - op.OperatorType = opType.Value; - op.Modifiers = astMethod.Modifiers; - astMethod.Parameters.MoveTo(op.Parameters); - astMethod.Attributes.MoveTo(op.Attributes); - op.Body = astMethod.Body.Detach(); - return op; - } - } - return astMethod; - } - - bool IsExplicitInterfaceImplementation(MethodDefinition methodDef) - { - return methodDef.HasOverrides && methodDef.IsPrivate; - } - - IEnumerable<TypeParameterDeclaration> MakeTypeParameters(IEnumerable<GenericParameter> genericParameters) - { - foreach (var gp in genericParameters) { - TypeParameterDeclaration tp = new TypeParameterDeclaration(); - tp.Name = CleanName(gp.Name); - if (gp.IsContravariant) - tp.Variance = VarianceModifier.Contravariant; - else if (gp.IsCovariant) - tp.Variance = VarianceModifier.Covariant; - ConvertCustomAttributes(tp, gp); - yield return tp; - } - } - - IEnumerable<Constraint> MakeConstraints(IEnumerable<GenericParameter> genericParameters) - { - foreach (var gp in genericParameters) { - Constraint c = new Constraint(); - c.TypeParameter = new SimpleType(CleanName(gp.Name)); - // class/struct must be first - if (gp.HasReferenceTypeConstraint) - c.BaseTypes.Add(new PrimitiveType("class")); - if (gp.HasNotNullableValueTypeConstraint) - c.BaseTypes.Add(new PrimitiveType("struct")); - - foreach (var constraintType in gp.Constraints) { - if (gp.HasNotNullableValueTypeConstraint && constraintType.FullName == "System.ValueType") - continue; - c.BaseTypes.Add(ConvertType(constraintType)); - } - - if (gp.HasDefaultConstructorConstraint && !gp.HasNotNullableValueTypeConstraint) - c.BaseTypes.Add(new PrimitiveType("new")); // new() must be last - if (c.BaseTypes.Any()) - yield return c; - } - } - - ConstructorDeclaration CreateConstructor(MethodDefinition methodDef) - { - ConstructorDeclaration astMethod = new ConstructorDeclaration(); - astMethod.AddAnnotation(methodDef); - astMethod.Modifiers = ConvertModifiers(methodDef); - if (methodDef.IsStatic) { - // don't show visibility for static ctors - astMethod.Modifiers &= ~Modifiers.VisibilityMask; - } - astMethod.Name = CleanName(methodDef.DeclaringType.Name); - astMethod.Parameters.AddRange(MakeParameters(methodDef)); - astMethod.Body = CreateMethodBody(methodDef, astMethod.Parameters); - ConvertAttributes(astMethod, methodDef); - if (methodDef.IsStatic && methodDef.DeclaringType.IsBeforeFieldInit && !astMethod.Body.IsNull) { - astMethod.Body.InsertChildAfter(null, new Comment(" Note: this type is marked as 'beforefieldinit'."), Roles.Comment); - } - return astMethod; - } - - Modifiers FixUpVisibility(Modifiers m) - { - Modifiers v = m & Modifiers.VisibilityMask; - // If any of the modifiers is public, use that - if ((v & Modifiers.Public) == Modifiers.Public) - return Modifiers.Public | (m & ~Modifiers.VisibilityMask); - // If both modifiers are private, no need to fix anything - if (v == Modifiers.Private) - return m; - // Otherwise, use the other modifiers (internal and/or protected) - return m & ~Modifiers.Private; - } - - EntityDeclaration CreateProperty(PropertyDefinition propDef) - { - PropertyDeclaration astProp = new PropertyDeclaration(); - astProp.AddAnnotation(propDef); - var accessor = propDef.GetMethod ?? propDef.SetMethod; - Modifiers getterModifiers = Modifiers.None; - Modifiers setterModifiers = Modifiers.None; - if (IsExplicitInterfaceImplementation(accessor)) { - astProp.PrivateImplementationType = ConvertType(accessor.Overrides.First().DeclaringType); - } else if (!propDef.DeclaringType.IsInterface) { - getterModifiers = ConvertModifiers(propDef.GetMethod); - setterModifiers = ConvertModifiers(propDef.SetMethod); - astProp.Modifiers = FixUpVisibility(getterModifiers | setterModifiers); - try { - if (accessor.IsVirtual && !accessor.IsNewSlot && (propDef.GetMethod == null || propDef.SetMethod == null)) { - foreach (var basePropDef in TypesHierarchyHelpers.FindBaseProperties(propDef)) { - if (basePropDef.GetMethod != null && basePropDef.SetMethod != null) { - var propVisibilityModifiers = ConvertModifiers(basePropDef.GetMethod) | ConvertModifiers(basePropDef.SetMethod); - astProp.Modifiers = FixUpVisibility((astProp.Modifiers & ~Modifiers.VisibilityMask) | (propVisibilityModifiers & Modifiers.VisibilityMask)); - break; - } else if ((basePropDef.GetMethod ?? basePropDef.SetMethod).IsNewSlot) { - break; - } - } - } - } catch (ReferenceResolvingException) { - // TODO: add some kind of notification (a comment?) about possible problems with decompiled code due to unresolved references. - } - } - astProp.Name = CleanName(propDef.Name); - astProp.ReturnType = ConvertType(propDef.PropertyType, propDef); - - if (propDef.GetMethod != null) { - astProp.Getter = new Accessor(); - astProp.Getter.Body = CreateMethodBody(propDef.GetMethod); - astProp.Getter.AddAnnotation(propDef.GetMethod); - ConvertAttributes(astProp.Getter, propDef.GetMethod); - - if ((getterModifiers & Modifiers.VisibilityMask) != (astProp.Modifiers & Modifiers.VisibilityMask)) - astProp.Getter.Modifiers = getterModifiers & Modifiers.VisibilityMask; - } - if (propDef.SetMethod != null) { - astProp.Setter = new Accessor(); - astProp.Setter.Body = CreateMethodBody(propDef.SetMethod); - astProp.Setter.AddAnnotation(propDef.SetMethod); - ConvertAttributes(astProp.Setter, propDef.SetMethod); - ParameterDefinition lastParam = propDef.SetMethod.Parameters.LastOrDefault(); - if (lastParam != null) { - ConvertCustomAttributes(astProp.Setter, lastParam, "param"); - if (lastParam.HasMarshalInfo) { - astProp.Setter.Attributes.Add(new AttributeSection(ConvertMarshalInfo(lastParam, propDef.Module)) { AttributeTarget = "param" }); - } - } - - if ((setterModifiers & Modifiers.VisibilityMask) != (astProp.Modifiers & Modifiers.VisibilityMask)) - astProp.Setter.Modifiers = setterModifiers & Modifiers.VisibilityMask; - } - ConvertCustomAttributes(astProp, propDef); - - EntityDeclaration member = astProp; - if(propDef.IsIndexer()) - member = ConvertPropertyToIndexer(astProp, propDef); - if(!accessor.HasOverrides && !accessor.DeclaringType.IsInterface) - if (accessor.IsVirtual == accessor.IsNewSlot) - SetNewModifier(member); - return member; - } - - IndexerDeclaration ConvertPropertyToIndexer(PropertyDeclaration astProp, PropertyDefinition propDef) - { - var astIndexer = new IndexerDeclaration(); - astIndexer.CopyAnnotationsFrom(astProp); - astProp.Attributes.MoveTo(astIndexer.Attributes); - astIndexer.Modifiers = astProp.Modifiers; - astIndexer.PrivateImplementationType = astProp.PrivateImplementationType.Detach(); - astIndexer.ReturnType = astProp.ReturnType.Detach(); - astIndexer.Getter = astProp.Getter.Detach(); - astIndexer.Setter = astProp.Setter.Detach(); - astIndexer.Parameters.AddRange(MakeParameters(propDef.Parameters)); - return astIndexer; - } - - EntityDeclaration CreateEvent(EventDefinition eventDef) - { - if (eventDef.AddMethod != null && eventDef.AddMethod.IsAbstract) { - // An abstract event cannot be custom - EventDeclaration astEvent = new EventDeclaration(); - ConvertCustomAttributes(astEvent, eventDef); - astEvent.AddAnnotation(eventDef); - astEvent.Variables.Add(new VariableInitializer(CleanName(eventDef.Name))); - astEvent.ReturnType = ConvertType(eventDef.EventType, eventDef); - if (!eventDef.DeclaringType.IsInterface) - astEvent.Modifiers = ConvertModifiers(eventDef.AddMethod); - return astEvent; - } else { - CustomEventDeclaration astEvent = new CustomEventDeclaration(); - ConvertCustomAttributes(astEvent, eventDef); - astEvent.AddAnnotation(eventDef); - astEvent.Name = CleanName(eventDef.Name); - astEvent.ReturnType = ConvertType(eventDef.EventType, eventDef); - if (eventDef.AddMethod == null || !IsExplicitInterfaceImplementation(eventDef.AddMethod)) - astEvent.Modifiers = ConvertModifiers(eventDef.AddMethod); - else - astEvent.PrivateImplementationType = ConvertType(eventDef.AddMethod.Overrides.First().DeclaringType); - - if (eventDef.AddMethod != null) { - astEvent.AddAccessor = new Accessor { - Body = CreateMethodBody(eventDef.AddMethod) - }.WithAnnotation(eventDef.AddMethod); - ConvertAttributes(astEvent.AddAccessor, eventDef.AddMethod); - } - if (eventDef.RemoveMethod != null) { - astEvent.RemoveAccessor = new Accessor { - Body = CreateMethodBody(eventDef.RemoveMethod) - }.WithAnnotation(eventDef.RemoveMethod); - ConvertAttributes(astEvent.RemoveAccessor, eventDef.RemoveMethod); - } - MethodDefinition accessor = eventDef.AddMethod ?? eventDef.RemoveMethod; - if (accessor.IsVirtual == accessor.IsNewSlot) { - SetNewModifier(astEvent); - } - return astEvent; - } - } - - public bool DecompileMethodBodies { get; set; } - - BlockStatement CreateMethodBody(MethodDefinition method, IEnumerable<ParameterDeclaration> parameters = null) - { - if (DecompileMethodBodies) - return AstMethodBodyBuilder.CreateMethodBody(method, context, parameters); - else - return null; - } - - FieldDeclaration CreateField(FieldDefinition fieldDef) - { - FieldDeclaration astField = new FieldDeclaration(); - astField.AddAnnotation(fieldDef); - VariableInitializer initializer = new VariableInitializer(CleanName(fieldDef.Name)); - astField.AddChild(initializer, Roles.Variable); - astField.ReturnType = ConvertType(fieldDef.FieldType, fieldDef); - astField.Modifiers = ConvertModifiers(fieldDef); - if (fieldDef.HasConstant) { - initializer.Initializer = CreateExpressionForConstant(fieldDef.Constant, fieldDef.FieldType, fieldDef.DeclaringType.IsEnum); - } - ConvertAttributes(astField, fieldDef); - SetNewModifier(astField); - return astField; - } - - static Expression CreateExpressionForConstant(object constant, TypeReference type, bool isEnumMemberDeclaration = false) - { - if (constant == null) { - if (type.IsValueType && !(type.Namespace == "System" && type.Name == "Nullable`1")) - return new DefaultValueExpression(ConvertType(type)); - else - return new NullReferenceExpression(); - } else { - TypeCode c = Type.GetTypeCode(constant.GetType()); - if (c >= TypeCode.SByte && c <= TypeCode.UInt64 && !isEnumMemberDeclaration) { - return MakePrimitive((long)CSharpPrimitiveCast.Cast(TypeCode.Int64, constant, false), type); - } else { - return new PrimitiveExpression(constant); - } - } - } - - public static IEnumerable<ParameterDeclaration> MakeParameters(MethodDefinition method, bool isLambda = false) - { - var parameters = MakeParameters(method.Parameters, isLambda); - if (method.CallingConvention == MethodCallingConvention.VarArg) { - return parameters.Concat(new[] { new ParameterDeclaration { Type = new PrimitiveType("__arglist") } }); - } else { - return parameters; - } - } - - public static IEnumerable<ParameterDeclaration> MakeParameters(IEnumerable<ParameterDefinition> paramCol, bool isLambda = false) - { - foreach(ParameterDefinition paramDef in paramCol) { - ParameterDeclaration astParam = new ParameterDeclaration(); - astParam.AddAnnotation(paramDef); - if (!(isLambda && paramDef.ParameterType.ContainsAnonymousType())) - astParam.Type = ConvertType(paramDef.ParameterType, paramDef); - astParam.Name = paramDef.Name; - - if (paramDef.ParameterType is ByReferenceType) { - astParam.ParameterModifier = (!paramDef.IsIn && paramDef.IsOut) ? ParameterModifier.Out : ParameterModifier.Ref; - ComposedType ct = astParam.Type as ComposedType; - if (ct != null && ct.PointerRank > 0) - ct.PointerRank--; - } - - if (paramDef.HasCustomAttributes) { - foreach (CustomAttribute ca in paramDef.CustomAttributes) { - if (ca.AttributeType.Name == "ParamArrayAttribute" && ca.AttributeType.Namespace == "System") - astParam.ParameterModifier = ParameterModifier.Params; - } - } - if (paramDef.IsOptional) { - astParam.DefaultExpression = CreateExpressionForConstant(paramDef.Constant, paramDef.ParameterType); - } - - ConvertCustomAttributes(astParam, paramDef); - ModuleDefinition module = ((MethodDefinition)paramDef.Method).Module; - if (paramDef.HasMarshalInfo) { - astParam.Attributes.Add(new AttributeSection(ConvertMarshalInfo(paramDef, module))); - } - if (astParam.ParameterModifier != ParameterModifier.Out) { - if (paramDef.IsIn) - astParam.Attributes.Add(new AttributeSection(CreateNonCustomAttribute(typeof(InAttribute), module))); - if (paramDef.IsOut) - astParam.Attributes.Add(new AttributeSection(CreateNonCustomAttribute(typeof(OutAttribute), module))); - } - yield return astParam; - } - } - - #region ConvertAttributes - void ConvertAttributes(EntityDeclaration attributedNode, TypeDefinition typeDefinition) - { - ConvertCustomAttributes(attributedNode, typeDefinition); - ConvertSecurityAttributes(attributedNode, typeDefinition); - - // Handle the non-custom attributes: - #region SerializableAttribute - if (typeDefinition.IsSerializable) - attributedNode.Attributes.Add(new AttributeSection(CreateNonCustomAttribute(typeof(SerializableAttribute)))); - #endregion - - #region ComImportAttribute - if (typeDefinition.IsImport) - attributedNode.Attributes.Add(new AttributeSection(CreateNonCustomAttribute(typeof(ComImportAttribute)))); - #endregion - - #region StructLayoutAttribute - LayoutKind layoutKind = LayoutKind.Auto; - switch (typeDefinition.Attributes & TypeAttributes.LayoutMask) { - case TypeAttributes.SequentialLayout: - layoutKind = LayoutKind.Sequential; - break; - case TypeAttributes.ExplicitLayout: - layoutKind = LayoutKind.Explicit; - break; - } - CharSet charSet = CharSet.None; - switch (typeDefinition.Attributes & TypeAttributes.StringFormatMask) { - case TypeAttributes.AnsiClass: - charSet = CharSet.Ansi; - break; - case TypeAttributes.AutoClass: - charSet = CharSet.Auto; - break; - case TypeAttributes.UnicodeClass: - charSet = CharSet.Unicode; - break; - } - LayoutKind defaultLayoutKind = (typeDefinition.IsValueType && !typeDefinition.IsEnum) ? LayoutKind.Sequential: LayoutKind.Auto; - if (layoutKind != defaultLayoutKind || charSet != CharSet.Ansi || typeDefinition.PackingSize > 0 || typeDefinition.ClassSize > 0) { - var structLayout = CreateNonCustomAttribute(typeof(StructLayoutAttribute)); - structLayout.Arguments.Add(new IdentifierExpression("LayoutKind").Member(layoutKind.ToString())); - if (charSet != CharSet.Ansi) { - structLayout.AddNamedArgument("CharSet", new IdentifierExpression("CharSet").Member(charSet.ToString())); - } - if (typeDefinition.PackingSize > 0) { - structLayout.AddNamedArgument("Pack", new PrimitiveExpression((int)typeDefinition.PackingSize)); - } - if (typeDefinition.ClassSize > 0) { - structLayout.AddNamedArgument("Size", new PrimitiveExpression((int)typeDefinition.ClassSize)); - } - attributedNode.Attributes.Add(new AttributeSection(structLayout)); - } - #endregion - } - - void ConvertAttributes(EntityDeclaration attributedNode, MethodDefinition methodDefinition) - { - ConvertCustomAttributes(attributedNode, methodDefinition); - ConvertSecurityAttributes(attributedNode, methodDefinition); - - MethodImplAttributes implAttributes = methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask; - - #region DllImportAttribute - if (methodDefinition.HasPInvokeInfo && methodDefinition.PInvokeInfo != null) { - PInvokeInfo info = methodDefinition.PInvokeInfo; - Ast.Attribute dllImport = CreateNonCustomAttribute(typeof(DllImportAttribute)); - dllImport.Arguments.Add(new PrimitiveExpression(info.Module.Name)); - - if (info.IsBestFitDisabled) - dllImport.AddNamedArgument("BestFitMapping", new PrimitiveExpression(false)); - if (info.IsBestFitEnabled) - dllImport.AddNamedArgument("BestFitMapping", new PrimitiveExpression(true)); - - CallingConvention callingConvention; - switch (info.Attributes & PInvokeAttributes.CallConvMask) { - case PInvokeAttributes.CallConvCdecl: - callingConvention = CallingConvention.Cdecl; - break; - case PInvokeAttributes.CallConvFastcall: - callingConvention = CallingConvention.FastCall; - break; - case PInvokeAttributes.CallConvStdCall: - callingConvention = CallingConvention.StdCall; - break; - case PInvokeAttributes.CallConvThiscall: - callingConvention = CallingConvention.ThisCall; - break; - case PInvokeAttributes.CallConvWinapi: - callingConvention = CallingConvention.Winapi; - break; - default: - throw new NotSupportedException("unknown calling convention"); - } - if (callingConvention != CallingConvention.Winapi) - dllImport.AddNamedArgument("CallingConvention", new IdentifierExpression("CallingConvention").Member(callingConvention.ToString())); - - CharSet charSet = CharSet.None; - switch (info.Attributes & PInvokeAttributes.CharSetMask) { - case PInvokeAttributes.CharSetAnsi: - charSet = CharSet.Ansi; - break; - case PInvokeAttributes.CharSetAuto: - charSet = CharSet.Auto; - break; - case PInvokeAttributes.CharSetUnicode: - charSet = CharSet.Unicode; - break; - } - if (charSet != CharSet.None) - dllImport.AddNamedArgument("CharSet", new IdentifierExpression("CharSet").Member(charSet.ToString())); - - if (!string.IsNullOrEmpty(info.EntryPoint) && info.EntryPoint != methodDefinition.Name) - dllImport.AddNamedArgument("EntryPoint", new PrimitiveExpression(info.EntryPoint)); - - if (info.IsNoMangle) - dllImport.AddNamedArgument("ExactSpelling", new PrimitiveExpression(true)); - - if ((implAttributes & MethodImplAttributes.PreserveSig) == MethodImplAttributes.PreserveSig) - implAttributes &= ~MethodImplAttributes.PreserveSig; - else - dllImport.AddNamedArgument("PreserveSig", new PrimitiveExpression(false)); - - if (info.SupportsLastError) - dllImport.AddNamedArgument("SetLastError", new PrimitiveExpression(true)); - - if (info.IsThrowOnUnmappableCharDisabled) - dllImport.AddNamedArgument("ThrowOnUnmappableChar", new PrimitiveExpression(false)); - if (info.IsThrowOnUnmappableCharEnabled) - dllImport.AddNamedArgument("ThrowOnUnmappableChar", new PrimitiveExpression(true)); - - attributedNode.Attributes.Add(new AttributeSection(dllImport)); - } - #endregion - - #region PreserveSigAttribute - if (implAttributes == MethodImplAttributes.PreserveSig) { - attributedNode.Attributes.Add(new AttributeSection(CreateNonCustomAttribute(typeof(PreserveSigAttribute)))); - implAttributes = 0; - } - #endregion - - #region MethodImplAttribute - if (implAttributes != 0) { - Ast.Attribute methodImpl = CreateNonCustomAttribute(typeof(MethodImplAttribute)); - TypeReference methodImplOptions = new TypeReference( - "System.Runtime.CompilerServices", "MethodImplOptions", - methodDefinition.Module, methodDefinition.Module.TypeSystem.Corlib); - methodImpl.Arguments.Add(MakePrimitive((long)implAttributes, methodImplOptions)); - attributedNode.Attributes.Add(new AttributeSection(methodImpl)); - } - #endregion - - ConvertAttributes(attributedNode, methodDefinition.MethodReturnType, methodDefinition.Module); - } - - void ConvertAttributes(EntityDeclaration attributedNode, MethodReturnType methodReturnType, ModuleDefinition module) - { - ConvertCustomAttributes(attributedNode, methodReturnType, "return"); - if (methodReturnType.HasMarshalInfo) { - var marshalInfo = ConvertMarshalInfo(methodReturnType, module); - attributedNode.Attributes.Add(new AttributeSection(marshalInfo) { AttributeTarget = "return" }); - } - } - - internal static void ConvertAttributes(EntityDeclaration attributedNode, FieldDefinition fieldDefinition, string attributeTarget = null) - { - ConvertCustomAttributes(attributedNode, fieldDefinition); - - #region FieldOffsetAttribute - if (fieldDefinition.HasLayoutInfo) { - Ast.Attribute fieldOffset = CreateNonCustomAttribute(typeof(FieldOffsetAttribute), fieldDefinition.Module); - fieldOffset.Arguments.Add(new PrimitiveExpression(fieldDefinition.Offset)); - attributedNode.Attributes.Add(new AttributeSection(fieldOffset) { AttributeTarget = attributeTarget }); - } - #endregion - - #region NonSerializedAttribute - if (fieldDefinition.IsNotSerialized) { - Ast.Attribute nonSerialized = CreateNonCustomAttribute(typeof(NonSerializedAttribute), fieldDefinition.Module); - attributedNode.Attributes.Add(new AttributeSection(nonSerialized) { AttributeTarget = attributeTarget }); - } - #endregion - - if (fieldDefinition.HasMarshalInfo) { - attributedNode.Attributes.Add(new AttributeSection(ConvertMarshalInfo(fieldDefinition, fieldDefinition.Module)) { AttributeTarget = attributeTarget }); - } - } - - #region MarshalAsAttribute (ConvertMarshalInfo) - static Ast.Attribute ConvertMarshalInfo(IMarshalInfoProvider marshalInfoProvider, ModuleDefinition module) - { - MarshalInfo marshalInfo = marshalInfoProvider.MarshalInfo; - Ast.Attribute attr = CreateNonCustomAttribute(typeof(MarshalAsAttribute), module); - var unmanagedType = new TypeReference("System.Runtime.InteropServices", "UnmanagedType", module, module.TypeSystem.Corlib); - attr.Arguments.Add(MakePrimitive((int)marshalInfo.NativeType, unmanagedType)); - - FixedArrayMarshalInfo fami = marshalInfo as FixedArrayMarshalInfo; - if (fami != null) { - attr.AddNamedArgument("SizeConst", new PrimitiveExpression(fami.Size)); - if (fami.ElementType != NativeType.None) - attr.AddNamedArgument("ArraySubType", MakePrimitive((int)fami.ElementType, unmanagedType)); - } - SafeArrayMarshalInfo sami = marshalInfo as SafeArrayMarshalInfo; - if (sami != null && sami.ElementType != VariantType.None) { - var varEnum = new TypeReference("System.Runtime.InteropServices", "VarEnum", module, module.TypeSystem.Corlib); - attr.AddNamedArgument("SafeArraySubType", MakePrimitive((int)sami.ElementType, varEnum)); - } - ArrayMarshalInfo ami = marshalInfo as ArrayMarshalInfo; - if (ami != null) { - if (ami.ElementType != NativeType.Max) - attr.AddNamedArgument("ArraySubType", MakePrimitive((int)ami.ElementType, unmanagedType)); - if (ami.Size >= 0) - attr.AddNamedArgument("SizeConst", new PrimitiveExpression(ami.Size)); - if (ami.SizeParameterMultiplier != 0 && ami.SizeParameterIndex >= 0) - attr.AddNamedArgument("SizeParamIndex", new PrimitiveExpression(ami.SizeParameterIndex)); - } - CustomMarshalInfo cmi = marshalInfo as CustomMarshalInfo; - if (cmi != null) { - attr.AddNamedArgument("MarshalType", new PrimitiveExpression(cmi.ManagedType.FullName)); - if (!string.IsNullOrEmpty(cmi.Cookie)) - attr.AddNamedArgument("MarshalCookie", new PrimitiveExpression(cmi.Cookie)); - } - FixedSysStringMarshalInfo fssmi = marshalInfo as FixedSysStringMarshalInfo; - if (fssmi != null) { - attr.AddNamedArgument("SizeConst", new PrimitiveExpression(fssmi.Size)); - } - return attr; - } - #endregion - - Ast.Attribute CreateNonCustomAttribute(Type attributeType) - { - return CreateNonCustomAttribute(attributeType, context.CurrentType != null ? context.CurrentType.Module : null); - } - - static Ast.Attribute CreateNonCustomAttribute(Type attributeType, ModuleDefinition module) - { - Debug.Assert(attributeType.Name.EndsWith("Attribute", StringComparison.Ordinal)); - Ast.Attribute attr = new Ast.Attribute(); - attr.Type = new SimpleType(attributeType.Name.Substring(0, attributeType.Name.Length - "Attribute".Length)); - if (module != null) { - attr.Type.AddAnnotation(new TypeReference(attributeType.Namespace, attributeType.Name, module, module.TypeSystem.Corlib)); - } - return attr; - } - - static void ConvertCustomAttributes(AstNode attributedNode, ICustomAttributeProvider customAttributeProvider, string attributeTarget = null) - { - EntityDeclaration entityDecl = attributedNode as EntityDeclaration; - if (customAttributeProvider.HasCustomAttributes) { - var attributes = new List<NRefactory.CSharp.Attribute>(); - foreach (var customAttribute in customAttributeProvider.CustomAttributes.OrderBy(a => a.AttributeType.FullName)) { - if (customAttribute.AttributeType.Name == "ExtensionAttribute" && customAttribute.AttributeType.Namespace == "System.Runtime.CompilerServices") { - // don't show the ExtensionAttribute (it's converted to the 'this' modifier) - continue; - } - if (customAttribute.AttributeType.Name == "ParamArrayAttribute" && customAttribute.AttributeType.Namespace == "System") { - // don't show the ParamArrayAttribute (it's converted to the 'params' modifier) - continue; - } - // if the method is async, remove [DebuggerStepThrough] and [Async - if (entityDecl != null && entityDecl.HasModifier(Modifiers.Async)) { - if (customAttribute.AttributeType.Name == "DebuggerStepThroughAttribute" && customAttribute.AttributeType.Namespace == "System.Diagnostics") { - continue; - } - if (customAttribute.AttributeType.Name == "AsyncStateMachineAttribute" && customAttribute.AttributeType.Namespace == "System.Runtime.CompilerServices") { - continue; - } - } - - var attribute = new NRefactory.CSharp.Attribute(); - attribute.AddAnnotation(customAttribute); - attribute.Type = ConvertType(customAttribute.AttributeType); - attributes.Add(attribute); - - SimpleType st = attribute.Type as SimpleType; - if (st != null && st.Identifier.EndsWith("Attribute", StringComparison.Ordinal)) { - st.Identifier = st.Identifier.Substring(0, st.Identifier.Length - "Attribute".Length); - } - - if(customAttribute.HasConstructorArguments) { - foreach (var parameter in customAttribute.ConstructorArguments) { - Expression parameterValue = ConvertArgumentValue(parameter); - attribute.Arguments.Add(parameterValue); - } - } - if (customAttribute.HasProperties) { - TypeDefinition resolvedAttributeType = customAttribute.AttributeType.Resolve(); - foreach (var propertyNamedArg in customAttribute.Properties) { - var propertyReference = resolvedAttributeType != null ? resolvedAttributeType.Properties.FirstOrDefault(pr => pr.Name == propertyNamedArg.Name) : null; - var propertyName = new IdentifierExpression(propertyNamedArg.Name).WithAnnotation(propertyReference); - var argumentValue = ConvertArgumentValue(propertyNamedArg.Argument); - attribute.Arguments.Add(new AssignmentExpression(propertyName, argumentValue)); - } - } - - if (customAttribute.HasFields) { - TypeDefinition resolvedAttributeType = customAttribute.AttributeType.Resolve(); - foreach (var fieldNamedArg in customAttribute.Fields) { - var fieldReference = resolvedAttributeType != null ? resolvedAttributeType.Fields.FirstOrDefault(f => f.Name == fieldNamedArg.Name) : null; - var fieldName = new IdentifierExpression(fieldNamedArg.Name).WithAnnotation(fieldReference); - var argumentValue = ConvertArgumentValue(fieldNamedArg.Argument); - attribute.Arguments.Add(new AssignmentExpression(fieldName, argumentValue)); - } - } - } - - if (attributeTarget == "module" || attributeTarget == "assembly") { - // use separate section for each attribute - foreach (var attribute in attributes) { - var section = new AttributeSection(); - section.AttributeTarget = attributeTarget; - section.Attributes.Add(attribute); - attributedNode.AddChild(section, EntityDeclaration.AttributeRole); - } - } else if (attributes.Count > 0) { - // use single section for all attributes - var section = new AttributeSection(); - section.AttributeTarget = attributeTarget; - section.Attributes.AddRange(attributes); - attributedNode.AddChild(section, EntityDeclaration.AttributeRole); - } - } - } - - static void ConvertSecurityAttributes(AstNode attributedNode, ISecurityDeclarationProvider secDeclProvider, string attributeTarget = null) - { - if (!secDeclProvider.HasSecurityDeclarations) - return; - var attributes = new List<NRefactory.CSharp.Attribute>(); - foreach (var secDecl in secDeclProvider.SecurityDeclarations.OrderBy(d => d.Action)) { - foreach (var secAttribute in secDecl.SecurityAttributes.OrderBy(a => a.AttributeType.FullName)) { - var attribute = new NRefactory.CSharp.Attribute(); - attribute.AddAnnotation(secAttribute); - attribute.Type = ConvertType(secAttribute.AttributeType); - attributes.Add(attribute); - - SimpleType st = attribute.Type as SimpleType; - if (st != null && st.Identifier.EndsWith("Attribute", StringComparison.Ordinal)) { - st.Identifier = st.Identifier.Substring(0, st.Identifier.Length - "Attribute".Length); - } - - var module = secAttribute.AttributeType.Module; - var securityActionType = new TypeReference("System.Security.Permissions", "SecurityAction", module, module.TypeSystem.Corlib); - attribute.Arguments.Add(MakePrimitive((int)secDecl.Action, securityActionType)); - - if (secAttribute.HasProperties) { - TypeDefinition resolvedAttributeType = secAttribute.AttributeType.Resolve(); - foreach (var propertyNamedArg in secAttribute.Properties) { - var propertyReference = resolvedAttributeType != null ? resolvedAttributeType.Properties.FirstOrDefault(pr => pr.Name == propertyNamedArg.Name) : null; - var propertyName = new IdentifierExpression(propertyNamedArg.Name).WithAnnotation(propertyReference); - var argumentValue = ConvertArgumentValue(propertyNamedArg.Argument); - attribute.Arguments.Add(new AssignmentExpression(propertyName, argumentValue)); - } - } - - if (secAttribute.HasFields) { - TypeDefinition resolvedAttributeType = secAttribute.AttributeType.Resolve(); - foreach (var fieldNamedArg in secAttribute.Fields) { - var fieldReference = resolvedAttributeType != null ? resolvedAttributeType.Fields.FirstOrDefault(f => f.Name == fieldNamedArg.Name) : null; - var fieldName = new IdentifierExpression(fieldNamedArg.Name).WithAnnotation(fieldReference); - var argumentValue = ConvertArgumentValue(fieldNamedArg.Argument); - attribute.Arguments.Add(new AssignmentExpression(fieldName, argumentValue)); - } - } - } - } - if (attributeTarget == "module" || attributeTarget == "assembly") { - // use separate section for each attribute - foreach (var attribute in attributes) { - var section = new AttributeSection(); - section.AttributeTarget = attributeTarget; - section.Attributes.Add(attribute); - attributedNode.AddChild(section, EntityDeclaration.AttributeRole); - } - } else if (attributes.Count > 0) { - // use single section for all attributes - var section = new AttributeSection(); - section.AttributeTarget = attributeTarget; - section.Attributes.AddRange(attributes); - attributedNode.AddChild(section, EntityDeclaration.AttributeRole); - } - } - - static Expression ConvertArgumentValue(CustomAttributeArgument argument) - { - if (argument.Value is CustomAttributeArgument[]) { - ArrayInitializerExpression arrayInit = new ArrayInitializerExpression(); - foreach (CustomAttributeArgument element in (CustomAttributeArgument[])argument.Value) { - arrayInit.Elements.Add(ConvertArgumentValue(element)); - } - ArrayType arrayType = argument.Type as ArrayType; - return new ArrayCreateExpression { - Type = ConvertType(arrayType != null ? arrayType.ElementType : argument.Type), - AdditionalArraySpecifiers = { new ArraySpecifier() }, - Initializer = arrayInit - }; - } else if (argument.Value is CustomAttributeArgument) { - // occurs with boxed arguments - return ConvertArgumentValue((CustomAttributeArgument)argument.Value); - } - var type = argument.Type.Resolve(); - if (type != null && type.IsEnum) { - return MakePrimitive(Convert.ToInt64(argument.Value), type); - } else if (argument.Value is TypeReference) { - return CreateTypeOfExpression((TypeReference)argument.Value); - } else { - return new PrimitiveExpression(argument.Value); - } - } - #endregion - - internal static Expression MakePrimitive(long val, TypeReference type) - { - if (TypeAnalysis.IsBoolean(type) && val == 0) - return new PrimitiveExpression(false); - else if (TypeAnalysis.IsBoolean(type) && val == 1) - return new PrimitiveExpression(true); - else if (val == 0 && type is PointerType) - return new NullReferenceExpression(); - if (type != null) - { // cannot rely on type.IsValueType, it's not set for typerefs (but is set for typespecs) - TypeDefinition enumDefinition = type.Resolve(); - if (enumDefinition != null && enumDefinition.IsEnum) { - TypeCode enumBaseTypeCode = TypeCode.Int32; - foreach (FieldDefinition field in enumDefinition.Fields) { - if (field.IsStatic && Equals(CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false), val)) - return ConvertType(type).Member(field.Name).WithAnnotation(field); - else if (!field.IsStatic) - enumBaseTypeCode = TypeAnalysis.GetTypeCode(field.FieldType); // use primitive type of the enum - } - if (IsFlagsEnum(enumDefinition)) { - long enumValue = val; - Expression expr = null; - long negatedEnumValue = ~val; - // limit negatedEnumValue to the appropriate range - switch (enumBaseTypeCode) { - case TypeCode.Byte: - case TypeCode.SByte: - negatedEnumValue &= byte.MaxValue; - break; - case TypeCode.Int16: - case TypeCode.UInt16: - negatedEnumValue &= ushort.MaxValue; - break; - case TypeCode.Int32: - case TypeCode.UInt32: - negatedEnumValue &= uint.MaxValue; - break; - } - Expression negatedExpr = null; - foreach (FieldDefinition field in enumDefinition.Fields.Where(fld => fld.IsStatic)) { - long fieldValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false); - if (fieldValue == 0) - continue; // skip None enum value - - if ((fieldValue & enumValue) == fieldValue) { - var fieldExpression = ConvertType(type).Member(field.Name).WithAnnotation(field); - if (expr == null) - expr = fieldExpression; - else - expr = new BinaryOperatorExpression(expr, BinaryOperatorType.BitwiseOr, fieldExpression); - - enumValue &= ~fieldValue; - } - if ((fieldValue & negatedEnumValue) == fieldValue) { - var fieldExpression = ConvertType(type).Member(field.Name).WithAnnotation(field); - if (negatedExpr == null) - negatedExpr = fieldExpression; - else - negatedExpr = new BinaryOperatorExpression(negatedExpr, BinaryOperatorType.BitwiseOr, fieldExpression); - - negatedEnumValue &= ~fieldValue; - } - } - if (enumValue == 0 && expr != null) { - if (!(negatedEnumValue == 0 && negatedExpr != null && negatedExpr.Descendants.Count() < expr.Descendants.Count())) { - return expr; - } - } - if (negatedEnumValue == 0 && negatedExpr != null) { - return new UnaryOperatorExpression(UnaryOperatorType.BitNot, negatedExpr); - } - } - return new PrimitiveExpression(CSharpPrimitiveCast.Cast(enumBaseTypeCode, val, false)).CastTo(ConvertType(type)); - } - } - TypeCode code = TypeAnalysis.GetTypeCode(type); - if (code == TypeCode.Object || code == TypeCode.Empty) - code = TypeCode.Int32; - return new PrimitiveExpression(CSharpPrimitiveCast.Cast(code, val, false)); - } - - static bool IsFlagsEnum(TypeDefinition type) - { - if (!type.HasCustomAttributes) - return false; - - return type.CustomAttributes.Any(attr => attr.AttributeType.FullName == "System.FlagsAttribute"); - } - - /// <summary> - /// Sets new modifier if the member hides some other member from a base type. - /// </summary> - /// <param name="member">The node of the member which new modifier state should be determined.</param> - static void SetNewModifier(EntityDeclaration member) - { - try { - bool addNewModifier = false; - if (member is IndexerDeclaration) { - var propertyDef = member.Annotation<PropertyDefinition>(); - var baseProperties = - TypesHierarchyHelpers.FindBaseProperties(propertyDef); - addNewModifier = baseProperties.Any(); - } else - addNewModifier = HidesBaseMember(member); - - if (addNewModifier) - member.Modifiers |= Modifiers.New; - } - catch (ReferenceResolvingException) { - // TODO: add some kind of notification (a comment?) about possible problems with decompiled code due to unresolved references. - } - } - - static bool HidesBaseMember(EntityDeclaration member) - { - var memberDefinition = member.Annotation<IMemberDefinition>(); - bool addNewModifier = false; - var methodDefinition = memberDefinition as MethodDefinition; - if (methodDefinition != null) { - addNewModifier = HidesByName(memberDefinition, includeBaseMethods: false); - if (!addNewModifier) - addNewModifier = TypesHierarchyHelpers.FindBaseMethods(methodDefinition).Any(); - } else - addNewModifier = HidesByName(memberDefinition, includeBaseMethods: true); - return addNewModifier; - } - - /// <summary> - /// Determines whether any base class member has the same name as the given member. - /// </summary> - /// <param name="member">The derived type's member.</param> - /// <param name="includeBaseMethods">true if names of methods declared in base types should also be checked.</param> - /// <returns>true if any base member has the same name as given member, otherwise false.</returns> - static bool HidesByName(IMemberDefinition member, bool includeBaseMethods) - { - Debug.Assert(!(member is PropertyDefinition) || !((PropertyDefinition)member).IsIndexer()); - - if (member.DeclaringType.BaseType != null) { - var baseTypeRef = member.DeclaringType.BaseType; - while (baseTypeRef != null) { -#pragma warning disable 618 - var baseType = baseTypeRef.ResolveOrThrow(); -#pragma warning restore 618 - if (baseType.HasProperties && AnyIsHiddenBy(baseType.Properties, member, m => !m.IsIndexer())) - return true; - if (baseType.HasEvents && AnyIsHiddenBy(baseType.Events, member)) - return true; - if (baseType.HasFields && AnyIsHiddenBy(baseType.Fields, member)) - return true; - if (includeBaseMethods && baseType.HasMethods - && AnyIsHiddenBy(baseType.Methods, member, m => !m.IsSpecialName)) - return true; - if (baseType.HasNestedTypes && AnyIsHiddenBy(baseType.NestedTypes, member)) - return true; - baseTypeRef = baseType.BaseType; - } - } - return false; - } - - static bool AnyIsHiddenBy<T>(IEnumerable<T> members, IMemberDefinition derived, Predicate<T> condition = null) - where T : IMemberDefinition - { - return members.Any(m => m.Name == derived.Name - && (condition == null || condition(m)) - && TypesHierarchyHelpers.IsVisibleFromDerived(m, derived.DeclaringType)); - } - } -} |