From 1695474bfc1bf6801ed11c8fb84e7c2e6fdfc8cc Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 2 Sep 2017 14:54:56 +0200 Subject: [PATCH] Delete a bunch of dead code. --- .gitmodules | 1 + ICSharpCode.Decompiler/Ast/AstBuilder.cs | 1700 ----------------- .../Ast/AstMethodBodyBuilder.cs | 1222 ------------ .../Ast/CommentStatement.cs | 69 - .../Ast/DecompilerContext.cs | 57 - ICSharpCode.Decompiler/Ast/NameVariables.cs | 347 ---- ICSharpCode.Decompiler/Ast/TextTokenWriter.cs | 373 ---- .../CSharp/Analysis/ControlFlow.cs | 784 -------- .../Analysis/DefiniteAssignmentAnalysis.cs | 750 -------- .../CompositeResolveVisitorNavigator.cs | 68 - .../Resolver/DetectSkippableNodesNavigator.cs | 88 - .../CSharp/Resolver/FindReferencedEntities.cs | 101 - .../Resolver/IResolveVisitorNavigator.cs | 103 - .../NodeListResolveVisitorNavigator.cs | 77 - .../CSharp/Syntax/ObservableAstVisitor.cs | 864 --------- .../Transforms/PatternStatementTransform.cs | 29 - .../ICSharpCode.Decompiler.csproj | 8 - 17 files changed, 1 insertion(+), 6640 deletions(-) delete mode 100644 ICSharpCode.Decompiler/Ast/AstBuilder.cs delete mode 100644 ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs delete mode 100644 ICSharpCode.Decompiler/Ast/CommentStatement.cs delete mode 100644 ICSharpCode.Decompiler/Ast/DecompilerContext.cs delete mode 100644 ICSharpCode.Decompiler/Ast/NameVariables.cs delete mode 100644 ICSharpCode.Decompiler/Ast/TextTokenWriter.cs delete mode 100644 ICSharpCode.Decompiler/CSharp/Analysis/ControlFlow.cs delete mode 100644 ICSharpCode.Decompiler/CSharp/Analysis/DefiniteAssignmentAnalysis.cs delete mode 100644 ICSharpCode.Decompiler/CSharp/Resolver/CompositeResolveVisitorNavigator.cs delete mode 100644 ICSharpCode.Decompiler/CSharp/Resolver/DetectSkippableNodesNavigator.cs delete mode 100644 ICSharpCode.Decompiler/CSharp/Resolver/FindReferencedEntities.cs delete mode 100644 ICSharpCode.Decompiler/CSharp/Resolver/IResolveVisitorNavigator.cs delete mode 100644 ICSharpCode.Decompiler/CSharp/Resolver/NodeListResolveVisitorNavigator.cs delete mode 100644 ICSharpCode.Decompiler/CSharp/Syntax/ObservableAstVisitor.cs diff --git a/.gitmodules b/.gitmodules index d1593580e..bedfc09b3 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,4 @@ [submodule "ILSpy-tests"] path = ILSpy-tests url = https://github.com/icsharpcode/ILSpy-tests + ignore = all diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs deleted file mode 100644 index 8dbf82cd3..000000000 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ /dev/null @@ -1,1700 +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 = ICSharpCode.NRefactory.CSharp; - using VarianceModifier = ICSharpCode.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 astNamespaces = new Dictionary(); - bool transformationsHaveRun; - - public AstBuilder(DecompilerContext context) - { - if (context == null) - throw new ArgumentNullException("context"); - this.context = context; - this.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("", 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")); - } - - /// - /// Runs the C# transformations on the compilation unit. - /// - public void RunTransformations() - { - RunTransformations(null); - } - - public void RunTransformations(Predicate transformAbortCondition) - { - TransformationPipeline.RunTransformationsUntil(syntaxTree, transformAbortCondition, context); - transformationsHaveRun = true; - } - - /// - /// Gets the abstract source tree. - /// - public SyntaxTree SyntaxTree { - get { return syntaxTree; } - } - - /// - /// Generates C# code from the abstract source tree. - /// - /// This method adds ParenthesizedExpressions into the AST, and will run transformations if was not called explicitly - 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.CoreLibrary)), - 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 class - if (typeDef.Name == "") continue; - // Skip any hidden types - if (AstBuilder.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.CoreLibrary)), - 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)); - } - - /// - /// Creates the AST for a type definition. - /// - /// - /// TypeDeclaration or DelegateDeclaration. - 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 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(); - ConvertCustomAttributes(enumMember, field); - 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().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(); - 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 - /// - /// Creates a typeof-expression for the specified type. - /// - public static TypeOfExpression CreateTypeOfExpression(TypeReference type) - { - return new TypeOfExpression(AddEmptyTypeArgumentsForUnboundGenerics(ConvertType(type))); - } - - static AstType AddEmptyTypeArgumentsForUnboundGenerics(AstType type) - { - TypeReference typeRef = type.Annotation(); - 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 - /// - /// Converts a type reference. - /// - /// The Cecil type reference that should be converted into - /// a type system type reference. - /// Attributes associated with the Cecil type reference. - /// This is used to support the 'dynamic' type. - 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 Mono.Cecil.ByReferenceType) { - typeIndex++; - // by reference type cannot be represented in C#; so we'll represent it as a pointer instead - return ConvertType((type as Mono.Cecil.ByReferenceType).ElementType, typeAttributes, ref typeIndex, options) - .MakePointerType(); - } else if (type is Mono.Cecil.PointerType) { - typeIndex++; - return ConvertType((type as Mono.Cecil.PointerType).ElementType, typeAttributes, ref typeIndex, options) - .MakePointerType(); - } else if (type is Mono.Cecil.ArrayType) { - typeIndex++; - return ConvertType((type as Mono.Cecil.ArrayType).ElementType, typeAttributes, ref typeIndex, options) - .MakeArrayType((type as Mono.Cecil.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 typeArguments = new List(); - 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 = ICSharpCode.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 = ICSharpCode.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 typeArguments = new List(); - foreach (GenericParameter gp in type.GenericParameters) { - typeArguments.Add(new SimpleType(gp.Name)); - } - ApplyTypeArgumentsTo(astType, typeArguments); - } - } - - static void ApplyTypeArgumentsTo(AstType baseType, List 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(); - if (type != null) { - int typeParameterCount; - ICSharpCode.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)); - bool createMethodBody = false; - // 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); - } - createMethodBody = true; - } else if (methodDef.IsStatic) { - // decompile static method in interface - astMethod.Modifiers = ConvertModifiers(methodDef); - createMethodBody = true; - } - if (createMethodBody) { - 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 MakeTypeParameters(IEnumerable 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 MakeConstraints(IEnumerable 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 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 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 MakeParameters(IEnumerable 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.CoreLibrary); - 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.CoreLibrary); - 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.CoreLibrary); - 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.CoreLibrary)); - } - return attr; - } - - static void ConvertCustomAttributes(AstNode attributedNode, ICustomAttributeProvider customAttributeProvider, string attributeTarget = null) - { - EntityDeclaration entityDecl = attributedNode as EntityDeclaration; - if (customAttributeProvider.HasCustomAttributes) { - var attributes = new List(); - 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 ICSharpCode.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(); - foreach (var secDecl in secDeclProvider.SecurityDeclarations.OrderBy(d => d.Action)) { - foreach (var secAttribute in secDecl.SecurityAttributes.OrderBy(a => a.AttributeType.FullName)) { - var attribute = new ICSharpCode.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.CoreLibrary); - 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); - } - } - - private 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) { - long val = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, argument.Value, false); - return MakePrimitive(val, 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 Ast.PrimitiveExpression(false); - else if (TypeAnalysis.IsBoolean(type) && val == 1) - return new Ast.PrimitiveExpression(true); - else if (val == 0 && type is PointerType) - return new Ast.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 && object.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 Ast.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 Ast.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"); - } - - /// - /// Sets new modifier if the member hides some other member from a base type. - /// - /// The node of the member which new modifier state should be determined. - static void SetNewModifier(EntityDeclaration member) - { - try { - bool addNewModifier = false; - if (member is IndexerDeclaration) { - var propertyDef = member.Annotation(); - 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. - } - } - - private static bool HidesBaseMember(EntityDeclaration member) - { - var memberDefinition = member.Annotation(); - 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; - } - - /// - /// Determines whether any base class member has the same name as the given member. - /// - /// The derived type's member. - /// true if names of methods declared in base types should also be checked. - /// true if any base member has the same name as given member, otherwise false. - 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) { - var baseType = baseTypeRef.ResolveOrThrow(); - 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(IEnumerable members, IMemberDefinition derived, Predicate condition = null) - where T : IMemberDefinition - { - return members.Any(m => m.Name == derived.Name - && (condition == null || condition(m)) - && TypesHierarchyHelpers.IsVisibleFromDerived(m, derived.DeclaringType)); - } - } -} diff --git a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs deleted file mode 100644 index a0bb65095..000000000 --- a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs +++ /dev/null @@ -1,1222 +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.Diagnostics; -using System.Linq; -using System.Threading; - -using ICSharpCode.Decompiler.Ast.Transforms; -using ICSharpCode.Decompiler.ILAst; -using ICSharpCode.NRefactory.CSharp; -using ICSharpCode.NRefactory.PatternMatching; -using ICSharpCode.NRefactory.Utils; -using Mono.Cecil; -using Mono.Cecil.Cil; - -namespace ICSharpCode.Decompiler.Ast -{ - using Ast = ICSharpCode.NRefactory.CSharp; - using Cecil = Mono.Cecil; - - public class AstMethodBodyBuilder - { - MethodDefinition methodDef; - TypeSystem typeSystem; - DecompilerContext context; - HashSet localVariablesToDefine = new HashSet(); // local variables that are missing a definition - - /// - /// Creates the body for the method definition. - /// - /// Method definition to decompile. - /// Decompilation context. - /// Parameter declarations of the method being decompiled. - /// These are used to update the parameter names when the decompiler generates names for the parameters. - /// Block for the method body - public static BlockStatement CreateMethodBody(MethodDefinition methodDef, - DecompilerContext context, - IEnumerable parameters = null) - { - MethodDefinition oldCurrentMethod = context.CurrentMethod; - Debug.Assert(oldCurrentMethod == null || oldCurrentMethod == methodDef); - context.CurrentMethod = methodDef; - context.CurrentMethodIsAsync = false; - try { - AstMethodBodyBuilder builder = new AstMethodBodyBuilder(); - builder.methodDef = methodDef; - builder.context = context; - builder.typeSystem = methodDef.Module.TypeSystem; - if (Debugger.IsAttached) { - return builder.CreateMethodBody(parameters); - } else { - try { - return builder.CreateMethodBody(parameters); - } catch (OperationCanceledException) { - throw; - } catch (Exception ex) { - throw new ICSharpCode.Decompiler.DecompilerException(methodDef, ex); - } - } - } finally { - context.CurrentMethod = oldCurrentMethod; - } - } - - public BlockStatement CreateMethodBody(IEnumerable parameters) - { - if (methodDef.Body == null) { - return null; - } - - context.CancellationToken.ThrowIfCancellationRequested(); - ILBlock ilMethod = new ILBlock(); - ILAstBuilder astBuilder = new ILAstBuilder(); - ilMethod.Body = astBuilder.Build(methodDef, true, context); - - context.CancellationToken.ThrowIfCancellationRequested(); - ILAstOptimizer bodyGraph = new ILAstOptimizer(); - bodyGraph.Optimize(context, ilMethod); - context.CancellationToken.ThrowIfCancellationRequested(); - - var localVariables = ilMethod.GetSelfAndChildrenRecursive().Select(e => e.Operand as ILVariable) - .Where(v => v != null && !v.IsParameter).Distinct(); - Debug.Assert(context.CurrentMethod == methodDef); - NameVariables.AssignNamesToVariables(context, astBuilder.Parameters, localVariables, ilMethod); - - if (parameters != null) { - foreach (var pair in (from p in parameters - join v in astBuilder.Parameters on p.Annotation() equals v.OriginalParameter - select new { p, v.Name })) - { - pair.p.Name = pair.Name; - } - } - - context.CancellationToken.ThrowIfCancellationRequested(); - Ast.BlockStatement astBlock = TransformBlock(ilMethod); - CommentStatement.ReplaceAll(astBlock); // convert CommentStatements to Comments - - Statement insertionPoint = astBlock.Statements.FirstOrDefault(); - foreach (ILVariable v in localVariablesToDefine) { - AstType type; - if (v.Type.ContainsAnonymousType()) - type = new SimpleType("var"); - else - type = AstBuilder.ConvertType(v.Type); - var newVarDecl = new VariableDeclarationStatement(type, v.Name); - newVarDecl.Variables.Single().AddAnnotation(v); - astBlock.Statements.InsertBefore(insertionPoint, newVarDecl); - } - - astBlock.AddAnnotation(new MethodDebugSymbols(methodDef) { LocalVariables = localVariables.ToList() }); - - return astBlock; - } - - Ast.BlockStatement TransformBlock(ILBlock block) - { - Ast.BlockStatement astBlock = new BlockStatement(); - if (block != null) { - foreach(ILNode node in block.GetChildren()) { - astBlock.Statements.AddRange(TransformNode(node)); - } - } - return astBlock; - } - - IEnumerable TransformNode(ILNode node) - { - if (node is ILLabel) { - yield return new Ast.LabelStatement { Label = ((ILLabel)node).Name }; - } else if (node is ILExpression) { - List ilRanges = ILRange.OrderAndJoin(node.GetSelfAndChildrenRecursive().SelectMany(e => e.ILRanges)); - AstNode codeExpr = TransformExpression((ILExpression)node); - if (codeExpr != null) { - codeExpr = codeExpr.WithAnnotation(ilRanges); - if (codeExpr is Ast.Expression) { - yield return new Ast.ExpressionStatement { Expression = (Ast.Expression)codeExpr }; - } else if (codeExpr is Ast.Statement) { - yield return (Ast.Statement)codeExpr; - } else { - throw new Exception(); - } - } - } else if (node is ILWhileLoop) { - ILWhileLoop ilLoop = (ILWhileLoop)node; - WhileStatement whileStmt = new WhileStatement() { - Condition = ilLoop.Condition != null ? (Expression)TransformExpression(ilLoop.Condition) : new PrimitiveExpression(true), - EmbeddedStatement = TransformBlock(ilLoop.BodyBlock) - }; - yield return whileStmt; - } else if (node is ILCondition) { - ILCondition conditionalNode = (ILCondition)node; - bool hasFalseBlock = conditionalNode.FalseBlock.EntryGoto != null || conditionalNode.FalseBlock.Body.Count > 0; - yield return new Ast.IfElseStatement { - Condition = (Expression)TransformExpression(conditionalNode.Condition), - TrueStatement = TransformBlock(conditionalNode.TrueBlock), - FalseStatement = hasFalseBlock ? TransformBlock(conditionalNode.FalseBlock) : null - }; - } else if (node is ILSwitch) { - ILSwitch ilSwitch = (ILSwitch)node; - if (TypeAnalysis.IsBoolean(ilSwitch.Condition.InferredType) && ( - from cb in ilSwitch.CaseBlocks - where cb.Values != null - from val in cb.Values - select val - ).Any(val => val != 0 && val != 1)) - { - // If switch cases contain values other then 0 and 1, force the condition to be non-boolean - ilSwitch.Condition.ExpectedType = typeSystem.Int32; - } - SwitchStatement switchStmt = new SwitchStatement() { Expression = (Expression)TransformExpression(ilSwitch.Condition) }; - foreach (var caseBlock in ilSwitch.CaseBlocks) { - SwitchSection section = new SwitchSection(); - if (caseBlock.Values != null) { - section.CaseLabels.AddRange(caseBlock.Values.Select(i => new CaseLabel() { Expression = AstBuilder.MakePrimitive(i, ilSwitch.Condition.ExpectedType ?? ilSwitch.Condition.InferredType) })); - } else { - section.CaseLabels.Add(new CaseLabel()); - } - section.Statements.Add(TransformBlock(caseBlock)); - switchStmt.SwitchSections.Add(section); - } - yield return switchStmt; - } else if (node is ILTryCatchBlock) { - ILTryCatchBlock tryCatchNode = ((ILTryCatchBlock)node); - var tryCatchStmt = new Ast.TryCatchStatement(); - tryCatchStmt.TryBlock = TransformBlock(tryCatchNode.TryBlock); - foreach (var catchClause in tryCatchNode.CatchBlocks) { - if (catchClause.ExceptionVariable == null - && (catchClause.ExceptionType == null || catchClause.ExceptionType.MetadataType == MetadataType.Object)) - { - tryCatchStmt.CatchClauses.Add(new Ast.CatchClause { Body = TransformBlock(catchClause) }); - } else { - tryCatchStmt.CatchClauses.Add( - new Ast.CatchClause { - Type = AstBuilder.ConvertType(catchClause.ExceptionType), - VariableName = catchClause.ExceptionVariable == null ? null : catchClause.ExceptionVariable.Name, - Body = TransformBlock(catchClause) - }.WithAnnotation(catchClause.ExceptionVariable)); - } - } - if (tryCatchNode.FinallyBlock != null) - tryCatchStmt.FinallyBlock = TransformBlock(tryCatchNode.FinallyBlock); - if (tryCatchNode.FaultBlock != null) { - CatchClause cc = new CatchClause(); - cc.Body = TransformBlock(tryCatchNode.FaultBlock); - cc.Body.Add(new ThrowStatement()); // rethrow - tryCatchStmt.CatchClauses.Add(cc); - } - yield return tryCatchStmt; - } else if (node is ILFixedStatement) { - ILFixedStatement fixedNode = (ILFixedStatement)node; - FixedStatement fixedStatement = new FixedStatement(); - foreach (ILExpression initializer in fixedNode.Initializers) { - Debug.Assert(initializer.Code == ILCode.Stloc); - ILVariable v = (ILVariable)initializer.Operand; - fixedStatement.Variables.Add( - new VariableInitializer { - Name = v.Name, - Initializer = (Expression)TransformExpression(initializer.Arguments[0]) - }.WithAnnotation(v)); - } - fixedStatement.Type = AstBuilder.ConvertType(((ILVariable)fixedNode.Initializers[0].Operand).Type); - fixedStatement.EmbeddedStatement = TransformBlock(fixedNode.BodyBlock); - yield return fixedStatement; - } else if (node is ILBlock) { - yield return TransformBlock((ILBlock)node); - } else { - throw new Exception("Unknown node type"); - } - } - - AstNode TransformExpression(ILExpression expr) - { - AstNode node = TransformByteCode(expr); - Expression astExpr = node as Expression; - - // get IL ranges - used in debugger - List ilRanges = ILRange.OrderAndJoin(expr.GetSelfAndChildrenRecursive().SelectMany(e => e.ILRanges)); - AstNode result; - - if (astExpr != null) - result = Convert(astExpr, expr.InferredType, expr.ExpectedType); - else - result = node; - - if (result != null) - result = result.WithAnnotation(new TypeInformation(expr.InferredType, expr.ExpectedType)); - - if (result != null) - return result.WithAnnotation(ilRanges); - - return result; - } - - AstNode TransformByteCode(ILExpression byteCode) - { - object operand = byteCode.Operand; - AstType operandAsTypeRef = AstBuilder.ConvertType(operand as Cecil.TypeReference); - - List args = new List(); - foreach(ILExpression arg in byteCode.Arguments) { - args.Add((Ast.Expression)TransformExpression(arg)); - } - Ast.Expression arg1 = args.Count >= 1 ? args[0] : null; - Ast.Expression arg2 = args.Count >= 2 ? args[1] : null; - Ast.Expression arg3 = args.Count >= 3 ? args[2] : null; - - switch (byteCode.Code) { - #region Arithmetic - case ILCode.Add: - case ILCode.Add_Ovf: - case ILCode.Add_Ovf_Un: - { - BinaryOperatorExpression boe; - if (byteCode.InferredType is PointerType) { - boe = new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2); - if (byteCode.Arguments[0].ExpectedType is PointerType || - byteCode.Arguments[1].ExpectedType is PointerType) { - boe.AddAnnotation(IntroduceUnsafeModifier.PointerArithmeticAnnotation); - } - } else { - boe = new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Add, arg2); - } - boe.AddAnnotation(byteCode.Code == ILCode.Add ? AddCheckedBlocks.UncheckedAnnotation : AddCheckedBlocks.CheckedAnnotation); - return boe; - } - case ILCode.Sub: - case ILCode.Sub_Ovf: - case ILCode.Sub_Ovf_Un: - { - BinaryOperatorExpression boe; - if (byteCode.InferredType is PointerType) { - boe = new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2); - if (byteCode.Arguments[0].ExpectedType is PointerType) { - boe.WithAnnotation(IntroduceUnsafeModifier.PointerArithmeticAnnotation); - } - } else { - boe = new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2); - } - boe.AddAnnotation(byteCode.Code == ILCode.Sub ? AddCheckedBlocks.UncheckedAnnotation : AddCheckedBlocks.CheckedAnnotation); - return boe; - } - case ILCode.Div: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2); - case ILCode.Div_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2); - case ILCode.Mul: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2).WithAnnotation(AddCheckedBlocks.UncheckedAnnotation); - case ILCode.Mul_Ovf: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2).WithAnnotation(AddCheckedBlocks.CheckedAnnotation); - case ILCode.Mul_Ovf_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2).WithAnnotation(AddCheckedBlocks.CheckedAnnotation); - case ILCode.Rem: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2); - case ILCode.Rem_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2); - case ILCode.And: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseAnd, arg2); - case ILCode.Or: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseOr, arg2); - case ILCode.Xor: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ExclusiveOr, arg2); - case ILCode.Shl: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftLeft, arg2); - case ILCode.Shr: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2); - case ILCode.Shr_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2); - case ILCode.Neg: return new Ast.UnaryOperatorExpression(UnaryOperatorType.Minus, arg1).WithAnnotation(AddCheckedBlocks.UncheckedAnnotation); - case ILCode.Not: return new Ast.UnaryOperatorExpression(UnaryOperatorType.BitNot, arg1); - case ILCode.PostIncrement: - case ILCode.PostIncrement_Ovf: - case ILCode.PostIncrement_Ovf_Un: - { - if (arg1 is DirectionExpression) - arg1 = ((DirectionExpression)arg1).Expression.Detach(); - var uoe = new Ast.UnaryOperatorExpression( - (int)byteCode.Operand > 0 ? UnaryOperatorType.PostIncrement : UnaryOperatorType.PostDecrement, arg1); - uoe.AddAnnotation((byteCode.Code == ILCode.PostIncrement) ? AddCheckedBlocks.UncheckedAnnotation : AddCheckedBlocks.CheckedAnnotation); - return uoe; - } - #endregion - #region Arrays - case ILCode.Newarr: { - var ace = new Ast.ArrayCreateExpression(); - ace.Type = operandAsTypeRef; - ComposedType ct = operandAsTypeRef as ComposedType; - if (ct != null) { - // change "new (int[,])[10] to new int[10][,]" - ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers); - } - if (byteCode.Code == ILCode.InitArray) { - ace.Initializer = new ArrayInitializerExpression(); - ace.Initializer.Elements.AddRange(args); - } else { - ace.Arguments.Add(arg1); - } - return ace; - } - case ILCode.InitArray: { - var ace = new Ast.ArrayCreateExpression(); - ace.Type = operandAsTypeRef; - ComposedType ct = operandAsTypeRef as ComposedType; - var arrayType = (ArrayType) operand; - if (ct != null) - { - // change "new (int[,])[10] to new int[10][,]" - ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers); - ace.Initializer = new ArrayInitializerExpression(); - } - var newArgs = new List(); - foreach (var arrayDimension in arrayType.Dimensions.Skip(1).Reverse()) - { - int length = (int)arrayDimension.UpperBound - (int)arrayDimension.LowerBound; - for (int j = 0; j < args.Count; j += length) - { - var child = new ArrayInitializerExpression(); - child.Elements.AddRange(args.GetRange(j, length)); - newArgs.Add(child); - } - var temp = args; - args = newArgs; - newArgs = temp; - newArgs.Clear(); - } - ace.Initializer.Elements.AddRange(args); - return ace; - } - case ILCode.Ldlen: return arg1.Member("Length"); - case ILCode.Ldelem_I: - case ILCode.Ldelem_I1: - case ILCode.Ldelem_I2: - case ILCode.Ldelem_I4: - case ILCode.Ldelem_I8: - case ILCode.Ldelem_U1: - case ILCode.Ldelem_U2: - case ILCode.Ldelem_U4: - case ILCode.Ldelem_R4: - case ILCode.Ldelem_R8: - case ILCode.Ldelem_Ref: - case ILCode.Ldelem_Any: - return arg1.Indexer(arg2); - case ILCode.Ldelema: - return MakeRef(arg1.Indexer(arg2)); - case ILCode.Stelem_I: - case ILCode.Stelem_I1: - case ILCode.Stelem_I2: - case ILCode.Stelem_I4: - case ILCode.Stelem_I8: - case ILCode.Stelem_R4: - case ILCode.Stelem_R8: - case ILCode.Stelem_Ref: - case ILCode.Stelem_Any: - return new Ast.AssignmentExpression(arg1.Indexer(arg2), arg3); - case ILCode.CompoundAssignment: - { - CastExpression cast = arg1 as CastExpression; - var boe = cast != null ? (BinaryOperatorExpression)cast.Expression : arg1 as BinaryOperatorExpression; - // AssignmentExpression doesn't support overloaded operators so they have to be processed to BinaryOperatorExpression - if (boe == null) { - var tmp = new ParenthesizedExpression(arg1); - ReplaceMethodCallsWithOperators.ProcessInvocationExpression((InvocationExpression)arg1); - boe = (BinaryOperatorExpression)tmp.Expression; - } - var assignment = new Ast.AssignmentExpression { - Left = boe.Left.Detach(), - Operator = ReplaceMethodCallsWithOperators.GetAssignmentOperatorForBinaryOperator(boe.Operator), - Right = boe.Right.Detach() - }.CopyAnnotationsFrom(boe); - // We do not mark the resulting assignment as RestoreOriginalAssignOperatorAnnotation, because - // the operator cannot be translated back to the expanded form (as the left-hand expression - // would be evaluated twice, and might have side-effects) - if (cast != null) { - cast.Expression = assignment; - return cast; - } else { - return assignment; - } - } - #endregion - #region Comparison - case ILCode.Ceq: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2); - case ILCode.Cne: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2); - case ILCode.Cgt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2); - case ILCode.Cgt_Un: { - // can also mean Inequality, when used with object references - TypeReference arg1Type = byteCode.Arguments[0].InferredType; - if (arg1Type != null && !arg1Type.IsValueType) goto case ILCode.Cne; - - // when comparing signed integral values using Cgt_Un with 0 - // the Ast should actually contain InEquality since "(uint)a > 0u" is identical to "a != 0" - if (arg1Type.IsSignedIntegralType()) - { - var p = arg2 as Ast.PrimitiveExpression; - if (p != null && p.Value.IsZero()) goto case ILCode.Cne; - } - - goto case ILCode.Cgt; - } - case ILCode.Cle_Un: { - // can also mean Equality, when used with object references - TypeReference arg1Type = byteCode.Arguments[0].InferredType; - if (arg1Type != null && !arg1Type.IsValueType) goto case ILCode.Ceq; - - // when comparing signed integral values using Cle_Un with 0 - // the Ast should actually contain Equality since "(uint)a <= 0u" is identical to "a == 0" - if (arg1Type.IsSignedIntegralType()) - { - var p = arg2 as Ast.PrimitiveExpression; - if (p != null && p.Value.IsZero()) goto case ILCode.Ceq; - } - - goto case ILCode.Cle; - } - case ILCode.Cle: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2); - case ILCode.Cge_Un: - case ILCode.Cge: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2); - case ILCode.Clt_Un: - case ILCode.Clt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2); - #endregion - #region Logical - case ILCode.LogicNot: return new Ast.UnaryOperatorExpression(UnaryOperatorType.Not, arg1); - case ILCode.LogicAnd: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ConditionalAnd, arg2); - case ILCode.LogicOr: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.ConditionalOr, arg2); - case ILCode.TernaryOp: return new Ast.ConditionalExpression() { Condition = arg1, TrueExpression = arg2, FalseExpression = arg3 }; - case ILCode.NullCoalescing: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.NullCoalescing, arg2); - #endregion - #region Branch - case ILCode.Br: return new Ast.GotoStatement(((ILLabel)byteCode.Operand).Name); - case ILCode.Brtrue: - return new Ast.IfElseStatement() { - Condition = arg1, - TrueStatement = new BlockStatement() { - new Ast.GotoStatement(((ILLabel)byteCode.Operand).Name) - } - }; - case ILCode.LoopOrSwitchBreak: return new Ast.BreakStatement(); - case ILCode.LoopContinue: return new Ast.ContinueStatement(); - #endregion - #region Conversions - case ILCode.Conv_I1: - case ILCode.Conv_I2: - case ILCode.Conv_I4: - case ILCode.Conv_I8: - case ILCode.Conv_U1: - case ILCode.Conv_U2: - case ILCode.Conv_U4: - case ILCode.Conv_U8: - case ILCode.Conv_I: - case ILCode.Conv_U: - { - // conversion was handled by Convert() function using the info from type analysis - CastExpression cast = arg1 as CastExpression; - if (cast != null) { - cast.AddAnnotation(AddCheckedBlocks.UncheckedAnnotation); - } - return arg1; - } - case ILCode.Conv_R4: - case ILCode.Conv_R8: - case ILCode.Conv_R_Un: // TODO - return arg1; - case ILCode.Conv_Ovf_I1: - case ILCode.Conv_Ovf_I2: - case ILCode.Conv_Ovf_I4: - case ILCode.Conv_Ovf_I8: - case ILCode.Conv_Ovf_U1: - case ILCode.Conv_Ovf_U2: - case ILCode.Conv_Ovf_U4: - case ILCode.Conv_Ovf_U8: - case ILCode.Conv_Ovf_I1_Un: - case ILCode.Conv_Ovf_I2_Un: - case ILCode.Conv_Ovf_I4_Un: - case ILCode.Conv_Ovf_I8_Un: - case ILCode.Conv_Ovf_U1_Un: - case ILCode.Conv_Ovf_U2_Un: - case ILCode.Conv_Ovf_U4_Un: - case ILCode.Conv_Ovf_U8_Un: - case ILCode.Conv_Ovf_I: - case ILCode.Conv_Ovf_U: - case ILCode.Conv_Ovf_I_Un: - case ILCode.Conv_Ovf_U_Un: - { - // conversion was handled by Convert() function using the info from type analysis - CastExpression cast = arg1 as CastExpression; - if (cast != null) { - cast.AddAnnotation(AddCheckedBlocks.CheckedAnnotation); - } - return arg1; - } - case ILCode.Unbox_Any: - // unboxing does not require a cast if the argument was an isinst instruction - if (arg1 is AsExpression && byteCode.Arguments[0].Code == ILCode.Isinst && TypeAnalysis.IsSameType(operand as TypeReference, byteCode.Arguments[0].Operand as TypeReference)) - return arg1; - else - goto case ILCode.Castclass; - case ILCode.Castclass: - if ((byteCode.Arguments[0].InferredType != null && byteCode.Arguments[0].InferredType.IsGenericParameter) || ((Cecil.TypeReference)operand).IsGenericParameter) - return arg1.CastTo(new PrimitiveType("object")).CastTo(operandAsTypeRef); - else - return arg1.CastTo(operandAsTypeRef); - case ILCode.Isinst: - return arg1.CastAs(operandAsTypeRef); - case ILCode.Box: - return arg1; - case ILCode.Unbox: - return MakeRef(arg1.CastTo(operandAsTypeRef)); - #endregion - #region Indirect - case ILCode.Ldind_Ref: - case ILCode.Ldobj: - if (arg1 is DirectionExpression) - return ((DirectionExpression)arg1).Expression.Detach(); - else - return new UnaryOperatorExpression(UnaryOperatorType.Dereference, arg1); - case ILCode.Stind_Ref: - case ILCode.Stobj: - if (arg1 is DirectionExpression) - return new AssignmentExpression(((DirectionExpression)arg1).Expression.Detach(), arg2); - else - return new AssignmentExpression(new UnaryOperatorExpression(UnaryOperatorType.Dereference, arg1), arg2); - #endregion - case ILCode.Arglist: - return new UndocumentedExpression { UndocumentedExpressionType = UndocumentedExpressionType.ArgListAccess }; - case ILCode.Break: return InlineAssembly(byteCode, args); - case ILCode.Call: - case ILCode.CallGetter: - case ILCode.CallSetter: - return TransformCall(false, byteCode, args); - case ILCode.Callvirt: - case ILCode.CallvirtGetter: - case ILCode.CallvirtSetter: - return TransformCall(true, byteCode, args); - case ILCode.Ldftn: { - Cecil.MethodReference cecilMethod = ((MethodReference)operand); - var expr = new Ast.IdentifierExpression(cecilMethod.Name); - expr.TypeArguments.AddRange(ConvertTypeArguments(cecilMethod)); - expr.AddAnnotation(cecilMethod); - return new IdentifierExpression("ldftn").Invoke(expr) - .WithAnnotation(new Transforms.DelegateConstruction.Annotation(false)); - } - case ILCode.Ldvirtftn: { - Cecil.MethodReference cecilMethod = ((MethodReference)operand); - var expr = new Ast.IdentifierExpression(cecilMethod.Name); - expr.TypeArguments.AddRange(ConvertTypeArguments(cecilMethod)); - expr.AddAnnotation(cecilMethod); - return new IdentifierExpression("ldvirtftn").Invoke(expr) - .WithAnnotation(new Transforms.DelegateConstruction.Annotation(true)); - } - case ILCode.Calli: return InlineAssembly(byteCode, args); - case ILCode.Ckfinite: return InlineAssembly(byteCode, args); - case ILCode.Constrained: return InlineAssembly(byteCode, args); - case ILCode.Cpblk: return InlineAssembly(byteCode, args); - case ILCode.Cpobj: return InlineAssembly(byteCode, args); - case ILCode.Dup: return arg1; - case ILCode.Endfilter: return InlineAssembly(byteCode, args); - case ILCode.Endfinally: return null; - case ILCode.Initblk: return InlineAssembly(byteCode, args); - case ILCode.Initobj: return InlineAssembly(byteCode, args); - case ILCode.DefaultValue: - return MakeDefaultValue((TypeReference)operand); - case ILCode.Jmp: return InlineAssembly(byteCode, args); - case ILCode.Ldc_I4: - return AstBuilder.MakePrimitive((int)operand, byteCode.InferredType); - case ILCode.Ldc_I8: - return AstBuilder.MakePrimitive((long)operand, byteCode.InferredType); - case ILCode.Ldc_R4: - case ILCode.Ldc_R8: - case ILCode.Ldc_Decimal: - return new Ast.PrimitiveExpression(operand); - case ILCode.Ldfld: - if (arg1 is DirectionExpression) - arg1 = ((DirectionExpression)arg1).Expression.Detach(); - return arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand); - case ILCode.Ldsfld: - return AstBuilder.ConvertType(((FieldReference)operand).DeclaringType) - .Member(((FieldReference)operand).Name).WithAnnotation(operand); - case ILCode.Stfld: - if (arg1 is DirectionExpression) - arg1 = ((DirectionExpression)arg1).Expression.Detach(); - return new AssignmentExpression(arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand), arg2); - case ILCode.Stsfld: - return new AssignmentExpression( - AstBuilder.ConvertType(((FieldReference)operand).DeclaringType) - .Member(((FieldReference)operand).Name).WithAnnotation(operand), - arg1); - case ILCode.Ldflda: - if (arg1 is DirectionExpression) - arg1 = ((DirectionExpression)arg1).Expression.Detach(); - return MakeRef(arg1.Member(((FieldReference) operand).Name).WithAnnotation(operand)); - case ILCode.Ldsflda: - return MakeRef( - AstBuilder.ConvertType(((FieldReference)operand).DeclaringType) - .Member(((FieldReference)operand).Name).WithAnnotation(operand)); - case ILCode.Ldloc: { - ILVariable v = (ILVariable)operand; - if (!v.IsParameter) - localVariablesToDefine.Add((ILVariable)operand); - Expression expr; - if (v.IsParameter && v.OriginalParameter.Index < 0) - expr = new ThisReferenceExpression(); - else - expr = new Ast.IdentifierExpression(((ILVariable)operand).Name).WithAnnotation(operand); - return v.IsParameter && v.Type is ByReferenceType ? MakeRef(expr) : expr; - } - case ILCode.Ldloca: { - ILVariable v = (ILVariable)operand; - if (v.IsParameter && v.OriginalParameter.Index < 0) - return MakeRef(new ThisReferenceExpression()); - if (!v.IsParameter) - localVariablesToDefine.Add((ILVariable)operand); - return MakeRef(new Ast.IdentifierExpression(((ILVariable)operand).Name).WithAnnotation(operand)); - } - case ILCode.Ldnull: return new Ast.NullReferenceExpression(); - case ILCode.Ldstr: return new Ast.PrimitiveExpression(operand); - case ILCode.Ldtoken: - if (operand is Cecil.TypeReference) { - return AstBuilder.CreateTypeOfExpression((TypeReference)operand).Member("TypeHandle"); - } else { - Expression referencedEntity; - string loadName; - string handleName; - if (operand is Cecil.FieldReference) { - loadName = "fieldof"; - handleName = "FieldHandle"; - FieldReference fr = (FieldReference)operand; - referencedEntity = AstBuilder.ConvertType(fr.DeclaringType).Member(fr.Name).WithAnnotation(fr); - } else if (operand is Cecil.MethodReference) { - loadName = "methodof"; - handleName = "MethodHandle"; - MethodReference mr = (MethodReference)operand; - var methodParameters = mr.Parameters.Select(p => new TypeReferenceExpression(AstBuilder.ConvertType(p.ParameterType))); - referencedEntity = AstBuilder.ConvertType(mr.DeclaringType).Invoke(mr.Name, methodParameters).WithAnnotation(mr); - } else { - loadName = "ldtoken"; - handleName = "Handle"; - referencedEntity = new IdentifierExpression(FormatByteCodeOperand(byteCode.Operand)); - } - return new IdentifierExpression(loadName).Invoke(referencedEntity).WithAnnotation(new LdTokenAnnotation()).Member(handleName); - } - case ILCode.Leave: return new GotoStatement() { Label = ((ILLabel)operand).Name }; - case ILCode.Localloc: - { - PointerType ptrType = byteCode.InferredType as PointerType; - TypeReference type; - if (ptrType != null) { - type = ptrType.ElementType; - } else { - type = typeSystem.Byte; - } - return new StackAllocExpression { - Type = AstBuilder.ConvertType(type), - CountExpression = arg1 - }; - } - case ILCode.Mkrefany: - { - DirectionExpression dir = arg1 as DirectionExpression; - if (dir != null) { - return new UndocumentedExpression { - UndocumentedExpressionType = UndocumentedExpressionType.MakeRef, - Arguments = { dir.Expression.Detach() } - }; - } else { - return InlineAssembly(byteCode, args); - } - } - case ILCode.Refanytype: - return new UndocumentedExpression { - UndocumentedExpressionType = UndocumentedExpressionType.RefType, - Arguments = { arg1 } - }.Member("TypeHandle"); - case ILCode.Refanyval: - return MakeRef( - new UndocumentedExpression { - UndocumentedExpressionType = UndocumentedExpressionType.RefValue, - Arguments = { arg1, new TypeReferenceExpression(operandAsTypeRef) } - }); - case ILCode.Newobj: { - Cecil.TypeReference declaringType = ((MethodReference)operand).DeclaringType; - if (declaringType is ArrayType) { - ComposedType ct = AstBuilder.ConvertType((ArrayType)declaringType) as ComposedType; - if (ct != null && ct.ArraySpecifiers.Count >= 1) { - var ace = new Ast.ArrayCreateExpression(); - ct.ArraySpecifiers.First().Remove(); - ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers); - ace.Type = ct; - ace.Arguments.AddRange(args); - return ace; - } - } - MethodDefinition ctor = ((MethodReference)operand).Resolve(); - if (declaringType.IsAnonymousType() && methodDef != null) { - AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression(); - if (CanInferAnonymousTypePropertyNamesFromArguments(args, ctor.Parameters)) { - atce.Initializers.AddRange(args); - } else { - for (int i = 0; i < args.Count; i++) { - atce.Initializers.Add( - new NamedExpression { - Name = ctor.Parameters[i].Name, - Expression = args[i] - }); - } - } - return atce; - } - var oce = new Ast.ObjectCreateExpression(); - oce.Type = AstBuilder.ConvertType(declaringType); - // seems like IsIn/IsOut information for parameters is only correct on the ctor's MethodDefinition - if (ctor != null) { - AdjustArgumentsForMethodCall(ctor, args); - } - oce.Arguments.AddRange(args); - return oce.WithAnnotation(operand); - } - case ILCode.No: return InlineAssembly(byteCode, args); - case ILCode.Nop: return null; - case ILCode.Pop: return arg1; - case ILCode.Readonly: return InlineAssembly(byteCode, args); - case ILCode.Ret: - if (methodDef.ReturnType.FullName != "System.Void") { - return new Ast.ReturnStatement { Expression = arg1 }; - } else { - return new Ast.ReturnStatement(); - } - case ILCode.Rethrow: return new Ast.ThrowStatement(); - case ILCode.Sizeof: return new Ast.SizeOfExpression { Type = operandAsTypeRef }; - case ILCode.Stloc: { - ILVariable locVar = (ILVariable)operand; - if (!locVar.IsParameter) - localVariablesToDefine.Add(locVar); - return new Ast.AssignmentExpression(new Ast.IdentifierExpression(locVar.Name).WithAnnotation(locVar), arg1); - } - case ILCode.Switch: return InlineAssembly(byteCode, args); - case ILCode.Tail: return InlineAssembly(byteCode, args); - case ILCode.Throw: return new Ast.ThrowStatement { Expression = arg1 }; - case ILCode.Unaligned: return InlineAssembly(byteCode, args); - case ILCode.Volatile: return InlineAssembly(byteCode, args); - case ILCode.YieldBreak: - return new Ast.YieldBreakStatement(); - case ILCode.YieldReturn: - return new Ast.YieldReturnStatement { Expression = arg1 }; - case ILCode.InitObject: - case ILCode.InitCollection: - { - ArrayInitializerExpression initializer = new ArrayInitializerExpression(); - for (int i = 1; i < args.Count; i++) { - Match m = objectInitializerPattern.Match(args[i]); - if (m.Success) { - MemberReferenceExpression mre = m.Get("left").Single(); - initializer.Elements.Add( - new NamedExpression { - Name = mre.MemberName, - Expression = m.Get("right").Single().Detach() - }.CopyAnnotationsFrom(mre)); - } else { - m = collectionInitializerPattern.Match(args[i]); - if (m.Success) { - if (m.Get("arg").Count() == 1) { - initializer.Elements.Add(m.Get("arg").Single().Detach()); - } else { - ArrayInitializerExpression argList = new ArrayInitializerExpression(); - foreach (var expr in m.Get("arg")) { - argList.Elements.Add(expr.Detach()); - } - initializer.Elements.Add(argList); - } - } else { - initializer.Elements.Add(args[i]); - } - } - } - ObjectCreateExpression oce = arg1 as ObjectCreateExpression; - DefaultValueExpression dve = arg1 as DefaultValueExpression; - if (oce != null) { - oce.Initializer = initializer; - return oce; - } else if (dve != null) { - oce = new ObjectCreateExpression(dve.Type.Detach()); - oce.CopyAnnotationsFrom(dve); - oce.Initializer = initializer; - return oce; - } else { - return new AssignmentExpression(arg1, initializer); - } - } - case ILCode.InitializedObject: - return new InitializedObjectExpression(); - case ILCode.Wrap: - return arg1.WithAnnotation(PushNegation.LiftedOperatorAnnotation); - case ILCode.AddressOf: - return MakeRef(arg1); - case ILCode.ExpressionTreeParameterDeclarations: - args[args.Count - 1].AddAnnotation(new ParameterDeclarationAnnotation(byteCode)); - return args[args.Count - 1]; - case ILCode.Await: - return new UnaryOperatorExpression(UnaryOperatorType.Await, UnpackDirectionExpression(arg1)); - case ILCode.NullableOf: - case ILCode.ValueOf: - return arg1; - default: - throw new Exception("Unknown OpCode: " + byteCode.Code); - } - } - - internal static bool CanInferAnonymousTypePropertyNamesFromArguments(IList args, IList parameters) - { - for (int i = 0; i < args.Count; i++) { - string inferredName; - if (args[i] is IdentifierExpression) - inferredName = ((IdentifierExpression)args[i]).Identifier; - else if (args[i] is MemberReferenceExpression) - inferredName = ((MemberReferenceExpression)args[i]).MemberName; - else - inferredName = null; - - if (inferredName != parameters[i].Name) { - return false; - } - } - return true; - } - - static readonly AstNode objectInitializerPattern = new AssignmentExpression( - new MemberReferenceExpression { - Target = new InitializedObjectExpression(), - MemberName = Pattern.AnyString - }.WithName("left"), - new AnyNode("right") - ); - - static readonly AstNode collectionInitializerPattern = new InvocationExpression { - Target = new MemberReferenceExpression { - Target = new InitializedObjectExpression(), - MemberName = "Add" - }, - Arguments = { new Repeat(new AnyNode("arg")) } - }; - - sealed class InitializedObjectExpression : IdentifierExpression - { - public InitializedObjectExpression() : base("__initialized_object__") {} - - protected override bool DoMatch(AstNode other, Match match) - { - return other is InitializedObjectExpression; - } - } - - Expression MakeDefaultValue(TypeReference type) - { - TypeDefinition typeDef = type.Resolve(); - if (typeDef != null) { - if (TypeAnalysis.IsIntegerOrEnum(typeDef)) - return AstBuilder.MakePrimitive(0, typeDef); - else if (!typeDef.IsValueType) - return new NullReferenceExpression(); - switch (typeDef.FullName) { - case "System.Nullable`1": - return new NullReferenceExpression(); - case "System.Single": - return new PrimitiveExpression(0f); - case "System.Double": - return new PrimitiveExpression(0.0); - case "System.Decimal": - return new PrimitiveExpression(0m); - } - } - return new DefaultValueExpression { Type = AstBuilder.ConvertType(type) }; - } - - AstNode TransformCall(bool isVirtual, ILExpression byteCode, List args) - { - Cecil.MethodReference cecilMethod = (MethodReference)byteCode.Operand; - Cecil.MethodDefinition cecilMethodDef = cecilMethod.Resolve(); - Ast.Expression target; - List methodArgs = new List(args); - if (cecilMethod.HasThis) { - target = methodArgs[0]; - methodArgs.RemoveAt(0); - - // Unpack any DirectionExpression that is used as target for the call - // (calling methods on value types implicitly passes the first argument by reference) - target = UnpackDirectionExpression(target); - - if (cecilMethodDef != null) { - // convert null.ToLower() to ((string)null).ToLower() - if (target is NullReferenceExpression) - target = target.CastTo(AstBuilder.ConvertType(cecilMethod.DeclaringType)); - - if (cecilMethodDef.DeclaringType.IsInterface) { - TypeReference tr = byteCode.Arguments[0].InferredType; - if (tr != null) { - TypeDefinition td = tr.Resolve(); - if (td != null && !td.IsInterface) { - // Calling an interface method on a non-interface object: - // we need to introduce an explicit cast - target = target.CastTo(AstBuilder.ConvertType(cecilMethod.DeclaringType)); - } - } - } - } - } else { - target = new TypeReferenceExpression { Type = AstBuilder.ConvertType(cecilMethod.DeclaringType) }; - } - if (target is ThisReferenceExpression && !isVirtual) { - // a non-virtual call on "this" might be a "base"-call. - if (cecilMethod.DeclaringType.GetElementType() != methodDef.DeclaringType) { - // If we're not calling a method in the current class; we must be calling one in the base class. - target = new BaseReferenceExpression(); - } - } - - if (cecilMethod.Name == ".ctor" && cecilMethod.DeclaringType.IsValueType) { - // On value types, the constructor can be called. - // This is equivalent to 'target = new ValueType(args);'. - ObjectCreateExpression oce = new ObjectCreateExpression(); - oce.Type = AstBuilder.ConvertType(cecilMethod.DeclaringType); - oce.AddAnnotation(cecilMethod); - AdjustArgumentsForMethodCall(cecilMethod, methodArgs); - oce.Arguments.AddRange(methodArgs); - return new AssignmentExpression(target, oce); - } - - if (cecilMethod.Name == "Get" && cecilMethod.DeclaringType is ArrayType && methodArgs.Count > 1) { - return target.Indexer(methodArgs); - } else if (cecilMethod.Name == "Set" && cecilMethod.DeclaringType is ArrayType && methodArgs.Count > 2) { - return new AssignmentExpression(target.Indexer(methodArgs.GetRange(0, methodArgs.Count - 1)), methodArgs.Last()); - } - - // Test whether the method is an accessor: - if (cecilMethodDef != null) { - if (cecilMethodDef.IsGetter && methodArgs.Count == 0) { - foreach (var prop in cecilMethodDef.DeclaringType.Properties) { - if (prop.GetMethod == cecilMethodDef) - return target.Member(prop.Name).WithAnnotation(prop).WithAnnotation(cecilMethod); - } - } else if (cecilMethodDef.IsGetter) { // with parameters - PropertyDefinition indexer = GetIndexer(cecilMethodDef); - if (indexer != null) - return target.Indexer(methodArgs).WithAnnotation(indexer).WithAnnotation(cecilMethod); - } else if (cecilMethodDef.IsSetter && methodArgs.Count == 1) { - foreach (var prop in cecilMethodDef.DeclaringType.Properties) { - if (prop.SetMethod == cecilMethodDef) - return new Ast.AssignmentExpression(target.Member(prop.Name).WithAnnotation(prop).WithAnnotation(cecilMethod), methodArgs[0]); - } - } else if (cecilMethodDef.IsSetter && methodArgs.Count > 1) { - PropertyDefinition indexer = GetIndexer(cecilMethodDef); - if (indexer != null) - return new AssignmentExpression( - target.Indexer(methodArgs.GetRange(0, methodArgs.Count - 1)).WithAnnotation(indexer).WithAnnotation(cecilMethod), - methodArgs[methodArgs.Count - 1] - ); - } else if (cecilMethodDef.IsAddOn && methodArgs.Count == 1) { - foreach (var ev in cecilMethodDef.DeclaringType.Events) { - if (ev.AddMethod == cecilMethodDef) { - return new Ast.AssignmentExpression { - Left = target.Member(ev.Name).WithAnnotation(ev).WithAnnotation(cecilMethod), - Operator = AssignmentOperatorType.Add, - Right = methodArgs[0] - }; - } - } - } else if (cecilMethodDef.IsRemoveOn && methodArgs.Count == 1) { - foreach (var ev in cecilMethodDef.DeclaringType.Events) { - if (ev.RemoveMethod == cecilMethodDef) { - return new Ast.AssignmentExpression { - Left = target.Member(ev.Name).WithAnnotation(ev).WithAnnotation(cecilMethod), - Operator = AssignmentOperatorType.Subtract, - Right = methodArgs[0] - }; - } - } - } else if (cecilMethodDef.Name == "Invoke" && cecilMethodDef.DeclaringType.BaseType != null && cecilMethodDef.DeclaringType.BaseType.FullName == "System.MulticastDelegate") { - AdjustArgumentsForMethodCall(cecilMethod, methodArgs); - return target.Invoke(methodArgs).WithAnnotation(cecilMethod); - } - } - // Default invocation - AdjustArgumentsForMethodCall(cecilMethodDef ?? cecilMethod, methodArgs); - return target.Invoke(cecilMethod.Name, ConvertTypeArguments(cecilMethod), methodArgs).WithAnnotation(cecilMethod); - } - - static Expression UnpackDirectionExpression(Expression target) - { - if (target is DirectionExpression) { - return ((DirectionExpression)target).Expression.Detach(); - } else { - return target; - } - } - - static void AdjustArgumentsForMethodCall(MethodReference cecilMethod, List methodArgs) - { - // Convert 'ref' into 'out' where necessary - for (int i = 0; i < methodArgs.Count && i < cecilMethod.Parameters.Count; i++) { - DirectionExpression dir = methodArgs[i] as DirectionExpression; - ParameterDefinition p = cecilMethod.Parameters[i]; - if (dir != null && p.IsOut && !p.IsIn) - dir.FieldDirection = FieldDirection.Out; - } - } - - internal static PropertyDefinition GetIndexer(MethodDefinition cecilMethodDef) - { - TypeDefinition typeDef = cecilMethodDef.DeclaringType; - string indexerName = null; - foreach (CustomAttribute ca in typeDef.CustomAttributes) { - if (ca.Constructor.FullName == "System.Void System.Reflection.DefaultMemberAttribute::.ctor(System.String)") { - indexerName = ca.ConstructorArguments.Single().Value as string; - break; - } - } - if (indexerName == null) - return null; - foreach (PropertyDefinition prop in typeDef.Properties) { - if (prop.Name == indexerName) { - if (prop.GetMethod == cecilMethodDef || prop.SetMethod == cecilMethodDef) - return prop; - } - } - return null; - } - - #if DEBUG - static readonly ConcurrentDictionary unhandledOpcodes = new ConcurrentDictionary(); - #endif - - [Conditional("DEBUG")] - public static void ClearUnhandledOpcodes() - { - #if DEBUG - unhandledOpcodes.Clear(); - #endif - } - - [Conditional("DEBUG")] - public static void PrintNumberOfUnhandledOpcodes() - { - #if DEBUG - foreach (var pair in unhandledOpcodes) { - Debug.WriteLine("AddMethodBodyBuilder unhandled opcode: {1}x {0}", pair.Key, pair.Value); - } - #endif - } - - static Expression InlineAssembly(ILExpression byteCode, List args) - { - #if DEBUG - unhandledOpcodes.AddOrUpdate(byteCode.Code, c => 1, (c, n) => n+1); - #endif - // Output the operand of the unknown IL code as well - if (byteCode.Operand != null) { - args.Insert(0, new IdentifierExpression(FormatByteCodeOperand(byteCode.Operand))); - } - return new IdentifierExpression(byteCode.Code.GetName()).Invoke(args); - } - - static string FormatByteCodeOperand(object operand) - { - if (operand == null) { - return string.Empty; - //} else if (operand is ILExpression) { - // return string.Format("IL_{0:X2}", ((ILExpression)operand).Offset); - } else if (operand is MethodReference) { - return ((MethodReference)operand).Name + "()"; - } else if (operand is Cecil.TypeReference) { - return ((Cecil.TypeReference)operand).FullName; - } else if (operand is VariableDefinition) { - return ((VariableDefinition)operand).Name; - } else if (operand is ParameterDefinition) { - return ((ParameterDefinition)operand).Name; - } else if (operand is FieldReference) { - return ((FieldReference)operand).Name; - } else if (operand is string) { - return "\"" + operand + "\""; - } else if (operand is int) { - return operand.ToString(); - } else { - return operand.ToString(); - } - } - - static IEnumerable ConvertTypeArguments(MethodReference cecilMethod) - { - GenericInstanceMethod g = cecilMethod as GenericInstanceMethod; - if (g == null) - return null; - if (g.GenericArguments.Any(ta => ta.ContainsAnonymousType())) - return null; - return g.GenericArguments.Select(t => AstBuilder.ConvertType(t)); - } - - static Ast.DirectionExpression MakeRef(Ast.Expression expr) - { - return new DirectionExpression { Expression = expr, FieldDirection = FieldDirection.Ref }; - } - - Ast.Expression Convert(Ast.Expression expr, Cecil.TypeReference actualType, Cecil.TypeReference reqType) - { - if (actualType == null || reqType == null || TypeAnalysis.IsSameType(actualType, reqType)) { - return expr; - } else if (actualType is ByReferenceType && reqType is PointerType && expr is DirectionExpression) { - return Convert( - new UnaryOperatorExpression(UnaryOperatorType.AddressOf, ((DirectionExpression)expr).Expression.Detach()), - new PointerType(((ByReferenceType)actualType).ElementType), - reqType); - } else if (actualType is PointerType && reqType is ByReferenceType) { - expr = Convert(expr, actualType, new PointerType(((ByReferenceType)reqType).ElementType)); - return new DirectionExpression { - FieldDirection = FieldDirection.Ref, - Expression = new UnaryOperatorExpression(UnaryOperatorType.Dereference, expr) - }; - } else if (actualType is PointerType && reqType is PointerType) { - if (actualType.FullName != reqType.FullName) - return expr.CastTo(AstBuilder.ConvertType(reqType)); - else - return expr; - } else { - bool actualIsIntegerOrEnum = TypeAnalysis.IsIntegerOrEnum(actualType); - bool requiredIsIntegerOrEnum = TypeAnalysis.IsIntegerOrEnum(reqType); - - if (TypeAnalysis.IsBoolean(reqType)) { - if (TypeAnalysis.IsBoolean(actualType)) - return expr; - if (actualIsIntegerOrEnum) { - return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, AstBuilder.MakePrimitive(0, actualType)); - } else { - return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, new NullReferenceExpression()); - } - } - if (TypeAnalysis.IsBoolean(actualType) && requiredIsIntegerOrEnum) { - return new ConditionalExpression { - Condition = expr, - TrueExpression = AstBuilder.MakePrimitive(1, reqType), - FalseExpression = AstBuilder.MakePrimitive(0, reqType) - }; - } - - if (expr is PrimitiveExpression && !requiredIsIntegerOrEnum && TypeAnalysis.IsEnum(actualType)) - { - return expr.CastTo(AstBuilder.ConvertType(actualType)); - } - - bool actualIsPrimitiveType = actualIsIntegerOrEnum - || actualType.MetadataType == MetadataType.Single || actualType.MetadataType == MetadataType.Double; - bool requiredIsPrimitiveType = requiredIsIntegerOrEnum - || reqType.MetadataType == MetadataType.Single || reqType.MetadataType == MetadataType.Double; - if (actualIsPrimitiveType && requiredIsPrimitiveType) { - return expr.CastTo(AstBuilder.ConvertType(reqType)); - } - return expr; - } - } - } -} diff --git a/ICSharpCode.Decompiler/Ast/CommentStatement.cs b/ICSharpCode.Decompiler/Ast/CommentStatement.cs deleted file mode 100644 index 6837b2418..000000000 --- a/ICSharpCode.Decompiler/Ast/CommentStatement.cs +++ /dev/null @@ -1,69 +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.Linq; -using ICSharpCode.NRefactory.CSharp; -using ICSharpCode.NRefactory.PatternMatching; - -namespace ICSharpCode.Decompiler.Ast -{ - /// - /// Allows storing comments inside IEnumerable{Statement}. Used in the AstMethodBuilder. - /// CommentStatement nodes are replaced with regular comments later on. - /// - class CommentStatement : Statement - { - string comment; - - public CommentStatement(string comment) - { - if (comment == null) - throw new ArgumentNullException("comment"); - this.comment = comment; - } - - public override void AcceptVisitor(IAstVisitor visitor) - { - } - - public override T AcceptVisitor(IAstVisitor visitor) - { - return default(T); - } - - public override S AcceptVisitor(IAstVisitor visitor, T data) - { - return default(S); - } - - public static void ReplaceAll(AstNode tree) - { - foreach (var cs in tree.Descendants.OfType()) { - cs.Parent.InsertChildBefore(cs, new Comment(cs.comment), Roles.Comment); - cs.Remove(); - } - } - - protected override bool DoMatch(AstNode other, Match match) - { - CommentStatement o = other as CommentStatement; - return o != null && MatchString(comment, o.comment); - } - } -} diff --git a/ICSharpCode.Decompiler/Ast/DecompilerContext.cs b/ICSharpCode.Decompiler/Ast/DecompilerContext.cs deleted file mode 100644 index b8cc2e149..000000000 --- a/ICSharpCode.Decompiler/Ast/DecompilerContext.cs +++ /dev/null @@ -1,57 +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.Generic; -using System.Threading; -using ICSharpCode.Decompiler.Ast; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.TypeSystem.Implementation; -using Mono.Cecil; - -namespace ICSharpCode.Decompiler -{ - public class DecompilerContext - { - public ModuleDefinition CurrentModule; - public CancellationToken CancellationToken; - public TypeDefinition CurrentType; - public MethodDefinition CurrentMethod; - public DecompilerSettings Settings = new DecompilerSettings(); - public bool CurrentMethodIsAsync; - - public DecompilerContext(ModuleDefinition currentModule) - { - if (currentModule == null) - throw new ArgumentNullException(nameof(currentModule)); - this.CurrentModule = currentModule; - } - - /// - /// Used to pass variable names from a method to its anonymous methods. - /// - internal List ReservedVariableNames = new List(); - - public DecompilerContext Clone() - { - DecompilerContext ctx = (DecompilerContext)MemberwiseClone(); - ctx.ReservedVariableNames = new List(ctx.ReservedVariableNames); - return ctx; - } - } -} diff --git a/ICSharpCode.Decompiler/Ast/NameVariables.cs b/ICSharpCode.Decompiler/Ast/NameVariables.cs deleted file mode 100644 index 3dc30e2dc..000000000 --- a/ICSharpCode.Decompiler/Ast/NameVariables.cs +++ /dev/null @@ -1,347 +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.Generic; -using System.Linq; - -using ICSharpCode.Decompiler.ILAst; -using Mono.Cecil; - -namespace ICSharpCode.Decompiler.Ast -{ - public class NameVariables - { - static readonly Dictionary typeNameToVariableNameDict = new Dictionary { - { "System.Boolean", "flag" }, - { "System.Byte", "b" }, - { "System.SByte", "b" }, - { "System.Int16", "num" }, - { "System.Int32", "num" }, - { "System.Int64", "num" }, - { "System.UInt16", "num" }, - { "System.UInt32", "num" }, - { "System.UInt64", "num" }, - { "System.Single", "num" }, - { "System.Double", "num" }, - { "System.Decimal", "num" }, - { "System.String", "text" }, - { "System.Object", "obj" }, - { "System.Char", "c" } - }; - - - public static void AssignNamesToVariables(DecompilerContext context, IEnumerable parameters, IEnumerable variables, ILBlock methodBody) - { - NameVariables nv = new NameVariables(); - nv.context = context; - nv.fieldNamesInCurrentType = context.CurrentType.Fields.Select(f => f.Name).ToList(); - // First mark existing variable names as reserved. - foreach (string name in context.ReservedVariableNames) - nv.AddExistingName(name); - foreach (var p in parameters) - nv.AddExistingName(p.Name); - foreach (var v in variables) { - if (v.IsGenerated) { - // don't introduce names for variables generated by ILSpy - keep "expr"/"arg" - nv.AddExistingName(v.Name); - } else if (v.OriginalVariable != null && context.Settings.UseDebugSymbols) { - string varName = v.OriginalVariable.Name; - if (string.IsNullOrEmpty(varName) || varName.StartsWith("V_", StringComparison.Ordinal) || !IsValidName(varName)) - { - // don't use the name from the debug symbols if it looks like a generated name - v.Name = null; - } else { - // use the name from the debug symbols - // (but ensure we don't use the same name for two variables) - v.Name = nv.GetAlternativeName(varName); - } - } else { - v.Name = null; - } - } - // Now generate names: - foreach (ILVariable p in parameters) { - if (string.IsNullOrEmpty(p.Name)) - p.Name = nv.GenerateNameForVariable(p, methodBody); - } - foreach (ILVariable varDef in variables) { - if (string.IsNullOrEmpty(varDef.Name)) - varDef.Name = nv.GenerateNameForVariable(varDef, methodBody); - } - } - - static bool IsValidName(string varName) - { - if (string.IsNullOrEmpty(varName)) - return false; - if (!(char.IsLetter(varName[0]) || varName[0] == '_')) - return false; - for (int i = 1; i < varName.Length; i++) { - if (!(char.IsLetterOrDigit(varName[i]) || varName[i] == '_')) - return false; - } - return true; - } - - DecompilerContext context; - List fieldNamesInCurrentType; - Dictionary typeNames = new Dictionary(); - - public void AddExistingName(string name) - { - if (string.IsNullOrEmpty(name)) - return; - int number; - string nameWithoutDigits = SplitName(name, out number); - int existingNumber; - if (typeNames.TryGetValue(nameWithoutDigits, out existingNumber)) { - typeNames[nameWithoutDigits] = Math.Max(number, existingNumber); - } else { - typeNames.Add(nameWithoutDigits, number); - } - } - - string SplitName(string name, out int number) - { - // First, identify whether the name already ends with a number: - int pos = name.Length; - while (pos > 0 && name[pos-1] >= '0' && name[pos-1] <= '9') - pos--; - if (pos < name.Length) { - if (int.TryParse(name.Substring(pos), out number)) { - return name.Substring(0, pos); - } - } - number = 1; - return name; - } - - const char maxLoopVariableName = 'n'; - - public string GetAlternativeName(string oldVariableName) - { - if (oldVariableName.Length == 1 && oldVariableName[0] >= 'i' && oldVariableName[0] <= maxLoopVariableName) { - for (char c = 'i'; c <= maxLoopVariableName; c++) { - if (!typeNames.ContainsKey(c.ToString())) { - typeNames.Add(c.ToString(), 1); - return c.ToString(); - } - } - } - - int number; - string nameWithoutDigits = SplitName(oldVariableName, out number); - - if (!typeNames.ContainsKey(nameWithoutDigits)) { - typeNames.Add(nameWithoutDigits, number - 1); - } - int count = ++typeNames[nameWithoutDigits]; - if (count != 1) { - return nameWithoutDigits + count.ToString(); - } else { - return nameWithoutDigits; - } - } - - string GenerateNameForVariable(ILVariable variable, ILBlock methodBody) - { - string proposedName = null; - if (variable.Type == context.CurrentType.Module.TypeSystem.Int32) { - // test whether the variable might be a loop counter - bool isLoopCounter = false; - foreach (ILWhileLoop loop in methodBody.GetSelfAndChildrenRecursive()) { - ILExpression expr = loop.Condition; - while (expr != null && expr.Code == ILCode.LogicNot) - expr = expr.Arguments[0]; - if (expr != null) { - switch (expr.Code) { - case ILCode.Clt: - case ILCode.Clt_Un: - case ILCode.Cgt: - case ILCode.Cgt_Un: - case ILCode.Cle: - case ILCode.Cle_Un: - case ILCode.Cge: - case ILCode.Cge_Un: - ILVariable loadVar; - if (expr.Arguments[0].Match(ILCode.Ldloc, out loadVar) && loadVar == variable) { - isLoopCounter = true; - } - break; - } - } - } - if (isLoopCounter) { - // For loop variables, use i,j,k,l,m,n - for (char c = 'i'; c <= maxLoopVariableName; c++) { - if (!typeNames.ContainsKey(c.ToString())) { - proposedName = c.ToString(); - break; - } - } - } - } - if (string.IsNullOrEmpty(proposedName)) { - var proposedNameForStores = - (from expr in methodBody.GetSelfAndChildrenRecursive() - where expr.Code == ILCode.Stloc && expr.Operand == variable - select GetNameFromExpression(expr.Arguments.Single()) - ).Except(fieldNamesInCurrentType).ToList(); - if (proposedNameForStores.Count == 1) { - proposedName = proposedNameForStores[0]; - } - } - if (string.IsNullOrEmpty(proposedName)) { - var proposedNameForLoads = - (from expr in methodBody.GetSelfAndChildrenRecursive() - from i in Enumerable.Range(0, expr.Arguments.Count) - let arg = expr.Arguments[i] - where arg.Code == ILCode.Ldloc && arg.Operand == variable - select GetNameForArgument(expr, i) - ).Except(fieldNamesInCurrentType).ToList(); - if (proposedNameForLoads.Count == 1) { - proposedName = proposedNameForLoads[0]; - } - } - if (string.IsNullOrEmpty(proposedName)) { - proposedName = GetNameByType(variable.Type); - } - - // remove any numbers from the proposed name - int number; - proposedName = SplitName(proposedName, out number); - - if (!typeNames.ContainsKey(proposedName)) { - typeNames.Add(proposedName, 0); - } - int count = ++typeNames[proposedName]; - if (count > 1) { - return proposedName + count.ToString(); - } else { - return proposedName; - } - } - - static string GetNameFromExpression(ILExpression expr) - { - switch (expr.Code) { - case ILCode.Ldfld: - case ILCode.Ldsfld: - return CleanUpVariableName(((FieldReference)expr.Operand).Name); - case ILCode.Call: - case ILCode.Callvirt: - case ILCode.CallGetter: - case ILCode.CallvirtGetter: - MethodReference mr = (MethodReference)expr.Operand; - if (mr.Name.StartsWith("get_", StringComparison.OrdinalIgnoreCase) && mr.Parameters.Count == 0) { - // use name from properties, but not from indexers - return CleanUpVariableName(mr.Name.Substring(4)); - } else if (mr.Name.StartsWith("Get", StringComparison.OrdinalIgnoreCase) && mr.Name.Length >= 4 && char.IsUpper(mr.Name[3])) { - // use name from Get-methods - return CleanUpVariableName(mr.Name.Substring(3)); - } - break; - } - return null; - } - - static string GetNameForArgument(ILExpression parent, int i) - { - switch (parent.Code) { - case ILCode.Stfld: - case ILCode.Stsfld: - if (i == parent.Arguments.Count - 1) // last argument is stored value - return CleanUpVariableName(((FieldReference)parent.Operand).Name); - else - break; - case ILCode.Call: - case ILCode.Callvirt: - case ILCode.Newobj: - case ILCode.CallGetter: - case ILCode.CallvirtGetter: - case ILCode.CallSetter: - case ILCode.CallvirtSetter: - MethodReference methodRef = (MethodReference)parent.Operand; - if (methodRef.Parameters.Count == 1 && i == parent.Arguments.Count - 1) { - // argument might be value of a setter - if (methodRef.Name.StartsWith("set_", StringComparison.OrdinalIgnoreCase)) { - return CleanUpVariableName(methodRef.Name.Substring(4)); - } else if (methodRef.Name.StartsWith("Set", StringComparison.OrdinalIgnoreCase) && methodRef.Name.Length >= 4 && char.IsUpper(methodRef.Name[3])) { - return CleanUpVariableName(methodRef.Name.Substring(3)); - } - } - MethodDefinition methodDef = methodRef.Resolve(); - if (methodDef != null) { - var p = methodDef.Parameters.ElementAtOrDefault((parent.Code != ILCode.Newobj && methodDef.HasThis) ? i - 1 : i); - if (p != null && !string.IsNullOrEmpty(p.Name)) - return CleanUpVariableName(p.Name); - } - break; - case ILCode.Ret: - return "result"; - } - return null; - } - - string GetNameByType(TypeReference type) - { - type = TypeAnalysis.UnpackModifiers(type); - - GenericInstanceType git = type as GenericInstanceType; - if (git != null && git.ElementType.FullName == "System.Nullable`1" && git.GenericArguments.Count == 1) { - type = ((GenericInstanceType)type).GenericArguments[0]; - } - - string name; - if (type.IsArray) { - name = "array"; - } else if (type.IsPointer || type.IsByReference) { - name = "ptr"; - } else if (type.Name.EndsWith("Exception", StringComparison.Ordinal)) { - name = "ex"; - } else if (!typeNameToVariableNameDict.TryGetValue(type.FullName, out name)) { - name = type.Name; - // remove the 'I' for interfaces - if (name.Length >= 3 && name[0] == 'I' && char.IsUpper(name[1]) && char.IsLower(name[2])) - name = name.Substring(1); - name = CleanUpVariableName(name); - } - return name; - } - - static string CleanUpVariableName(string name) - { - // remove the backtick (generics) - int pos = name.IndexOf('`'); - if (pos >= 0) - name = name.Substring(0, pos); - - // remove field prefix: - if (name.Length > 2 && name.StartsWith("m_", StringComparison.Ordinal)) - name = name.Substring(2); - else if (name.Length > 1 && name[0] == '_' && (char.IsLetter(name[1]) || name[1] == '_')) - name = name.Substring(1); - - if (name.Length == 0) - return "obj"; - else - return char.ToLower(name[0]) + name.Substring(1); - } - } -} diff --git a/ICSharpCode.Decompiler/Ast/TextTokenWriter.cs b/ICSharpCode.Decompiler/Ast/TextTokenWriter.cs deleted file mode 100644 index 2cfff7d96..000000000 --- a/ICSharpCode.Decompiler/Ast/TextTokenWriter.cs +++ /dev/null @@ -1,373 +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.Generic; -using System.Linq; -using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.ILAst; -using ICSharpCode.NRefactory; -using ICSharpCode.NRefactory.CSharp; -using Mono.Cecil; - -namespace ICSharpCode.Decompiler.Ast -{ - public class TextTokenWriter : TokenWriter - { - readonly ITextOutput output; - readonly DecompilerContext context; - readonly Stack nodeStack = new Stack(); - int braceLevelWithinType = -1; - bool inDocumentationComment = false; - bool firstUsingDeclaration; - bool lastUsingDeclaration; - - TextLocation? lastEndOfLine; - - public bool FoldBraces = false; - - public TextTokenWriter(ITextOutput output, DecompilerContext context) - { - if (output == null) - throw new ArgumentNullException("output"); - if (context == null) - throw new ArgumentNullException("context"); - this.output = output; - this.context = context; - } - - public override void WriteIdentifier(Identifier identifier) - { - if (identifier.IsVerbatim || CSharpOutputVisitor.IsKeyword(identifier.Name, identifier)) { - output.Write('@'); - } - - var definition = GetCurrentDefinition(); - if (definition != null) { - output.WriteDefinition(identifier.Name, definition, false); - return; - } - - object memberRef = GetCurrentMemberReference(); - - if (memberRef != null) { - output.WriteReference(identifier.Name, memberRef); - return; - } - - definition = GetCurrentLocalDefinition(); - if (definition != null) { - output.WriteDefinition(identifier.Name, definition); - return; - } - - memberRef = GetCurrentLocalReference(); - if (memberRef != null) { - output.WriteReference(identifier.Name, memberRef, true); - return; - } - - if (firstUsingDeclaration) { - output.MarkFoldStart(defaultCollapsed: true); - firstUsingDeclaration = false; - } - - output.Write(identifier.Name); - } - - MemberReference GetCurrentMemberReference() - { - AstNode node = nodeStack.Peek(); - MemberReference memberRef = node.Annotation(); - if (memberRef == null && node.Role == Roles.TargetExpression && (node.Parent is InvocationExpression || node.Parent is ObjectCreateExpression)) { - memberRef = node.Parent.Annotation(); - } - if (node is IdentifierExpression && node.Role == Roles.TargetExpression && node.Parent is InvocationExpression && memberRef != null) { - var declaringType = memberRef.DeclaringType.Resolve(); - if (declaringType != null && declaringType.IsDelegate()) - return null; - } - return FilterMemberReference(memberRef); - } - - MemberReference FilterMemberReference(MemberReference memberRef) - { - if (memberRef == null) - return null; - - if (context.Settings.AutomaticEvents && memberRef is FieldDefinition) { - var field = (FieldDefinition)memberRef; - return field.DeclaringType.Events.FirstOrDefault(ev => ev.Name == field.Name) ?? memberRef; - } - - return memberRef; - } - - object GetCurrentLocalReference() - { - AstNode node = nodeStack.Peek(); - ILVariable variable = node.Annotation(); - if (variable != null) { - if (variable.OriginalParameter != null) - return variable.OriginalParameter; - //if (variable.OriginalVariable != null) - // return variable.OriginalVariable; - return variable; - } - - var gotoStatement = node as GotoStatement; - if (gotoStatement != null) - { - var method = nodeStack.Select(nd => nd.Annotation()).FirstOrDefault(mr => mr != null); - if (method != null) - return method.ToString() + gotoStatement.Label; - } - - return null; - } - - object GetCurrentLocalDefinition() - { - AstNode node = nodeStack.Peek(); - if (node is Identifier && node.Parent != null) - node = node.Parent; - - var parameterDef = node.Annotation(); - if (parameterDef != null) - return parameterDef; - - if (node is VariableInitializer || node is CatchClause || node is ForeachStatement) { - var variable = node.Annotation(); - if (variable != null) { - if (variable.OriginalParameter != null) - return variable.OriginalParameter; - //if (variable.OriginalVariable != null) - // return variable.OriginalVariable; - return variable; - } - } - - var label = node as LabelStatement; - if (label != null) { - var method = nodeStack.Select(nd => nd.Annotation()).FirstOrDefault(mr => mr != null); - if (method != null) - return method.ToString() + label.Label; - } - - return null; - } - - object GetCurrentDefinition() - { - if (nodeStack == null || nodeStack.Count == 0) - return null; - - var node = nodeStack.Peek(); - if (node is Identifier) - node = node.Parent; - if (IsDefinition(node)) - return node.Annotation(); - - return null; - } - - public override void WriteKeyword(Role role, string keyword) - { - output.Write(keyword); - } - - public override void WriteToken(Role role, string token) - { - // Attach member reference to token only if there's no identifier in the current node. - MemberReference memberRef = GetCurrentMemberReference(); - var node = nodeStack.Peek(); - if (memberRef != null && node.GetChildByRole(Roles.Identifier).IsNull) - output.WriteReference(token, memberRef); - else - output.Write(token); - } - - public override void Space() - { - output.Write(' '); - } - - public void OpenBrace(BraceStyle style) - { - if (braceLevelWithinType >= 0 || nodeStack.Peek() is TypeDeclaration) - braceLevelWithinType++; - if (nodeStack.OfType().Count() <= 1 || FoldBraces) { - output.MarkFoldStart(defaultCollapsed: braceLevelWithinType == 1); - } - output.WriteLine(); - output.WriteLine("{"); - output.Indent(); - } - - public void CloseBrace(BraceStyle style) - { - output.Unindent(); - output.Write('}'); - if (nodeStack.OfType().Count() <= 1 || FoldBraces) - output.MarkFoldEnd(); - if (braceLevelWithinType >= 0) - braceLevelWithinType--; - } - - public override void Indent() - { - output.Indent(); - } - - public override void Unindent() - { - output.Unindent(); - } - - public override void NewLine() - { - if (lastUsingDeclaration) { - output.MarkFoldEnd(); - lastUsingDeclaration = false; - } - lastEndOfLine = output.Location; - output.WriteLine(); - } - - public override void WriteComment(CommentType commentType, string content) - { - switch (commentType) { - case CommentType.SingleLine: - output.Write("//"); - output.WriteLine(content); - break; - case CommentType.MultiLine: - output.Write("/*"); - output.Write(content); - output.Write("*/"); - break; - case CommentType.Documentation: - bool isLastLine = !(nodeStack.Peek().NextSibling is Comment); - if (!inDocumentationComment && !isLastLine) { - inDocumentationComment = true; - output.MarkFoldStart("///" + content, true); - } - output.Write("///"); - output.Write(content); - if (inDocumentationComment && isLastLine) { - inDocumentationComment = false; - output.MarkFoldEnd(); - } - output.WriteLine(); - break; - default: - output.Write(content); - break; - } - } - - public override void WritePreProcessorDirective(PreProcessorDirectiveType type, string argument) - { - // pre-processor directive must start on its own line - output.Write('#'); - output.Write(type.ToString().ToLowerInvariant()); - if (!string.IsNullOrEmpty(argument)) { - output.Write(' '); - output.Write(argument); - } - output.WriteLine(); - } - - public override void WritePrimitiveValue(object value, string literalValue = null) - { - new TextWriterTokenWriter(new TextOutputWriter(output)).WritePrimitiveValue(value, literalValue); - } - - public override void WritePrimitiveType(string type) - { - output.Write(type); - if (type == "new") { - output.Write("()"); - } - } - - Stack startLocations = new Stack(); - Stack symbolsStack = new Stack(); - - public override void StartNode(AstNode node) - { - if (nodeStack.Count == 0) { - if (IsUsingDeclaration(node)) { - firstUsingDeclaration = !IsUsingDeclaration(node.PrevSibling); - lastUsingDeclaration = !IsUsingDeclaration(node.NextSibling); - } else { - firstUsingDeclaration = false; - lastUsingDeclaration = false; - } - } - nodeStack.Push(node); - startLocations.Push(output.Location); - - if (node is EntityDeclaration && node.Annotation() != null && node.GetChildByRole(Roles.Identifier).IsNull) - output.WriteDefinition("", node.Annotation(), false); - - if (node.Annotation() != null) { - symbolsStack.Push(node.Annotation()); - symbolsStack.Peek().StartLocation = startLocations.Peek(); - } - } - - private bool IsUsingDeclaration(AstNode node) - { - return node is UsingDeclaration || node is UsingAliasDeclaration; - } - - public override void EndNode(AstNode node) - { - if (nodeStack.Pop() != node) - throw new InvalidOperationException(); - - var startLocation = startLocations.Pop(); - - // code mappings - var ranges = node.Annotation>(); - if (symbolsStack.Count > 0 && ranges != null && ranges.Count > 0) { - // Ignore the newline which was printed at the end of the statement - TextLocation endLocation = (node is Statement) ? (lastEndOfLine ?? output.Location) : output.Location; - symbolsStack.Peek().SequencePoints.Add( - new SequencePoint() { - ILRanges = ILRange.OrderAndJoin(ranges).ToArray(), - StartLocation = startLocation, - EndLocation = endLocation - }); - } - - if (node.Annotation() != null) { - symbolsStack.Peek().EndLocation = output.Location; - output.AddDebugSymbols(symbolsStack.Pop()); - } - } - - private static bool IsDefinition(AstNode node) - { - return node is EntityDeclaration - || (node is VariableInitializer && node.Parent is FieldDeclaration) - || node is FixedVariableInitializer; - } - } -} diff --git a/ICSharpCode.Decompiler/CSharp/Analysis/ControlFlow.cs b/ICSharpCode.Decompiler/CSharp/Analysis/ControlFlow.cs deleted file mode 100644 index e505e4bce..000000000 --- a/ICSharpCode.Decompiler/CSharp/Analysis/ControlFlow.cs +++ /dev/null @@ -1,784 +0,0 @@ -// Copyright (c) 2010-2013 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.Generic; -using System.Diagnostics; -using System.Linq; -using System.Threading; -using ICSharpCode.Decompiler.CSharp.Resolver; -using ICSharpCode.Decompiler.CSharp.Syntax; -using ICSharpCode.Decompiler.CSharp.TypeSystem; -using ICSharpCode.Decompiler.Semantics; - -namespace ICSharpCode.Decompiler.CSharp.Analysis -{ - /// - /// Represents a node in the control flow graph of a C# method. - /// - public class ControlFlowNode - { - public readonly Statement PreviousStatement; - public readonly Statement NextStatement; - - public readonly ControlFlowNodeType Type; - - public readonly List Outgoing = new List(); - public readonly List Incoming = new List(); - - public ControlFlowNode(Statement previousStatement, Statement nextStatement, ControlFlowNodeType type) - { - if (previousStatement == null && nextStatement == null) - throw new ArgumentException("previousStatement and nextStatement must not be both null"); - this.PreviousStatement = previousStatement; - this.NextStatement = nextStatement; - this.Type = type; - } - } - - public enum ControlFlowNodeType - { - /// - /// Unknown node type - /// - None, - /// - /// Node in front of a statement - /// - StartNode, - /// - /// Node between two statements - /// - BetweenStatements, - /// - /// Node at the end of a statement list - /// - EndNode, - /// - /// Node representing the position before evaluating the condition of a loop. - /// - LoopCondition - } - - public class ControlFlowEdge - { - public readonly ControlFlowNode From; - public readonly ControlFlowNode To; - public readonly ControlFlowEdgeType Type; - - List jumpOutOfTryFinally; - - public ControlFlowEdge(ControlFlowNode from, ControlFlowNode to, ControlFlowEdgeType type) - { - if (from == null) - throw new ArgumentNullException("from"); - if (to == null) - throw new ArgumentNullException("to"); - this.From = from; - this.To = to; - this.Type = type; - } - - internal void AddJumpOutOfTryFinally(TryCatchStatement tryFinally) - { - if (jumpOutOfTryFinally == null) - jumpOutOfTryFinally = new List(); - jumpOutOfTryFinally.Add(tryFinally); - } - - /// - /// Gets whether this control flow edge is leaving any try-finally statements. - /// - public bool IsLeavingTryFinally { - get { return jumpOutOfTryFinally != null; } - } - - /// - /// Gets the try-finally statements that this control flow edge is leaving. - /// - public IEnumerable TryFinallyStatements { - get { return jumpOutOfTryFinally ?? Enumerable.Empty(); } - } - } - - public enum ControlFlowEdgeType - { - /// - /// Regular control flow. - /// - Normal, - /// - /// Conditional control flow (edge taken if condition is true) - /// - ConditionTrue, - /// - /// Conditional control flow (edge taken if condition is false) - /// - ConditionFalse, - /// - /// A jump statement (goto, goto case, break or continue) - /// - Jump - } - - /// - /// Constructs the control flow graph for C# statements. - /// - public class ControlFlowGraphBuilder - { - // Written according to the reachability rules in the C# spec (§8.1 End points and reachability) - - protected virtual ControlFlowNode CreateNode(Statement previousStatement, Statement nextStatement, ControlFlowNodeType type) - { - cancellationToken.ThrowIfCancellationRequested(); - return new ControlFlowNode(previousStatement, nextStatement, type); - } - - protected virtual ControlFlowEdge CreateEdge(ControlFlowNode from, ControlFlowNode to, ControlFlowEdgeType type) - { - cancellationToken.ThrowIfCancellationRequested(); - return new ControlFlowEdge(from, to, type); - } - - Statement rootStatement; - CSharpTypeResolveContext typeResolveContext; - Func resolver; - List nodes; - Dictionary labels; - List gotoStatements; - CancellationToken cancellationToken; - - internal IList BuildControlFlowGraph(Statement statement, Func resolver, CSharpTypeResolveContext typeResolveContext, CancellationToken cancellationToken) - { - NodeCreationVisitor nodeCreationVisitor = new NodeCreationVisitor(); - nodeCreationVisitor.builder = this; - try { - this.nodes = new List(); - this.labels = new Dictionary(); - this.gotoStatements = new List(); - this.rootStatement = statement; - this.resolver = resolver; - this.typeResolveContext = typeResolveContext; - this.cancellationToken = cancellationToken; - - ControlFlowNode entryPoint = CreateStartNode(statement); - statement.AcceptVisitor(nodeCreationVisitor, entryPoint); - - // Resolve goto statements: - foreach (ControlFlowNode gotoStmt in gotoStatements) { - string label = ((GotoStatement)gotoStmt.NextStatement).Label; - ControlFlowNode labelNode; - if (labels.TryGetValue(label, out labelNode)) - nodeCreationVisitor.Connect(gotoStmt, labelNode, ControlFlowEdgeType.Jump); - } - - AnnotateLeaveEdgesWithTryFinallyBlocks(); - - return nodes; - } finally { - this.nodes = null; - this.labels = null; - this.gotoStatements = null; - this.rootStatement = null; - this.resolver = null; - this.typeResolveContext = null; - this.cancellationToken = CancellationToken.None; - } - } - - void AnnotateLeaveEdgesWithTryFinallyBlocks() - { - foreach (ControlFlowEdge edge in nodes.SelectMany(n => n.Outgoing)) { - if (edge.Type != ControlFlowEdgeType.Jump) { - // Only jumps are potential candidates for leaving try-finally blocks. - // Note that the regular edges leaving try or catch blocks are already annotated by the visitor. - continue; - } - Statement gotoStatement = edge.From.NextStatement; - Debug.Assert(gotoStatement is GotoStatement || gotoStatement is GotoDefaultStatement || gotoStatement is GotoCaseStatement || gotoStatement is BreakStatement || gotoStatement is ContinueStatement); - Statement targetStatement = edge.To.PreviousStatement ?? edge.To.NextStatement; - if (gotoStatement.Parent == targetStatement.Parent) - continue; - HashSet targetParentTryCatch = new HashSet(targetStatement.Ancestors.OfType()); - for (AstNode node = gotoStatement.Parent; node != null; node = node.Parent) { - TryCatchStatement leftTryCatch = node as TryCatchStatement; - if (leftTryCatch != null) { - if (targetParentTryCatch.Contains(leftTryCatch)) - break; - if (!leftTryCatch.FinallyBlock.IsNull) - edge.AddJumpOutOfTryFinally(leftTryCatch); - } - } - } - } - - #region Create*Node - ControlFlowNode CreateStartNode(Statement statement) - { - if (statement.IsNull) - return null; - ControlFlowNode node = CreateNode(null, statement, ControlFlowNodeType.StartNode); - nodes.Add(node); - return node; - } - - ControlFlowNode CreateSpecialNode(Statement statement, ControlFlowNodeType type, bool addToNodeList = true) - { - ControlFlowNode node = CreateNode(null, statement, type); - if (addToNodeList) - nodes.Add(node); - return node; - } - - ControlFlowNode CreateEndNode(Statement statement, bool addToNodeList = true) - { - Statement nextStatement; - if (statement == rootStatement) { - nextStatement = null; - } else { - // Find the next statement in the same role: - AstNode next = statement; - do { - next = next.NextSibling; - } while (next != null && next.Role != statement.Role); - nextStatement = next as Statement; - } - ControlFlowNodeType type = nextStatement != null ? ControlFlowNodeType.BetweenStatements : ControlFlowNodeType.EndNode; - ControlFlowNode node = CreateNode(statement, nextStatement, type); - if (addToNodeList) - nodes.Add(node); - return node; - } - #endregion - - #region Constant evaluation - /// - /// Gets/Sets whether to handle only primitive expressions as constants (no complex expressions like "a + b"). - /// - public bool EvaluateOnlyPrimitiveConstants { get; set; } - - /// - /// Evaluates an expression. - /// - /// The constant value of the expression; or null if the expression is not a constant. - ResolveResult EvaluateConstant(Expression expr) - { - if (expr.IsNull) - return null; - if (EvaluateOnlyPrimitiveConstants) { - if (!(expr is PrimitiveExpression || expr is NullReferenceExpression)) - return null; - } - return resolver(expr, cancellationToken); - } - - /// - /// Evaluates an expression. - /// - /// The value of the constant boolean expression; or null if the value is not a constant boolean expression. - bool? EvaluateCondition(Expression expr) - { - ResolveResult rr = EvaluateConstant(expr); - if (rr != null && rr.IsCompileTimeConstant) - return rr.ConstantValue as bool?; - else - return null; - } - - bool AreEqualConstants(ResolveResult c1, ResolveResult c2) - { - if (c1 == null || c2 == null || !c1.IsCompileTimeConstant || !c2.IsCompileTimeConstant) - return false; - CSharpResolver r = new CSharpResolver(typeResolveContext); - ResolveResult c = r.ResolveBinaryOperator(BinaryOperatorType.Equality, c1, c2); - return c.IsCompileTimeConstant && (c.ConstantValue as bool?) == true; - } - #endregion - - sealed class NodeCreationVisitor : DepthFirstAstVisitor - { - // 'data' parameter: input control flow node (start of statement being visited) - // Return value: result control flow node (end of statement being visited) - - internal ControlFlowGraphBuilder builder; - Stack breakTargets = new Stack(); - Stack continueTargets = new Stack(); - List gotoCaseOrDefault = new List(); - - internal ControlFlowEdge Connect(ControlFlowNode from, ControlFlowNode to, ControlFlowEdgeType type = ControlFlowEdgeType.Normal) - { - if (from == null || to == null) - return null; - ControlFlowEdge edge = builder.CreateEdge(from, to, type); - from.Outgoing.Add(edge); - to.Incoming.Add(edge); - return edge; - } - - /// - /// Creates an end node for stmt and connects from with the new node. - /// - ControlFlowNode CreateConnectedEndNode(Statement stmt, ControlFlowNode from) - { - ControlFlowNode newNode = builder.CreateEndNode(stmt); - Connect(from, newNode); - return newNode; - } - - protected override ControlFlowNode VisitChildren(AstNode node, ControlFlowNode data) - { - // We have overrides for all possible statements and should visit statements only. - throw new NotSupportedException(); - } - - public override ControlFlowNode VisitBlockStatement(BlockStatement blockStatement, ControlFlowNode data) - { - // C# 4.0 spec: §8.2 Blocks - ControlFlowNode childNode = HandleStatementList(blockStatement.Statements, data); - return CreateConnectedEndNode(blockStatement, childNode); - } - - ControlFlowNode HandleStatementList(AstNodeCollection statements, ControlFlowNode source) - { - ControlFlowNode childNode = null; - foreach (Statement stmt in statements) { - if (childNode == null) { - childNode = builder.CreateStartNode(stmt); - if (source != null) - Connect(source, childNode); - } - Debug.Assert(childNode.NextStatement == stmt); - childNode = stmt.AcceptVisitor(this, childNode); - Debug.Assert(childNode.PreviousStatement == stmt); - } - return childNode ?? source; - } - - public override ControlFlowNode VisitEmptyStatement(EmptyStatement emptyStatement, ControlFlowNode data) - { - return CreateConnectedEndNode(emptyStatement, data); - } - - public override ControlFlowNode VisitLabelStatement(LabelStatement labelStatement, ControlFlowNode data) - { - ControlFlowNode end = CreateConnectedEndNode(labelStatement, data); - builder.labels[labelStatement.Label] = end; - return end; - } - - public override ControlFlowNode VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement, ControlFlowNode data) - { - return CreateConnectedEndNode(variableDeclarationStatement, data); - } - - public override ControlFlowNode VisitExpressionStatement(ExpressionStatement expressionStatement, ControlFlowNode data) - { - return CreateConnectedEndNode(expressionStatement, data); - } - - public override ControlFlowNode VisitIfElseStatement(IfElseStatement ifElseStatement, ControlFlowNode data) - { - bool? cond = builder.EvaluateCondition(ifElseStatement.Condition); - - ControlFlowNode trueBegin = builder.CreateStartNode(ifElseStatement.TrueStatement); - if (cond != false) - Connect(data, trueBegin, ControlFlowEdgeType.ConditionTrue); - ControlFlowNode trueEnd = ifElseStatement.TrueStatement.AcceptVisitor(this, trueBegin); - - ControlFlowNode falseBegin = builder.CreateStartNode(ifElseStatement.FalseStatement); - if (cond != true) - Connect(data, falseBegin, ControlFlowEdgeType.ConditionFalse); - ControlFlowNode falseEnd = ifElseStatement.FalseStatement.AcceptVisitor(this, falseBegin); - // (if no else statement exists, both falseBegin and falseEnd will be null) - - ControlFlowNode end = builder.CreateEndNode(ifElseStatement); - Connect(trueEnd, end); - if (falseEnd != null) { - Connect(falseEnd, end); - } else if (cond != true) { - Connect(data, end, ControlFlowEdgeType.ConditionFalse); - } - return end; - } - - public override ControlFlowNode VisitSwitchStatement(SwitchStatement switchStatement, ControlFlowNode data) - { - // First, figure out which switch section will get called (if the expression is constant): - ResolveResult constant = builder.EvaluateConstant(switchStatement.Expression); - SwitchSection defaultSection = null; - SwitchSection sectionMatchedByConstant = null; - foreach (SwitchSection section in switchStatement.SwitchSections) { - foreach (CaseLabel label in section.CaseLabels) { - if (label.Expression.IsNull) { - defaultSection = section; - } else if (constant != null && constant.IsCompileTimeConstant) { - ResolveResult labelConstant = builder.EvaluateConstant(label.Expression); - if (builder.AreEqualConstants(constant, labelConstant)) - sectionMatchedByConstant = section; - } - } - } - if (constant != null && constant.IsCompileTimeConstant && sectionMatchedByConstant == null) - sectionMatchedByConstant = defaultSection; - - int gotoCaseOrDefaultInOuterScope = gotoCaseOrDefault.Count; - List sectionStartNodes = new List(); - - ControlFlowNode end = builder.CreateEndNode(switchStatement, addToNodeList: false); - breakTargets.Push(end); - foreach (SwitchSection section in switchStatement.SwitchSections) { - int sectionStartNodeID = builder.nodes.Count; - if (constant == null || !constant.IsCompileTimeConstant || section == sectionMatchedByConstant) { - HandleStatementList(section.Statements, data); - } else { - // This section is unreachable: pass null to HandleStatementList. - HandleStatementList(section.Statements, null); - } - // Don't bother connecting the ends of the sections: the 'break' statement takes care of that. - - // Store the section start node for 'goto case' statements. - sectionStartNodes.Add(sectionStartNodeID < builder.nodes.Count ? builder.nodes[sectionStartNodeID] : null); - } - breakTargets.Pop(); - if (defaultSection == null && sectionMatchedByConstant == null) { - Connect(data, end); - } - - if (gotoCaseOrDefault.Count > gotoCaseOrDefaultInOuterScope) { - // Resolve 'goto case' statements: - for (int i = gotoCaseOrDefaultInOuterScope; i < gotoCaseOrDefault.Count; i++) { - ControlFlowNode gotoCaseNode = gotoCaseOrDefault[i]; - GotoCaseStatement gotoCaseStatement = gotoCaseNode.NextStatement as GotoCaseStatement; - ResolveResult gotoCaseConstant = null; - if (gotoCaseStatement != null) { - gotoCaseConstant = builder.EvaluateConstant(gotoCaseStatement.LabelExpression); - } - int targetSectionIndex = -1; - int currentSectionIndex = 0; - foreach (SwitchSection section in switchStatement.SwitchSections) { - foreach (CaseLabel label in section.CaseLabels) { - if (gotoCaseStatement != null) { - // goto case - if (!label.Expression.IsNull) { - ResolveResult labelConstant = builder.EvaluateConstant(label.Expression); - if (builder.AreEqualConstants(gotoCaseConstant, labelConstant)) - targetSectionIndex = currentSectionIndex; - } - } else { - // goto default - if (label.Expression.IsNull) - targetSectionIndex = currentSectionIndex; - } - } - currentSectionIndex++; - } - if (targetSectionIndex >= 0 && sectionStartNodes[targetSectionIndex] != null) - Connect(gotoCaseNode, sectionStartNodes[targetSectionIndex], ControlFlowEdgeType.Jump); - else - Connect(gotoCaseNode, end, ControlFlowEdgeType.Jump); - } - gotoCaseOrDefault.RemoveRange(gotoCaseOrDefaultInOuterScope, gotoCaseOrDefault.Count - gotoCaseOrDefaultInOuterScope); - } - - builder.nodes.Add(end); - return end; - } - - public override ControlFlowNode VisitGotoCaseStatement(GotoCaseStatement gotoCaseStatement, ControlFlowNode data) - { - gotoCaseOrDefault.Add(data); - return builder.CreateEndNode(gotoCaseStatement); - } - - public override ControlFlowNode VisitGotoDefaultStatement(GotoDefaultStatement gotoDefaultStatement, ControlFlowNode data) - { - gotoCaseOrDefault.Add(data); - return builder.CreateEndNode(gotoDefaultStatement); - } - - public override ControlFlowNode VisitWhileStatement(WhileStatement whileStatement, ControlFlowNode data) - { - // while (cond) { embeddedStmt; } - ControlFlowNode end = builder.CreateEndNode(whileStatement, addToNodeList: false); - ControlFlowNode conditionNode = builder.CreateSpecialNode(whileStatement, ControlFlowNodeType.LoopCondition); - breakTargets.Push(end); - continueTargets.Push(conditionNode); - - Connect(data, conditionNode); - - bool? cond = builder.EvaluateCondition(whileStatement.Condition); - ControlFlowNode bodyStart = builder.CreateStartNode(whileStatement.EmbeddedStatement); - if (cond != false) - Connect(conditionNode, bodyStart, ControlFlowEdgeType.ConditionTrue); - ControlFlowNode bodyEnd = whileStatement.EmbeddedStatement.AcceptVisitor(this, bodyStart); - Connect(bodyEnd, conditionNode); - if (cond != true) - Connect(conditionNode, end, ControlFlowEdgeType.ConditionFalse); - - breakTargets.Pop(); - continueTargets.Pop(); - builder.nodes.Add(end); - return end; - } - - public override ControlFlowNode VisitDoWhileStatement(DoWhileStatement doWhileStatement, ControlFlowNode data) - { - // do { embeddedStmt; } while(cond); - ControlFlowNode end = builder.CreateEndNode(doWhileStatement, addToNodeList: false); - ControlFlowNode conditionNode = builder.CreateSpecialNode(doWhileStatement, ControlFlowNodeType.LoopCondition, addToNodeList: false); - breakTargets.Push(end); - continueTargets.Push(conditionNode); - - ControlFlowNode bodyStart = builder.CreateStartNode(doWhileStatement.EmbeddedStatement); - Connect(data, bodyStart); - ControlFlowNode bodyEnd = doWhileStatement.EmbeddedStatement.AcceptVisitor(this, bodyStart); - Connect(bodyEnd, conditionNode); - - bool? cond = builder.EvaluateCondition(doWhileStatement.Condition); - if (cond != false) - Connect(conditionNode, bodyStart, ControlFlowEdgeType.ConditionTrue); - if (cond != true) - Connect(conditionNode, end, ControlFlowEdgeType.ConditionFalse); - - breakTargets.Pop(); - continueTargets.Pop(); - builder.nodes.Add(conditionNode); - builder.nodes.Add(end); - return end; - } - - public override ControlFlowNode VisitForStatement(ForStatement forStatement, ControlFlowNode data) - { - data = HandleStatementList(forStatement.Initializers, data); - // for (initializers ; cond; iterators) { embeddedStmt; } - ControlFlowNode end = builder.CreateEndNode(forStatement, addToNodeList: false); - ControlFlowNode conditionNode = builder.CreateSpecialNode(forStatement, ControlFlowNodeType.LoopCondition); - Connect(data, conditionNode); - - int iteratorStartNodeID = builder.nodes.Count; - ControlFlowNode iteratorEnd = HandleStatementList(forStatement.Iterators, null); - ControlFlowNode iteratorStart; - if (iteratorEnd != null) { - iteratorStart = builder.nodes[iteratorStartNodeID]; - Connect(iteratorEnd, conditionNode); - } else { - iteratorStart = conditionNode; - } - - breakTargets.Push(end); - continueTargets.Push(iteratorStart); - - ControlFlowNode bodyStart = builder.CreateStartNode(forStatement.EmbeddedStatement); - ControlFlowNode bodyEnd = forStatement.EmbeddedStatement.AcceptVisitor(this, bodyStart); - Connect(bodyEnd, iteratorStart); - - breakTargets.Pop(); - continueTargets.Pop(); - - bool? cond = forStatement.Condition.IsNull ? true : builder.EvaluateCondition(forStatement.Condition); - if (cond != false) - Connect(conditionNode, bodyStart, ControlFlowEdgeType.ConditionTrue); - if (cond != true) - Connect(conditionNode, end, ControlFlowEdgeType.ConditionFalse); - - builder.nodes.Add(end); - return end; - } - - ControlFlowNode HandleEmbeddedStatement(Statement embeddedStatement, ControlFlowNode source) - { - if (embeddedStatement == null || embeddedStatement.IsNull) - return source; - ControlFlowNode bodyStart = builder.CreateStartNode(embeddedStatement); - if (source != null) - Connect(source, bodyStart); - return embeddedStatement.AcceptVisitor(this, bodyStart); - } - - public override ControlFlowNode VisitForeachStatement(ForeachStatement foreachStatement, ControlFlowNode data) - { - // foreach (...) { embeddedStmt } - ControlFlowNode end = builder.CreateEndNode(foreachStatement, addToNodeList: false); - ControlFlowNode conditionNode = builder.CreateSpecialNode(foreachStatement, ControlFlowNodeType.LoopCondition); - Connect(data, conditionNode); - - breakTargets.Push(end); - continueTargets.Push(conditionNode); - - ControlFlowNode bodyEnd = HandleEmbeddedStatement(foreachStatement.EmbeddedStatement, conditionNode); - Connect(bodyEnd, conditionNode); - - breakTargets.Pop(); - continueTargets.Pop(); - - Connect(conditionNode, end); - builder.nodes.Add(end); - return end; - } - - public override ControlFlowNode VisitBreakStatement(BreakStatement breakStatement, ControlFlowNode data) - { - if (breakTargets.Count > 0) - Connect(data, breakTargets.Peek(), ControlFlowEdgeType.Jump); - return builder.CreateEndNode(breakStatement); - } - - public override ControlFlowNode VisitContinueStatement(ContinueStatement continueStatement, ControlFlowNode data) - { - if (continueTargets.Count > 0) - Connect(data, continueTargets.Peek(), ControlFlowEdgeType.Jump); - return builder.CreateEndNode(continueStatement); - } - - public override ControlFlowNode VisitGotoStatement(GotoStatement gotoStatement, ControlFlowNode data) - { - builder.gotoStatements.Add(data); - return builder.CreateEndNode(gotoStatement); - } - - public override ControlFlowNode VisitReturnStatement(ReturnStatement returnStatement, ControlFlowNode data) - { - return builder.CreateEndNode(returnStatement); // end not connected with data - } - - public override ControlFlowNode VisitThrowStatement(ThrowStatement throwStatement, ControlFlowNode data) - { - return builder.CreateEndNode(throwStatement); // end not connected with data - } - - public override ControlFlowNode VisitTryCatchStatement(TryCatchStatement tryCatchStatement, ControlFlowNode data) - { - ControlFlowNode end = builder.CreateEndNode(tryCatchStatement, addToNodeList: false); - var edge = Connect(HandleEmbeddedStatement(tryCatchStatement.TryBlock, data), end); - if (!tryCatchStatement.FinallyBlock.IsNull) - edge.AddJumpOutOfTryFinally(tryCatchStatement); - foreach (CatchClause cc in tryCatchStatement.CatchClauses) { - edge = Connect(HandleEmbeddedStatement(cc.Body, data), end); - if (!tryCatchStatement.FinallyBlock.IsNull) - edge.AddJumpOutOfTryFinally(tryCatchStatement); - } - if (!tryCatchStatement.FinallyBlock.IsNull) { - // Don't connect the end of the try-finally block to anything. - // Consumers of the CFG will have to special-case try-finally. - HandleEmbeddedStatement(tryCatchStatement.FinallyBlock, data); - } - builder.nodes.Add(end); - return end; - } - - public override ControlFlowNode VisitCheckedStatement(CheckedStatement checkedStatement, ControlFlowNode data) - { - ControlFlowNode bodyEnd = HandleEmbeddedStatement(checkedStatement.Body, data); - return CreateConnectedEndNode(checkedStatement, bodyEnd); - } - - public override ControlFlowNode VisitUncheckedStatement(UncheckedStatement uncheckedStatement, ControlFlowNode data) - { - ControlFlowNode bodyEnd = HandleEmbeddedStatement(uncheckedStatement.Body, data); - return CreateConnectedEndNode(uncheckedStatement, bodyEnd); - } - - public override ControlFlowNode VisitLockStatement(LockStatement lockStatement, ControlFlowNode data) - { - ControlFlowNode bodyEnd = HandleEmbeddedStatement(lockStatement.EmbeddedStatement, data); - return CreateConnectedEndNode(lockStatement, bodyEnd); - } - - public override ControlFlowNode VisitUsingStatement(UsingStatement usingStatement, ControlFlowNode data) - { - data = HandleEmbeddedStatement(usingStatement.ResourceAcquisition as Statement, data); - ControlFlowNode bodyEnd = HandleEmbeddedStatement(usingStatement.EmbeddedStatement, data); - return CreateConnectedEndNode(usingStatement, bodyEnd); - } - - public override ControlFlowNode VisitYieldReturnStatement(YieldReturnStatement yieldStatement, ControlFlowNode data) - { - return CreateConnectedEndNode(yieldStatement, data); - } - - public override ControlFlowNode VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement, ControlFlowNode data) - { - return builder.CreateEndNode(yieldBreakStatement); // end not connected with data - } - - public override ControlFlowNode VisitUnsafeStatement(UnsafeStatement unsafeStatement, ControlFlowNode data) - { - ControlFlowNode bodyEnd = HandleEmbeddedStatement(unsafeStatement.Body, data); - return CreateConnectedEndNode(unsafeStatement, bodyEnd); - } - - public override ControlFlowNode VisitFixedStatement(FixedStatement fixedStatement, ControlFlowNode data) - { - ControlFlowNode bodyEnd = HandleEmbeddedStatement(fixedStatement.EmbeddedStatement, data); - return CreateConnectedEndNode(fixedStatement, bodyEnd); - } - } - - /// - /// Debugging helper that exports a control flow graph. - /// - //public static GraphVizGraph ExportGraph(IList nodes) - //{ - // GraphVizGraph g = new GraphVizGraph(); - // GraphVizNode[] n = new GraphVizNode[nodes.Count]; - // Dictionary dict = new Dictionary(); - // for (int i = 0; i < n.Length; i++) { - // dict.Add(nodes[i], i); - // n[i] = new GraphVizNode(i); - // string name = "#" + i + " = "; - // switch (nodes[i].Type) { - // case ControlFlowNodeType.StartNode: - // case ControlFlowNodeType.BetweenStatements: - // name += nodes[i].NextStatement.DebugToString(); - // break; - // case ControlFlowNodeType.EndNode: - // name += "End of " + nodes[i].PreviousStatement.DebugToString(); - // break; - // case ControlFlowNodeType.LoopCondition: - // name += "Condition in " + nodes[i].NextStatement.DebugToString(); - // break; - // default: - // name += "?"; - // break; - // } - // n[i].label = name; - // g.AddNode(n[i]); - // } - // for (int i = 0; i < n.Length; i++) { - // foreach (ControlFlowEdge edge in nodes[i].Outgoing) { - // GraphVizEdge ge = new GraphVizEdge(i, dict[edge.To]); - // if (edge.IsLeavingTryFinally) - // ge.style = "dashed"; - // switch (edge.Type) { - // case ControlFlowEdgeType.ConditionTrue: - // ge.color = "green"; - // break; - // case ControlFlowEdgeType.ConditionFalse: - // ge.color = "red"; - // break; - // case ControlFlowEdgeType.Jump: - // ge.color = "blue"; - // break; - // } - // g.AddEdge(ge); - // } - // } - // return g; - //} - } -} diff --git a/ICSharpCode.Decompiler/CSharp/Analysis/DefiniteAssignmentAnalysis.cs b/ICSharpCode.Decompiler/CSharp/Analysis/DefiniteAssignmentAnalysis.cs deleted file mode 100644 index 70ab770bb..000000000 --- a/ICSharpCode.Decompiler/CSharp/Analysis/DefiniteAssignmentAnalysis.cs +++ /dev/null @@ -1,750 +0,0 @@ -// Copyright (c) 2010-2013 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.Generic; -using System.Diagnostics; -using System.Linq; -using System.Threading; -using ICSharpCode.Decompiler.CSharp.Syntax; -using ICSharpCode.Decompiler.CSharp.TypeSystem; -using ICSharpCode.Decompiler.Semantics; -using ICSharpCode.Decompiler.TypeSystem.Implementation; - -namespace ICSharpCode.Decompiler.CSharp.Analysis -{ - /// - /// Represents the definite assignment status of a variable at a specific location. - /// - public enum DefiniteAssignmentStatus - { - /// - /// The variable might be assigned or unassigned. - /// - PotentiallyAssigned, - /// - /// The variable is definitely assigned. - /// - DefinitelyAssigned, - /// - /// The variable is definitely assigned iff the expression results in the value 'true'. - /// - AssignedAfterTrueExpression, - /// - /// The variable is definitely assigned iff the expression results in the value 'false'. - /// - AssignedAfterFalseExpression, - /// - /// The code is unreachable. - /// - CodeUnreachable - } - - /// - /// Implements the C# definite assignment analysis (C# 4.0 Spec: §5.3 Definite assignment) - /// - public class DefiniteAssignmentAnalysis - { - sealed class DefiniteAssignmentNode : ControlFlowNode - { - public int Index; - public DefiniteAssignmentStatus NodeStatus; - - public DefiniteAssignmentNode(Statement previousStatement, Statement nextStatement, ControlFlowNodeType type) - : base(previousStatement, nextStatement, type) - { - } - } - - sealed class DerivedControlFlowGraphBuilder : ControlFlowGraphBuilder - { - protected override ControlFlowNode CreateNode(Statement previousStatement, Statement nextStatement, ControlFlowNodeType type) - { - return new DefiniteAssignmentNode(previousStatement, nextStatement, type); - } - } - - readonly DefiniteAssignmentVisitor visitor = new DefiniteAssignmentVisitor(); - readonly List allNodes = new List(); - readonly Dictionary beginNodeDict = new Dictionary(); - readonly Dictionary endNodeDict = new Dictionary(); - readonly Dictionary conditionNodeDict = new Dictionary(); - readonly Func resolve; - Dictionary edgeStatus = new Dictionary(); - - string variableName; - List unassignedVariableUses = new List(); - int analyzedRangeStart, analyzedRangeEnd; - CancellationToken analysisCancellationToken; - - Queue nodesWithModifiedInput = new Queue(); - - public DefiniteAssignmentAnalysis(Statement rootStatement, Func resolve, CSharpTypeResolveContext context, CancellationToken cancellationToken) - { - if (rootStatement == null) - throw new ArgumentNullException("rootStatement"); - if (resolve == null) - throw new ArgumentNullException("resolve"); - this.resolve = resolve; - - visitor.analysis = this; - DerivedControlFlowGraphBuilder cfgBuilder = new DerivedControlFlowGraphBuilder(); - if (context.Compilation.MainAssembly.UnresolvedAssembly is MinimalCorlib) { - cfgBuilder.EvaluateOnlyPrimitiveConstants = true; - } - allNodes.AddRange(cfgBuilder.BuildControlFlowGraph(rootStatement, resolve, context, cancellationToken).Cast()); - for (int i = 0; i < allNodes.Count; i++) { - DefiniteAssignmentNode node = allNodes[i]; - node.Index = i; // assign numbers to the nodes - if (node.Type == ControlFlowNodeType.StartNode || node.Type == ControlFlowNodeType.BetweenStatements) { - // Anonymous methods have separate control flow graphs, but we also need to analyze those. - // Iterate backwards so that anonymous methods are inserted in the correct order - for (AstNode child = node.NextStatement.LastChild; child != null; child = child.PrevSibling) { - InsertAnonymousMethods(i + 1, child, cfgBuilder, context, cancellationToken); - } - } - // Now register the node in the dictionaries: - if (node.Type == ControlFlowNodeType.StartNode || node.Type == ControlFlowNodeType.BetweenStatements) - beginNodeDict.Add(node.NextStatement, node); - if (node.Type == ControlFlowNodeType.BetweenStatements || node.Type == ControlFlowNodeType.EndNode) - endNodeDict.Add(node.PreviousStatement, node); - if (node.Type == ControlFlowNodeType.LoopCondition) - conditionNodeDict.Add(node.NextStatement, node); - } - // Verify that we created nodes for all statements: - Debug.Assert(!rootStatement.DescendantsAndSelf.OfType().Except(allNodes.Select(n => n.NextStatement)).Any()); - // Verify that we put all nodes into the dictionaries: - Debug.Assert(rootStatement.DescendantsAndSelf.OfType().All(stmt => beginNodeDict.ContainsKey(stmt))); - Debug.Assert(rootStatement.DescendantsAndSelf.OfType().All(stmt => endNodeDict.ContainsKey(stmt))); - - this.analyzedRangeStart = 0; - this.analyzedRangeEnd = allNodes.Count - 1; - } - - void InsertAnonymousMethods(int insertPos, AstNode node, ControlFlowGraphBuilder cfgBuilder, CSharpTypeResolveContext context, CancellationToken cancellationToken) - { - // Ignore any statements, as those have their own ControlFlowNode and get handled separately - if (node is Statement) - return; - AnonymousMethodExpression ame = node as AnonymousMethodExpression; - if (ame != null) { - allNodes.InsertRange(insertPos, cfgBuilder.BuildControlFlowGraph(ame.Body, resolve, context, cancellationToken).Cast()); - return; - } - LambdaExpression lambda = node as LambdaExpression; - if (lambda != null && lambda.Body is Statement) { - allNodes.InsertRange(insertPos, cfgBuilder.BuildControlFlowGraph((Statement)lambda.Body, resolve, context, cancellationToken).Cast()); - return; - } - // Descend into child expressions - // Iterate backwards so that anonymous methods are inserted in the correct order - for (AstNode child = node.LastChild; child != null; child = child.PrevSibling) { - InsertAnonymousMethods(insertPos, child, cfgBuilder, context, cancellationToken); - } - } - - /// - /// Gets the unassigned usages of the previously analyzed variable. - /// - public IList UnassignedVariableUses { - get { - return unassignedVariableUses.AsReadOnly(); - } - } - - /// - /// Sets the range of statements to be analyzed. - /// This method can be used to restrict the analysis to only a part of the method. - /// Only the control flow paths that are fully contained within the selected part will be analyzed. - /// - /// By default, both 'start' and 'end' are inclusive. - public void SetAnalyzedRange(Statement start, Statement end, bool startInclusive = true, bool endInclusive = true) - { - var dictForStart = startInclusive ? beginNodeDict : endNodeDict; - var dictForEnd = endInclusive ? endNodeDict : beginNodeDict; - Debug.Assert(dictForStart.ContainsKey(start) && dictForEnd.ContainsKey(end)); - int startIndex = dictForStart[start].Index; - int endIndex = dictForEnd[end].Index; - if (startIndex > endIndex) - throw new ArgumentException("The start statement must be lexically preceding the end statement"); - this.analyzedRangeStart = startIndex; - this.analyzedRangeEnd = endIndex; - } - - public void Analyze(string variable, DefiniteAssignmentStatus initialStatus = DefiniteAssignmentStatus.PotentiallyAssigned, CancellationToken cancellationToken = default(CancellationToken)) - { - this.analysisCancellationToken = cancellationToken; - this.variableName = variable; - try { - // Reset the status: - unassignedVariableUses.Clear(); - foreach (DefiniteAssignmentNode node in allNodes) { - node.NodeStatus = DefiniteAssignmentStatus.CodeUnreachable; - foreach (ControlFlowEdge edge in node.Outgoing) - edgeStatus[edge] = DefiniteAssignmentStatus.CodeUnreachable; - } - - ChangeNodeStatus(allNodes[analyzedRangeStart], initialStatus); - // Iterate as long as the input status of some nodes is changing: - while (nodesWithModifiedInput.Count > 0) { - DefiniteAssignmentNode node = nodesWithModifiedInput.Dequeue(); - DefiniteAssignmentStatus inputStatus = DefiniteAssignmentStatus.CodeUnreachable; - foreach (ControlFlowEdge edge in node.Incoming) { - inputStatus = MergeStatus(inputStatus, edgeStatus[edge]); - } - ChangeNodeStatus(node, inputStatus); - } - } finally { - this.analysisCancellationToken = CancellationToken.None; - this.variableName = null; - } - } - - public DefiniteAssignmentStatus GetStatusBefore(Statement statement) - { - return beginNodeDict[statement].NodeStatus; - } - - public DefiniteAssignmentStatus GetStatusAfter(Statement statement) - { - return endNodeDict[statement].NodeStatus; - } - - public DefiniteAssignmentStatus GetStatusBeforeLoopCondition(Statement statement) - { - return conditionNodeDict[statement].NodeStatus; - } - - /*/// - /// Exports the CFG. This method is intended to help debugging issues related to definite assignment. - /// - public GraphVizGraph ExportGraph() - { - GraphVizGraph g = new GraphVizGraph(); - g.Title = "DefiniteAssignment - " + variableName; - for (int i = 0; i < allNodes.Count; i++) { - string name = "#" + i + " = " + allNodes[i].NodeStatus.ToString() + Environment.NewLine; - switch (allNodes[i].Type) { - case ControlFlowNodeType.StartNode: - case ControlFlowNodeType.BetweenStatements: - name += allNodes[i].NextStatement.ToString(); - break; - case ControlFlowNodeType.EndNode: - name += "End of " + allNodes[i].PreviousStatement.ToString(); - break; - case ControlFlowNodeType.LoopCondition: - name += "Condition in " + allNodes[i].NextStatement.ToString(); - break; - default: - name += allNodes[i].Type.ToString(); - break; - } - g.AddNode(new GraphVizNode(i) { label = name }); - foreach (ControlFlowEdge edge in allNodes[i].Outgoing) { - GraphVizEdge ge = new GraphVizEdge(i, ((DefiniteAssignmentNode)edge.To).Index); - if (edgeStatus.Count > 0) - ge.label = edgeStatus[edge].ToString(); - if (edge.IsLeavingTryFinally) - ge.style = "dashed"; - switch (edge.Type) { - case ControlFlowEdgeType.ConditionTrue: - ge.color = "green"; - break; - case ControlFlowEdgeType.ConditionFalse: - ge.color = "red"; - break; - case ControlFlowEdgeType.Jump: - ge.color = "blue"; - break; - } - g.AddEdge(ge); - } - } - return g; - }*/ - - static DefiniteAssignmentStatus MergeStatus(DefiniteAssignmentStatus a, DefiniteAssignmentStatus b) - { - // The result will be DefinitelyAssigned if at least one incoming edge is DefinitelyAssigned and all others are unreachable. - // The result will be DefinitelyUnassigned if at least one incoming edge is DefinitelyUnassigned and all others are unreachable. - // The result will be Unreachable if all incoming edges are unreachable. - // Otherwise, the result will be PotentiallyAssigned. - - if (a == b) - return a; - else if (a == DefiniteAssignmentStatus.CodeUnreachable) - return b; - else if (b == DefiniteAssignmentStatus.CodeUnreachable) - return a; - else - return DefiniteAssignmentStatus.PotentiallyAssigned; - } - - void ChangeNodeStatus (DefiniteAssignmentNode node, DefiniteAssignmentStatus inputStatus) - { - if (node.NodeStatus == inputStatus) - return; - node.NodeStatus = inputStatus; - DefiniteAssignmentStatus outputStatus; - switch (node.Type) { - case ControlFlowNodeType.StartNode: - case ControlFlowNodeType.BetweenStatements: - if (node.NextStatement is IfElseStatement) { - // Handle if-else as a condition node - goto case ControlFlowNodeType.LoopCondition; - } - if (inputStatus == DefiniteAssignmentStatus.DefinitelyAssigned) { - // There isn't any way to un-assign variables, so we don't have to check the expression - // if the status already is definitely assigned. - outputStatus = DefiniteAssignmentStatus.DefinitelyAssigned; - } else { - outputStatus = CleanSpecialValues (node.NextStatement.AcceptVisitor (visitor, inputStatus)); - } - break; - case ControlFlowNodeType.EndNode: - outputStatus = inputStatus; - if (node.PreviousStatement.Role == TryCatchStatement.FinallyBlockRole - && (outputStatus == DefiniteAssignmentStatus.DefinitelyAssigned || outputStatus == DefiniteAssignmentStatus.PotentiallyAssigned)) { - TryCatchStatement tryFinally = (TryCatchStatement)node.PreviousStatement.Parent; - // Changing the status on a finally block potentially changes the status of all edges leaving that finally block: - foreach (ControlFlowEdge edge in allNodes.SelectMany(n => n.Outgoing)) { - if (edge.IsLeavingTryFinally && edge.TryFinallyStatements.Contains (tryFinally)) { - DefiniteAssignmentStatus s = edgeStatus [edge]; - if (s == DefiniteAssignmentStatus.PotentiallyAssigned) { - ChangeEdgeStatus (edge, outputStatus); - } - } - } - } - break; - case ControlFlowNodeType.LoopCondition: - ForeachStatement foreachStmt = node.NextStatement as ForeachStatement; - if (foreachStmt != null) { - outputStatus = CleanSpecialValues (foreachStmt.InExpression.AcceptVisitor (visitor, inputStatus)); - if (foreachStmt.VariableName == this.variableName) - outputStatus = DefiniteAssignmentStatus.DefinitelyAssigned; - break; - } else { - Debug.Assert (node.NextStatement is IfElseStatement || node.NextStatement is WhileStatement || node.NextStatement is ForStatement || node.NextStatement is DoWhileStatement); - Expression condition = node.NextStatement.GetChildByRole (Roles.Condition); - if (condition.IsNull) - outputStatus = inputStatus; - else - outputStatus = condition.AcceptVisitor(visitor, inputStatus); - foreach (ControlFlowEdge edge in node.Outgoing) { - if (edge.Type == ControlFlowEdgeType.ConditionTrue && outputStatus == DefiniteAssignmentStatus.AssignedAfterTrueExpression) { - ChangeEdgeStatus(edge, DefiniteAssignmentStatus.DefinitelyAssigned); - } else if (edge.Type == ControlFlowEdgeType.ConditionFalse && outputStatus == DefiniteAssignmentStatus.AssignedAfterFalseExpression) { - ChangeEdgeStatus(edge, DefiniteAssignmentStatus.DefinitelyAssigned); - } else { - ChangeEdgeStatus(edge, CleanSpecialValues(outputStatus)); - } - } - return; - } - default: - throw new InvalidOperationException(); - } - foreach (ControlFlowEdge edge in node.Outgoing) { - ChangeEdgeStatus(edge, outputStatus); - } - } - - void ChangeEdgeStatus(ControlFlowEdge edge, DefiniteAssignmentStatus newStatus) - { - DefiniteAssignmentStatus oldStatus = edgeStatus[edge]; - if (oldStatus == newStatus) - return; - // Ensure that status can cannot change back to CodeUnreachable after it once was reachable. - // Also, don't ever use AssignedAfter... for statements. - if (newStatus == DefiniteAssignmentStatus.CodeUnreachable - || newStatus == DefiniteAssignmentStatus.AssignedAfterFalseExpression - || newStatus == DefiniteAssignmentStatus.AssignedAfterTrueExpression) - { - throw new InvalidOperationException(); - } - // Note that the status can change from DefinitelyAssigned - // back to PotentiallyAssigned as unreachable input edges are - // discovered to be reachable. - - edgeStatus[edge] = newStatus; - DefiniteAssignmentNode targetNode = (DefiniteAssignmentNode)edge.To; - if (analyzedRangeStart <= targetNode.Index && targetNode.Index <= analyzedRangeEnd) { - // TODO: potential optimization: visit previously unreachable nodes with higher priority - // (e.g. use Deque and enqueue previously unreachable nodes at the front, but - // other nodes at the end) - nodesWithModifiedInput.Enqueue(targetNode); - } - } - - /// - /// Evaluates an expression. - /// - /// The constant value of the expression; or null if the expression is not a constant. - ResolveResult EvaluateConstant(Expression expr) - { - return resolve(expr, analysisCancellationToken); - } - - /// - /// Evaluates an expression. - /// - /// The value of the constant boolean expression; or null if the value is not a constant boolean expression. - bool? EvaluateCondition(Expression expr) - { - ResolveResult rr = EvaluateConstant(expr); - if (rr != null && rr.IsCompileTimeConstant) - return rr.ConstantValue as bool?; - else - return null; - } - - static DefiniteAssignmentStatus CleanSpecialValues(DefiniteAssignmentStatus status) - { - if (status == DefiniteAssignmentStatus.AssignedAfterTrueExpression) - return DefiniteAssignmentStatus.PotentiallyAssigned; - else if (status == DefiniteAssignmentStatus.AssignedAfterFalseExpression) - return DefiniteAssignmentStatus.PotentiallyAssigned; - else - return status; - } - - sealed class DefiniteAssignmentVisitor : DepthFirstAstVisitor - { - internal DefiniteAssignmentAnalysis analysis; - - // The general approach for unknown nodes is to pass the status through all child nodes in order - protected override DefiniteAssignmentStatus VisitChildren(AstNode node, DefiniteAssignmentStatus data) - { - // the special values are valid as output only, not as input - Debug.Assert(data == CleanSpecialValues(data)); - DefiniteAssignmentStatus status = data; - for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { - analysis.analysisCancellationToken.ThrowIfCancellationRequested(); - - Debug.Assert(!(child is Statement)); // statements are visited with the CFG, not with the visitor pattern - status = child.AcceptVisitor(this, status); - status = CleanSpecialValues(status); - } - return status; - } - - #region Statements - // For statements, the visitor only describes the effect of the statement itself; - // we do not consider the effect of any nested statements. - // This is done because the nested statements will be reached using the control flow graph. - - // In fact, these methods are present so that the default logic in VisitChildren does not try to visit the nested statements. - - public override DefiniteAssignmentStatus VisitBlockStatement(BlockStatement blockStatement, DefiniteAssignmentStatus data) - { - return data; - } - - public override DefiniteAssignmentStatus VisitCheckedStatement(CheckedStatement checkedStatement, DefiniteAssignmentStatus data) - { - return data; - } - - public override DefiniteAssignmentStatus VisitUncheckedStatement(UncheckedStatement uncheckedStatement, DefiniteAssignmentStatus data) - { - return data; - } - - // ExpressionStatement handled by default logic - // VariableDeclarationStatement handled by default logic - - public override DefiniteAssignmentStatus VisitVariableInitializer(VariableInitializer variableInitializer, DefiniteAssignmentStatus data) - { - if (variableInitializer.Initializer.IsNull) { - return data; - } else { - DefiniteAssignmentStatus status = variableInitializer.Initializer.AcceptVisitor(this, data); - if (variableInitializer.Name == analysis.variableName) - return DefiniteAssignmentStatus.DefinitelyAssigned; - else - return status; - } - } - - // IfStatement not handled by visitor, but special-cased in the code consuming the control flow graph - - public override DefiniteAssignmentStatus VisitSwitchStatement(SwitchStatement switchStatement, DefiniteAssignmentStatus data) - { - return switchStatement.Expression.AcceptVisitor(this, data); - } - - public override DefiniteAssignmentStatus VisitWhileStatement(WhileStatement whileStatement, DefiniteAssignmentStatus data) - { - return data; // condition is handled by special condition CFG node - } - - public override DefiniteAssignmentStatus VisitDoWhileStatement(DoWhileStatement doWhileStatement, DefiniteAssignmentStatus data) - { - return data; // condition is handled by special condition CFG node - } - - public override DefiniteAssignmentStatus VisitForStatement(ForStatement forStatement, DefiniteAssignmentStatus data) - { - return data; // condition is handled by special condition CFG node; initializer and iterator statements are handled by CFG - } - - // Break/Continue/Goto: handled by default logic - - // ThrowStatement: handled by default logic (just visit the expression) - // ReturnStatement: handled by default logic (just visit the expression) - - public override DefiniteAssignmentStatus VisitTryCatchStatement(TryCatchStatement tryCatchStatement, DefiniteAssignmentStatus data) - { - return data; // no special logic when entering the try-catch-finally statement - // TODO: where to put the special logic when exiting the try-finally statement? - } - - public override DefiniteAssignmentStatus VisitForeachStatement(ForeachStatement foreachStatement, DefiniteAssignmentStatus data) - { - return data; // assignment of the foreach loop variable is done when handling the condition node - } - - public override DefiniteAssignmentStatus VisitUsingStatement(UsingStatement usingStatement, DefiniteAssignmentStatus data) - { - if (usingStatement.ResourceAcquisition is Expression) - return usingStatement.ResourceAcquisition.AcceptVisitor(this, data); - else - return data; // don't handle resource acquisition statements, as those are connected in the control flow graph - } - - public override DefiniteAssignmentStatus VisitLockStatement(LockStatement lockStatement, DefiniteAssignmentStatus data) - { - return lockStatement.Expression.AcceptVisitor(this, data); - } - - // Yield statements use the default logic - - public override DefiniteAssignmentStatus VisitUnsafeStatement(UnsafeStatement unsafeStatement, DefiniteAssignmentStatus data) - { - return data; - } - - public override DefiniteAssignmentStatus VisitFixedStatement(FixedStatement fixedStatement, DefiniteAssignmentStatus data) - { - DefiniteAssignmentStatus status = data; - foreach (var variable in fixedStatement.Variables) - status = variable.AcceptVisitor(this, status); - return status; - } - #endregion - - #region Expressions - public override DefiniteAssignmentStatus VisitDirectionExpression(DirectionExpression directionExpression, DefiniteAssignmentStatus data) - { - if (directionExpression.FieldDirection == FieldDirection.Out) { - return HandleAssignment(directionExpression.Expression, null, data); - } else { - // use default logic for 'ref' - return VisitChildren(directionExpression, data); - } - } - - public override DefiniteAssignmentStatus VisitAssignmentExpression(AssignmentExpression assignmentExpression, DefiniteAssignmentStatus data) - { - if (assignmentExpression.Operator == AssignmentOperatorType.Assign) { - return HandleAssignment(assignmentExpression.Left, assignmentExpression.Right, data); - } else { - // use default logic for compound assignment operators - return VisitChildren(assignmentExpression, data); - } - } - - DefiniteAssignmentStatus HandleAssignment(Expression left, Expression right, DefiniteAssignmentStatus initialStatus) - { - IdentifierExpression ident = left as IdentifierExpression; - if (ident != null && ident.Identifier == analysis.variableName) { - // right==null is special case when handling 'out' expressions - if (right != null) - right.AcceptVisitor(this, initialStatus); - return DefiniteAssignmentStatus.DefinitelyAssigned; - } else { - DefiniteAssignmentStatus status = left.AcceptVisitor(this, initialStatus); - if (right != null) - status = right.AcceptVisitor(this, CleanSpecialValues(status)); - return CleanSpecialValues(status); - } - } - - public override DefiniteAssignmentStatus VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, DefiniteAssignmentStatus data) - { - // Don't use the default logic here because we don't want to clean up the special values. - return parenthesizedExpression.Expression.AcceptVisitor(this, data); - } - - public override DefiniteAssignmentStatus VisitCheckedExpression(CheckedExpression checkedExpression, DefiniteAssignmentStatus data) - { - return checkedExpression.Expression.AcceptVisitor(this, data); - } - - public override DefiniteAssignmentStatus VisitUncheckedExpression(UncheckedExpression uncheckedExpression, DefiniteAssignmentStatus data) - { - return uncheckedExpression.Expression.AcceptVisitor(this, data); - } - - public override DefiniteAssignmentStatus VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, DefiniteAssignmentStatus data) - { - if (binaryOperatorExpression.Operator == BinaryOperatorType.ConditionalAnd) { - // Handle constant left side of && expressions (not in the C# spec, but done by the MS compiler) - bool? cond = analysis.EvaluateCondition(binaryOperatorExpression.Left); - if (cond == true) - return binaryOperatorExpression.Right.AcceptVisitor(this, data); // right operand gets evaluated unconditionally - else if (cond == false) - return data; // right operand never gets evaluated - // C# 4.0 spec: §5.3.3.24 Definite Assignment for && expressions - DefiniteAssignmentStatus afterLeft = binaryOperatorExpression.Left.AcceptVisitor(this, data); - DefiniteAssignmentStatus beforeRight; - if (afterLeft == DefiniteAssignmentStatus.AssignedAfterTrueExpression) - beforeRight = DefiniteAssignmentStatus.DefinitelyAssigned; - else if (afterLeft == DefiniteAssignmentStatus.AssignedAfterFalseExpression) - beforeRight = DefiniteAssignmentStatus.PotentiallyAssigned; - else - beforeRight = afterLeft; - DefiniteAssignmentStatus afterRight = binaryOperatorExpression.Right.AcceptVisitor(this, beforeRight); - if (afterLeft == DefiniteAssignmentStatus.DefinitelyAssigned) - return DefiniteAssignmentStatus.DefinitelyAssigned; - else if (afterRight == DefiniteAssignmentStatus.DefinitelyAssigned && afterLeft == DefiniteAssignmentStatus.AssignedAfterFalseExpression) - return DefiniteAssignmentStatus.DefinitelyAssigned; - else if (afterRight == DefiniteAssignmentStatus.DefinitelyAssigned || afterRight == DefiniteAssignmentStatus.AssignedAfterTrueExpression) - return DefiniteAssignmentStatus.AssignedAfterTrueExpression; - else if (afterLeft == DefiniteAssignmentStatus.AssignedAfterFalseExpression && afterRight == DefiniteAssignmentStatus.AssignedAfterFalseExpression) - return DefiniteAssignmentStatus.AssignedAfterFalseExpression; - else - return DefiniteAssignmentStatus.PotentiallyAssigned; - } else if (binaryOperatorExpression.Operator == BinaryOperatorType.ConditionalOr) { - // C# 4.0 spec: §5.3.3.25 Definite Assignment for || expressions - bool? cond = analysis.EvaluateCondition(binaryOperatorExpression.Left); - if (cond == false) - return binaryOperatorExpression.Right.AcceptVisitor(this, data); // right operand gets evaluated unconditionally - else if (cond == true) - return data; // right operand never gets evaluated - DefiniteAssignmentStatus afterLeft = binaryOperatorExpression.Left.AcceptVisitor(this, data); - DefiniteAssignmentStatus beforeRight; - if (afterLeft == DefiniteAssignmentStatus.AssignedAfterTrueExpression) - beforeRight = DefiniteAssignmentStatus.PotentiallyAssigned; - else if (afterLeft == DefiniteAssignmentStatus.AssignedAfterFalseExpression) - beforeRight = DefiniteAssignmentStatus.DefinitelyAssigned; - else - beforeRight = afterLeft; - DefiniteAssignmentStatus afterRight = binaryOperatorExpression.Right.AcceptVisitor(this, beforeRight); - if (afterLeft == DefiniteAssignmentStatus.DefinitelyAssigned) - return DefiniteAssignmentStatus.DefinitelyAssigned; - else if (afterRight == DefiniteAssignmentStatus.DefinitelyAssigned && afterLeft == DefiniteAssignmentStatus.AssignedAfterTrueExpression) - return DefiniteAssignmentStatus.DefinitelyAssigned; - else if (afterRight == DefiniteAssignmentStatus.DefinitelyAssigned || afterRight == DefiniteAssignmentStatus.AssignedAfterFalseExpression) - return DefiniteAssignmentStatus.AssignedAfterFalseExpression; - else if (afterLeft == DefiniteAssignmentStatus.AssignedAfterTrueExpression && afterRight == DefiniteAssignmentStatus.AssignedAfterTrueExpression) - return DefiniteAssignmentStatus.AssignedAfterTrueExpression; - else - return DefiniteAssignmentStatus.PotentiallyAssigned; - } else if (binaryOperatorExpression.Operator == BinaryOperatorType.NullCoalescing) { - // C# 4.0 spec: §5.3.3.27 Definite assignment for ?? expressions - ResolveResult crr = analysis.EvaluateConstant(binaryOperatorExpression.Left); - if (crr != null && crr.IsCompileTimeConstant && crr.ConstantValue == null) - return binaryOperatorExpression.Right.AcceptVisitor(this, data); - DefiniteAssignmentStatus status = CleanSpecialValues(binaryOperatorExpression.Left.AcceptVisitor(this, data)); - binaryOperatorExpression.Right.AcceptVisitor(this, status); - return status; - } else { - // use default logic for other operators - return VisitChildren(binaryOperatorExpression, data); - } - } - - public override DefiniteAssignmentStatus VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, DefiniteAssignmentStatus data) - { - if (unaryOperatorExpression.Operator == UnaryOperatorType.Not) { - // C# 4.0 spec: §5.3.3.26 Definite assignment for ! expressions - DefiniteAssignmentStatus status = unaryOperatorExpression.Expression.AcceptVisitor(this, data); - if (status == DefiniteAssignmentStatus.AssignedAfterFalseExpression) - return DefiniteAssignmentStatus.AssignedAfterTrueExpression; - else if (status == DefiniteAssignmentStatus.AssignedAfterTrueExpression) - return DefiniteAssignmentStatus.AssignedAfterFalseExpression; - else - return status; - } else { - // use default logic for other operators - return VisitChildren(unaryOperatorExpression, data); - } - } - - public override DefiniteAssignmentStatus VisitConditionalExpression(ConditionalExpression conditionalExpression, DefiniteAssignmentStatus data) - { - // C# 4.0 spec: §5.3.3.28 Definite assignment for ?: expressions - bool? cond = analysis.EvaluateCondition(conditionalExpression.Condition); - if (cond == true) { - return conditionalExpression.TrueExpression.AcceptVisitor(this, data); - } else if (cond == false) { - return conditionalExpression.FalseExpression.AcceptVisitor(this, data); - } else { - DefiniteAssignmentStatus afterCondition = conditionalExpression.Condition.AcceptVisitor(this, data); - - DefiniteAssignmentStatus beforeTrue, beforeFalse; - if (afterCondition == DefiniteAssignmentStatus.AssignedAfterTrueExpression) { - beforeTrue = DefiniteAssignmentStatus.DefinitelyAssigned; - beforeFalse = DefiniteAssignmentStatus.PotentiallyAssigned; - } else if (afterCondition == DefiniteAssignmentStatus.AssignedAfterFalseExpression) { - beforeTrue = DefiniteAssignmentStatus.PotentiallyAssigned; - beforeFalse = DefiniteAssignmentStatus.DefinitelyAssigned; - } else { - beforeTrue = afterCondition; - beforeFalse = afterCondition; - } - - DefiniteAssignmentStatus afterTrue = conditionalExpression.TrueExpression.AcceptVisitor(this, beforeTrue); - DefiniteAssignmentStatus afterFalse = conditionalExpression.FalseExpression.AcceptVisitor(this, beforeFalse); - return MergeStatus(CleanSpecialValues(afterTrue), CleanSpecialValues(afterFalse)); - } - } - - public override DefiniteAssignmentStatus VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, DefiniteAssignmentStatus data) - { - BlockStatement body = anonymousMethodExpression.Body; - analysis.ChangeNodeStatus(analysis.beginNodeDict[body], data); - return data; - } - - public override DefiniteAssignmentStatus VisitLambdaExpression(LambdaExpression lambdaExpression, DefiniteAssignmentStatus data) - { - Statement body = lambdaExpression.Body as Statement; - if (body != null) { - analysis.ChangeNodeStatus(analysis.beginNodeDict[body], data); - } else { - lambdaExpression.Body.AcceptVisitor(this, data); - } - return data; - } - - public override DefiniteAssignmentStatus VisitIdentifierExpression(IdentifierExpression identifierExpression, DefiniteAssignmentStatus data) - { - if (data != DefiniteAssignmentStatus.DefinitelyAssigned - && identifierExpression.Identifier == analysis.variableName && identifierExpression.TypeArguments.Count == 0) - { - analysis.unassignedVariableUses.Add(identifierExpression); - } - return data; - } - #endregion - } - } -} diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/CompositeResolveVisitorNavigator.cs b/ICSharpCode.Decompiler/CSharp/Resolver/CompositeResolveVisitorNavigator.cs deleted file mode 100644 index 6f495dfbc..000000000 --- a/ICSharpCode.Decompiler/CSharp/Resolver/CompositeResolveVisitorNavigator.cs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2010-2013 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 ICSharpCode.Decompiler.CSharp.Syntax; -using ICSharpCode.Decompiler.Semantics; -using ICSharpCode.Decompiler.TypeSystem; - -namespace ICSharpCode.Decompiler.CSharp.Resolver -{ - public sealed class CompositeResolveVisitorNavigator : IResolveVisitorNavigator - { - IResolveVisitorNavigator[] navigators; - - public CompositeResolveVisitorNavigator(params IResolveVisitorNavigator[] navigators) - { - if (navigators == null) - throw new ArgumentNullException("navigators"); - this.navigators = navigators; - foreach (var n in navigators) { - if (n == null) - throw new ArgumentException("Array must not contain nulls."); - } - } - - public ResolveVisitorNavigationMode Scan(AstNode node) - { - bool needsScan = false; - foreach (var navigator in navigators) { - ResolveVisitorNavigationMode mode = navigator.Scan(node); - if (mode == ResolveVisitorNavigationMode.Resolve) - return mode; // resolve has highest priority - else if (mode == ResolveVisitorNavigationMode.Scan) - needsScan = true; - } - return needsScan ? ResolveVisitorNavigationMode.Scan : ResolveVisitorNavigationMode.Skip; - } - - public void Resolved(AstNode node, ResolveResult result) - { - foreach (var navigator in navigators) { - navigator.Resolved(node, result); - } - } - - public void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) - { - foreach (var navigator in navigators) { - navigator.ProcessConversion(expression, result, conversion, targetType); - } - } - } -} diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/DetectSkippableNodesNavigator.cs b/ICSharpCode.Decompiler/CSharp/Resolver/DetectSkippableNodesNavigator.cs deleted file mode 100644 index c83510b1d..000000000 --- a/ICSharpCode.Decompiler/CSharp/Resolver/DetectSkippableNodesNavigator.cs +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2010-2013 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.Collections.Generic; -using ICSharpCode.Decompiler.CSharp.Syntax; -using ICSharpCode.Decompiler.Semantics; -using ICSharpCode.Decompiler.TypeSystem; - -namespace ICSharpCode.Decompiler.CSharp.Resolver -{ - /// - /// When an is searching for specific nodes - /// (e.g. all IdentifierExpressions), it has to scan the whole syntax tree for those nodes. - /// However, scanning in the ResolveVisitor is expensive (e.g. any lambda that is scanned must be resolved), - /// so it makes sense to detect when a whole subtree is scan-only, and skip that tree instead. - /// - /// The DetectSkippableNodesNavigator performs this job by running the input IResolveVisitorNavigator - /// over the whole AST, and detecting subtrees that are scan-only, and replaces them with Skip. - /// - public sealed class DetectSkippableNodesNavigator : IResolveVisitorNavigator - { - readonly Dictionary dict = new Dictionary(); - IResolveVisitorNavigator navigator; - - public DetectSkippableNodesNavigator(IResolveVisitorNavigator navigator, AstNode root) - { - this.navigator = navigator; - Init(root); - } - - bool Init(AstNode node) - { - var mode = navigator.Scan(node); - if (mode == ResolveVisitorNavigationMode.Skip) - return false; - - bool needsResolve = (mode != ResolveVisitorNavigationMode.Scan); - - for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { - needsResolve |= Init(child); - } - - if (needsResolve) { - // If this node or any child node needs resolving, store the mode in the dictionary. - dict.Add(node, mode); - } - return needsResolve; - } - - /// - public ResolveVisitorNavigationMode Scan(AstNode node) - { - ResolveVisitorNavigationMode mode; - if (dict.TryGetValue(node, out mode)) { - return mode; - } else { - return ResolveVisitorNavigationMode.Skip; - } - } - - /// - public void Resolved(AstNode node, ResolveResult result) - { - navigator.Resolved(node, result); - } - - /// - public void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) - { - navigator.ProcessConversion(expression, result, conversion, targetType); - } - } -} diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/FindReferencedEntities.cs b/ICSharpCode.Decompiler/CSharp/Resolver/FindReferencedEntities.cs deleted file mode 100644 index d0d969837..000000000 --- a/ICSharpCode.Decompiler/CSharp/Resolver/FindReferencedEntities.cs +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) 2010-2013 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 ICSharpCode.Decompiler.CSharp.Syntax; -using ICSharpCode.Decompiler.Semantics; -using ICSharpCode.Decompiler.TypeSystem; - -namespace ICSharpCode.Decompiler.CSharp.Resolver -{ - /// - /// Find all entities that are referenced in the scanned AST. - /// - public sealed class FindReferencedEntities : IResolveVisitorNavigator - { - readonly Action memberReferenceFound; - readonly Action typeReferenceFound; - - /// - /// Creates a new FindReferencedEntities instance that - /// looks for entity definitions. - /// The visitor will report type definitions and member definitions (not specialized members). - /// - public FindReferencedEntities(Action referenceFound) - { - if (referenceFound == null) - throw new ArgumentNullException("referenceFound"); - this.memberReferenceFound = (node, member) => referenceFound(node, member.MemberDefinition); - this.typeReferenceFound = (node, type) => { - var def = type.GetDefinition(); - if (def != null) - referenceFound(node, def); - }; - } - - /// - /// Creates a new FindReferencedEntities instance that - /// looks for types and members. - /// The visitor will report parameterized types and potentially specialized members. - /// - public FindReferencedEntities(Action typeReferenceFound, Action memberReferenceFound) - { - if (typeReferenceFound == null) - throw new ArgumentNullException("typeReferenceFound"); - if (memberReferenceFound == null) - throw new ArgumentNullException("memberReferenceFound"); - this.typeReferenceFound = typeReferenceFound; - this.memberReferenceFound = memberReferenceFound; - } - - public ResolveVisitorNavigationMode Scan(AstNode node) - { - return ResolveVisitorNavigationMode.Resolve; - } - - public void Resolved(AstNode node, ResolveResult result) - { - if (ParenthesizedExpression.ActsAsParenthesizedExpression(node)) - return; - - MemberResolveResult mrr = result as MemberResolveResult; - if (mrr != null) { - memberReferenceFound(node, mrr.Member); - } - TypeResolveResult trr = result as TypeResolveResult; - if (trr != null) { - typeReferenceFound(node, trr.Type); - } - ForEachResolveResult ferr = result as ForEachResolveResult; - if (ferr != null) { - Resolved(node, ferr.GetEnumeratorCall); - if (ferr.CurrentProperty != null) - memberReferenceFound(node, ferr.CurrentProperty); - if (ferr.MoveNextMethod != null) - memberReferenceFound(node, ferr.MoveNextMethod); - } - } - - public void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) - { - if (conversion.IsUserDefined || conversion.IsMethodGroupConversion) { - memberReferenceFound(expression, conversion.Method); - } - } - } -} diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/IResolveVisitorNavigator.cs b/ICSharpCode.Decompiler/CSharp/Resolver/IResolveVisitorNavigator.cs deleted file mode 100644 index 4191d1c8d..000000000 --- a/ICSharpCode.Decompiler/CSharp/Resolver/IResolveVisitorNavigator.cs +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) 2010-2013 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 ICSharpCode.Decompiler.CSharp.Syntax; -using ICSharpCode.Decompiler.Semantics; -using ICSharpCode.Decompiler.TypeSystem; - -namespace ICSharpCode.Decompiler.CSharp.Resolver -{ - /// - /// Allows controlling which nodes are resolved by the resolve visitor. - /// - /// - public interface IResolveVisitorNavigator - { - /// - /// Asks the navigator whether to scan, skip, or resolve a node. - /// - ResolveVisitorNavigationMode Scan(AstNode node); - - /// - /// Notifies the navigator that a node was resolved. - /// - /// The node that was resolved - /// Resolve result - void Resolved(AstNode node, ResolveResult result); - - /// - /// Notifies the navigator that an implicit conversion was applied. - /// - /// The expression that was resolved. - /// The resolve result of the expression. - /// The conversion applied to the expressed. - /// The target type of the conversion. - void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType); - } - - /// - /// Represents the operation mode of the resolve visitor. - /// - /// - public enum ResolveVisitorNavigationMode - { - /// - /// Scan into the children of the current node, without resolving the current node. - /// - Scan, - /// - /// Skip the current node - do not scan into it; do not resolve it. - /// - Skip, - /// - /// Resolve the current node. - /// Subnodes which are not required for resolving the current node - /// will ask the navigator again whether they should be resolved. - /// - Resolve - } - - sealed class ConstantModeResolveVisitorNavigator : IResolveVisitorNavigator - { - readonly ResolveVisitorNavigationMode mode; - readonly IResolveVisitorNavigator targetForResolveCalls; - - public ConstantModeResolveVisitorNavigator(ResolveVisitorNavigationMode mode, IResolveVisitorNavigator targetForResolveCalls) - { - this.mode = mode; - this.targetForResolveCalls = targetForResolveCalls; - } - - ResolveVisitorNavigationMode IResolveVisitorNavigator.Scan(AstNode node) - { - return mode; - } - - void IResolveVisitorNavigator.Resolved(AstNode node, ResolveResult result) - { - if (targetForResolveCalls != null) - targetForResolveCalls.Resolved(node, result); - } - - void IResolveVisitorNavigator.ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) - { - if (targetForResolveCalls != null) - targetForResolveCalls.ProcessConversion(expression, result, conversion, targetType); - } - } -} diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/NodeListResolveVisitorNavigator.cs b/ICSharpCode.Decompiler/CSharp/Resolver/NodeListResolveVisitorNavigator.cs deleted file mode 100644 index 77419f3a7..000000000 --- a/ICSharpCode.Decompiler/CSharp/Resolver/NodeListResolveVisitorNavigator.cs +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2010-2013 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.Generic; -using ICSharpCode.Decompiler.CSharp.Syntax; -using ICSharpCode.Decompiler.Semantics; -using ICSharpCode.Decompiler.TypeSystem; - -namespace ICSharpCode.Decompiler.CSharp.Resolver -{ - /// - /// implementation that resolves a list of nodes. - /// We will skip all nodes which are not the target nodes or ancestors of the target nodes. - /// - public class NodeListResolveVisitorNavigator : IResolveVisitorNavigator - { - readonly Dictionary dict = new Dictionary(); - - /// - /// Creates a new NodeListResolveVisitorNavigator that resolves the specified nodes. - /// - public NodeListResolveVisitorNavigator(params AstNode[] nodes) - : this((IEnumerable)nodes) - { - } - - /// - /// Creates a new NodeListResolveVisitorNavigator that resolves the specified nodes. - /// - public NodeListResolveVisitorNavigator(IEnumerable nodes, bool scanOnly = false) - { - if (nodes == null) - throw new ArgumentNullException("nodes"); - foreach (var node in nodes) { - dict[node] = scanOnly ? ResolveVisitorNavigationMode.Scan : ResolveVisitorNavigationMode.Resolve; - for (var ancestor = node.Parent; ancestor != null && !dict.ContainsKey(ancestor); ancestor = ancestor.Parent) { - dict.Add(ancestor, ResolveVisitorNavigationMode.Scan); - } - } - } - - /// - public virtual ResolveVisitorNavigationMode Scan(AstNode node) - { - ResolveVisitorNavigationMode mode; - if (dict.TryGetValue(node, out mode)) { - return mode; - } else { - return ResolveVisitorNavigationMode.Skip; - } - } - - public virtual void Resolved(AstNode node, ResolveResult result) - { - } - - public virtual void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) - { - } - } -} diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/ObservableAstVisitor.cs b/ICSharpCode.Decompiler/CSharp/Syntax/ObservableAstVisitor.cs deleted file mode 100644 index eaaf8a2b9..000000000 --- a/ICSharpCode.Decompiler/CSharp/Syntax/ObservableAstVisitor.cs +++ /dev/null @@ -1,864 +0,0 @@ -// -// ObservableAstVisitor.cs -// -// Author: -// Mike Krüger -// -// Copyright (c) 2011 Novell, Inc (http://www.novell.com) -// -// 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; - -namespace ICSharpCode.Decompiler.CSharp.Syntax -{ - public class ObservableAstVisitor : IAstVisitor - { - void Visit(Action enter, Action leave, T node) where T : AstNode - { - if (enter != null) - enter(node); - AstNode next; - for (var child = node.FirstChild; child != null; child = next) { - // Store next to allow the loop to continue - // if the visitor removes/replaces children. - next = child.NextSibling; - child.AcceptVisitor (this); - } - if (leave != null) - leave(node); - } - - void IAstVisitor.VisitNullNode(AstNode nullNode) - { - } - - void IAstVisitor.VisitErrorNode(AstNode nullNode) - { - } - - public event Action EnterSyntaxTree, LeaveSyntaxTree; - - void IAstVisitor.VisitSyntaxTree(SyntaxTree unit) - { - Visit(EnterSyntaxTree, LeaveSyntaxTree, unit); - } - - public event Action EnterComment, LeaveComment; - - void IAstVisitor.VisitComment(Comment comment) - { - Visit(EnterComment, LeaveComment, comment); - } - - public event Action EnterNewLine, LeaveNewLine; - - void IAstVisitor.VisitNewLine(NewLineNode newLineNode) - { - Visit(EnterNewLine, LeaveNewLine, newLineNode); - } - - public event Action EnterWhitespace, LeaveWhitespace; - - void IAstVisitor.VisitWhitespace(WhitespaceNode whitespace) - { - Visit(EnterWhitespace, LeaveWhitespace, whitespace); - } - - public event Action EnterText, LeaveText; - - void IAstVisitor.VisitText(TextNode textNode) - { - Visit(EnterText, LeaveText, textNode); - } - - public event Action EnterPreProcessorDirective, LeavePreProcessorDirective; - void IAstVisitor.VisitPreProcessorDirective(PreProcessorDirective preProcessorDirective) - { - Visit(EnterPreProcessorDirective, LeavePreProcessorDirective, preProcessorDirective); - } - - public event Action EnterDocumentationReference, LeaveDocumentationReference; - - void IAstVisitor.VisitDocumentationReference(DocumentationReference documentationReference) - { - Visit(EnterDocumentationReference, LeaveDocumentationReference, documentationReference); - } - - public event Action EnterIdentifier, LeaveIdentifier; - - void IAstVisitor.VisitIdentifier(Identifier identifier) - { - Visit(EnterIdentifier, LeaveIdentifier, identifier); - } - - public event Action EnterCSharpTokenNode, LeaveCSharpTokenNode; - - void IAstVisitor.VisitCSharpTokenNode(CSharpTokenNode token) - { - Visit(EnterCSharpTokenNode, LeaveCSharpTokenNode, token); - } - - public event Action EnterPrimitiveType, LeavePrimitiveType; - - void IAstVisitor.VisitPrimitiveType(PrimitiveType primitiveType) - { - Visit(EnterPrimitiveType, LeavePrimitiveType, primitiveType); - } - - public event Action EnterComposedType, LeaveComposedType; - - void IAstVisitor.VisitComposedType(ComposedType composedType) - { - Visit(EnterComposedType, LeaveComposedType, composedType); - } - - public event Action EnterSimpleType, LeaveSimpleType; - - void IAstVisitor.VisitSimpleType(SimpleType simpleType) - { - Visit(EnterSimpleType, LeaveSimpleType, simpleType); - } - - public event Action EnterMemberType, LeaveMemberType; - - void IAstVisitor.VisitMemberType(MemberType memberType) - { - Visit(EnterMemberType, LeaveMemberType, memberType); - } - - public event Action EnterAttribute, LeaveAttribute; - - void IAstVisitor.VisitAttribute(Attribute attribute) - { - Visit(EnterAttribute, LeaveAttribute, attribute); - } - - public event Action EnterAttributeSection, LeaveAttributeSection; - - void IAstVisitor.VisitAttributeSection(AttributeSection attributeSection) - { - Visit(EnterAttributeSection, LeaveAttributeSection, attributeSection); - } - - public event Action EnterDelegateDeclaration, LeaveDelegateDeclaration; - - void IAstVisitor.VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration) - { - Visit(EnterDelegateDeclaration, LeaveDelegateDeclaration, delegateDeclaration); - } - - public event Action EnterNamespaceDeclaration, LeaveNamespaceDeclaration; - - void IAstVisitor.VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration) - { - Visit(EnterNamespaceDeclaration, LeaveNamespaceDeclaration, namespaceDeclaration); - } - - public event Action EnterTypeDeclaration, LeaveTypeDeclaration; - - void IAstVisitor.VisitTypeDeclaration(TypeDeclaration typeDeclaration) - { - Visit(EnterTypeDeclaration, LeaveTypeDeclaration, typeDeclaration); - } - - public event Action EnterTypeParameterDeclaration, LeaveTypeParameterDeclaration; - - void IAstVisitor.VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration) - { - Visit(EnterTypeParameterDeclaration, LeaveTypeParameterDeclaration, typeParameterDeclaration); - } - - public event Action EnterEnumMemberDeclaration, LeaveEnumMemberDeclaration; - - void IAstVisitor.VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration) - { - Visit(EnterEnumMemberDeclaration, LeaveEnumMemberDeclaration, enumMemberDeclaration); - } - - public event Action EnterUsingDeclaration, LeaveUsingDeclaration; - - void IAstVisitor.VisitUsingDeclaration(UsingDeclaration usingDeclaration) - { - Visit(EnterUsingDeclaration, LeaveUsingDeclaration, usingDeclaration); - } - - public event Action EnterUsingAliasDeclaration, LeaveUsingAliasDeclaration; - - void IAstVisitor.VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration) - { - Visit(EnterUsingAliasDeclaration, LeaveUsingAliasDeclaration, usingDeclaration); - } - - public event Action EnterExternAliasDeclaration, LeaveExternAliasDeclaration; - - void IAstVisitor.VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration) - { - Visit(EnterExternAliasDeclaration, LeaveExternAliasDeclaration, externAliasDeclaration); - } - - public event Action EnterConstructorDeclaration, LeaveConstructorDeclaration; - - void IAstVisitor.VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration) - { - Visit(EnterConstructorDeclaration, LeaveConstructorDeclaration, constructorDeclaration); - } - - public event Action EnterConstructorInitializer, LeaveConstructorInitializer; - - void IAstVisitor.VisitConstructorInitializer(ConstructorInitializer constructorInitializer) - { - Visit(EnterConstructorInitializer, LeaveConstructorInitializer, constructorInitializer); - } - - public event Action EnterDestructorDeclaration, LeaveDestructorDeclaration; - - void IAstVisitor.VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration) - { - Visit(EnterDestructorDeclaration, LeaveDestructorDeclaration, destructorDeclaration); - } - - public event Action EnterEventDeclaration, LeaveEventDeclaration; - - void IAstVisitor.VisitEventDeclaration(EventDeclaration eventDeclaration) - { - Visit(EnterEventDeclaration, LeaveEventDeclaration, eventDeclaration); - } - - public event Action EnterCustomEventDeclaration, LeaveCustomEventDeclaration; - - void IAstVisitor.VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration) - { - Visit(EnterCustomEventDeclaration, LeaveCustomEventDeclaration, eventDeclaration); - } - - public event Action EnterFieldDeclaration, LeaveFieldDeclaration; - - void IAstVisitor.VisitFieldDeclaration(FieldDeclaration fieldDeclaration) - { - Visit(EnterFieldDeclaration, LeaveFieldDeclaration, fieldDeclaration); - } - - public event Action EnterFixedFieldDeclaration, LeaveFixedFieldDeclaration; - - void IAstVisitor.VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration) - { - Visit(EnterFixedFieldDeclaration, LeaveFixedFieldDeclaration, fixedFieldDeclaration); - } - - public event Action EnterFixedVariableInitializer, LeaveFixedVariableInitializer; - - void IAstVisitor.VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer) - { - Visit(EnterFixedVariableInitializer, LeaveFixedVariableInitializer, fixedVariableInitializer); - } - - public event Action EnterIndexerDeclaration, LeaveIndexerDeclaration; - - void IAstVisitor.VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration) - { - Visit(EnterIndexerDeclaration, LeaveIndexerDeclaration, indexerDeclaration); - } - - public event Action EnterMethodDeclaration, LeaveMethodDeclaration; - - void IAstVisitor.VisitMethodDeclaration(MethodDeclaration methodDeclaration) - { - Visit(EnterMethodDeclaration, LeaveMethodDeclaration, methodDeclaration); - } - - public event Action EnterOperatorDeclaration, LeaveOperatorDeclaration; - - void IAstVisitor.VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration) - { - Visit(EnterOperatorDeclaration, LeaveOperatorDeclaration, operatorDeclaration); - } - - public event Action EnterPropertyDeclaration, LeavePropertyDeclaration; - - void IAstVisitor.VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration) - { - Visit(EnterPropertyDeclaration, LeavePropertyDeclaration, propertyDeclaration); - } - - public event Action EnterAccessor, LeaveAccessor; - - void IAstVisitor.VisitAccessor(Accessor accessor) - { - Visit(EnterAccessor, LeaveAccessor, accessor); - } - - public event Action EnterVariableInitializer, LeaveVariableInitializer; - - void IAstVisitor.VisitVariableInitializer(VariableInitializer variableInitializer) - { - Visit(EnterVariableInitializer, LeaveVariableInitializer, variableInitializer); - } - - public event Action EnterParameterDeclaration, LeaveParameterDeclaration; - - void IAstVisitor.VisitParameterDeclaration(ParameterDeclaration parameterDeclaration) - { - Visit(EnterParameterDeclaration, LeaveParameterDeclaration, parameterDeclaration); - } - - public event Action EnterConstraint, LeaveConstraint; - - void IAstVisitor.VisitConstraint(Constraint constraint) - { - Visit(EnterConstraint, LeaveConstraint, constraint); - } - - public event Action EnterBlockStatement, LeaveBlockStatement; - - void IAstVisitor.VisitBlockStatement(BlockStatement blockStatement) - { - Visit(EnterBlockStatement, LeaveBlockStatement, blockStatement); - } - - public event Action EnterExpressionStatement, LeaveExpressionStatement; - - void IAstVisitor.VisitExpressionStatement(ExpressionStatement expressionStatement) - { - Visit(EnterExpressionStatement, LeaveExpressionStatement, expressionStatement); - } - - public event Action EnterBreakStatement, LeaveBreakStatement; - - void IAstVisitor.VisitBreakStatement(BreakStatement breakStatement) - { - Visit(EnterBreakStatement, LeaveBreakStatement, breakStatement); - } - - public event Action EnterCheckedStatement, LeaveCheckedStatement; - - void IAstVisitor.VisitCheckedStatement(CheckedStatement checkedStatement) - { - Visit(EnterCheckedStatement, LeaveCheckedStatement, checkedStatement); - } - - public event Action EnterContinueStatement, LeaveContinueStatement; - - void IAstVisitor.VisitContinueStatement(ContinueStatement continueStatement) - { - Visit(EnterContinueStatement, LeaveContinueStatement, continueStatement); - } - - public event Action EnterDoWhileStatement, LeaveDoWhileStatement; - - void IAstVisitor.VisitDoWhileStatement(DoWhileStatement doWhileStatement) - { - Visit(EnterDoWhileStatement, LeaveDoWhileStatement, doWhileStatement); - } - - public event Action EnterEmptyStatement, LeaveEmptyStatement; - - void IAstVisitor.VisitEmptyStatement(EmptyStatement emptyStatement) - { - Visit(EnterEmptyStatement, LeaveEmptyStatement, emptyStatement); - } - - public event Action EnterFixedStatement, LeaveFixedStatement; - - void IAstVisitor.VisitFixedStatement(FixedStatement fixedStatement) - { - Visit(EnterFixedStatement, LeaveFixedStatement, fixedStatement); - } - - public event Action EnterForeachStatement, LeaveForeachStatement; - - void IAstVisitor.VisitForeachStatement(ForeachStatement foreachStatement) - { - Visit(EnterForeachStatement, LeaveForeachStatement, foreachStatement); - } - - public event Action EnterForStatement, LeaveForStatement; - - void IAstVisitor.VisitForStatement(ForStatement forStatement) - { - Visit(EnterForStatement, LeaveForStatement, forStatement); - } - - public event Action EnterGotoCaseStatement, LeaveGotoCaseStatement; - - void IAstVisitor.VisitGotoCaseStatement(GotoCaseStatement gotoCaseStatement) - { - Visit(EnterGotoCaseStatement, LeaveGotoCaseStatement, gotoCaseStatement); - } - - public event Action EnterGotoDefaultStatement, LeaveGotoDefaultStatement; - - void IAstVisitor.VisitGotoDefaultStatement(GotoDefaultStatement gotoDefaultStatement) - { - Visit(EnterGotoDefaultStatement, LeaveGotoDefaultStatement, gotoDefaultStatement); - } - - public event Action EnterGotoStatement, LeaveGotoStatement; - - void IAstVisitor.VisitGotoStatement(GotoStatement gotoStatement) - { - Visit(EnterGotoStatement, LeaveGotoStatement, gotoStatement); - } - - public event Action EnterIfElseStatement, LeaveIfElseStatement; - - void IAstVisitor.VisitIfElseStatement(IfElseStatement ifElseStatement) - { - Visit(EnterIfElseStatement, LeaveIfElseStatement, ifElseStatement); - } - - public event Action EnterLabelStatement, LeaveLabelStatement; - - void IAstVisitor.VisitLabelStatement(LabelStatement labelStatement) - { - Visit(EnterLabelStatement, LeaveLabelStatement, labelStatement); - } - - public event Action EnterLockStatement, LeaveLockStatement; - - void IAstVisitor.VisitLockStatement(LockStatement lockStatement) - { - Visit(EnterLockStatement, LeaveLockStatement, lockStatement); - } - - public event Action EnterReturnStatement, LeaveReturnStatement; - - void IAstVisitor.VisitReturnStatement(ReturnStatement returnStatement) - { - Visit(EnterReturnStatement, LeaveReturnStatement, returnStatement); - } - - public event Action EnterSwitchStatement, LeaveSwitchStatement; - - void IAstVisitor.VisitSwitchStatement(SwitchStatement switchStatement) - { - Visit(EnterSwitchStatement, LeaveSwitchStatement, switchStatement); - } - - public event Action EnterSwitchSection, LeaveSwitchSection; - - void IAstVisitor.VisitSwitchSection(SwitchSection switchSection) - { - Visit(EnterSwitchSection, LeaveSwitchSection, switchSection); - } - - public event Action EnterCaseLabel, LeaveCaseLabel; - - void IAstVisitor.VisitCaseLabel(CaseLabel caseLabel) - { - Visit(EnterCaseLabel, LeaveCaseLabel, caseLabel); - } - - public event Action EnterThrowStatement, LeaveThrowStatement; - - void IAstVisitor.VisitThrowStatement(ThrowStatement throwStatement) - { - Visit(EnterThrowStatement, LeaveThrowStatement, throwStatement); - } - - public event Action EnterTryCatchStatement, LeaveTryCatchStatement; - - void IAstVisitor.VisitTryCatchStatement(TryCatchStatement tryCatchStatement) - { - Visit(EnterTryCatchStatement, LeaveTryCatchStatement, tryCatchStatement); - } - - public event Action EnterCatchClause, LeaveCatchClause; - - void IAstVisitor.VisitCatchClause(CatchClause catchClause) - { - Visit(EnterCatchClause, LeaveCatchClause, catchClause); - } - - public event Action EnterUncheckedStatement, LeaveUncheckedStatement; - - void IAstVisitor.VisitUncheckedStatement(UncheckedStatement uncheckedStatement) - { - Visit(EnterUncheckedStatement, LeaveUncheckedStatement, uncheckedStatement); - } - - public event Action EnterUnsafeStatement, LeaveUnsafeStatement; - - void IAstVisitor.VisitUnsafeStatement(UnsafeStatement unsafeStatement) - { - Visit(EnterUnsafeStatement, LeaveUnsafeStatement, unsafeStatement); - } - - public event Action EnterUsingStatement, LeaveUsingStatement; - - void IAstVisitor.VisitUsingStatement(UsingStatement usingStatement) - { - Visit(EnterUsingStatement, LeaveUsingStatement, usingStatement); - } - - public event Action EnterVariableDeclarationStatement, LeaveVariableDeclarationStatement; - - void IAstVisitor.VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement) - { - Visit(EnterVariableDeclarationStatement, LeaveVariableDeclarationStatement, variableDeclarationStatement); - } - - public event Action EnterWhileStatement, LeaveWhileStatement; - - void IAstVisitor.VisitWhileStatement(WhileStatement whileStatement) - { - Visit(EnterWhileStatement, LeaveWhileStatement, whileStatement); - } - - public event Action EnterYieldBreakStatement, LeaveYieldBreakStatement; - - void IAstVisitor.VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement) - { - Visit(EnterYieldBreakStatement, LeaveYieldBreakStatement, yieldBreakStatement); - } - - public event Action EnterYieldReturnStatement, LeaveYieldReturnStatement; - - void IAstVisitor.VisitYieldReturnStatement(YieldReturnStatement yieldStatement) - { - Visit(EnterYieldReturnStatement, LeaveYieldReturnStatement, yieldStatement); - } - - public event Action EnterAnonymousMethodExpression, LeaveAnonymousMethodExpression; - - void IAstVisitor.VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression) - { - Visit(EnterAnonymousMethodExpression, LeaveAnonymousMethodExpression, anonymousMethodExpression); - } - - public event Action EnterLambdaExpression, LeaveLambdaExpression; - - void IAstVisitor.VisitLambdaExpression(LambdaExpression lambdaExpression) - { - Visit(EnterLambdaExpression, LeaveLambdaExpression, lambdaExpression); - } - - public event Action EnterAssignmentExpression, LeaveAssignmentExpression; - - void IAstVisitor.VisitAssignmentExpression(AssignmentExpression assignmentExpression) - { - Visit(EnterAssignmentExpression, LeaveAssignmentExpression, assignmentExpression); - } - - public event Action EnterBaseReferenceExpression, LeaveBaseReferenceExpression; - - void IAstVisitor.VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression) - { - Visit(EnterBaseReferenceExpression, LeaveBaseReferenceExpression, baseReferenceExpression); - } - - public event Action EnterBinaryOperatorExpression, LeaveBinaryOperatorExpression; - - void IAstVisitor.VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression) - { - Visit(EnterBinaryOperatorExpression, LeaveBinaryOperatorExpression, binaryOperatorExpression); - } - - public event Action EnterCastExpression, LeaveCastExpression; - - void IAstVisitor.VisitCastExpression(CastExpression castExpression) - { - Visit(EnterCastExpression, LeaveCastExpression, castExpression); - } - - public event Action EnterCheckedExpression, LeaveCheckedExpression; - - void IAstVisitor.VisitCheckedExpression(CheckedExpression checkedExpression) - { - Visit(EnterCheckedExpression, LeaveCheckedExpression, checkedExpression); - } - - public event Action EnterConditionalExpression, LeaveConditionalExpression; - - void IAstVisitor.VisitConditionalExpression(ConditionalExpression conditionalExpression) - { - Visit(EnterConditionalExpression, LeaveConditionalExpression, conditionalExpression); - } - - public event Action EnterIdentifierExpression, LeaveIdentifierExpression; - - void IAstVisitor.VisitIdentifierExpression(IdentifierExpression identifierExpression) - { - Visit(EnterIdentifierExpression, LeaveIdentifierExpression, identifierExpression); - } - - public event Action EnterIndexerExpression, LeaveIndexerExpression; - - void IAstVisitor.VisitIndexerExpression(IndexerExpression indexerExpression) - { - Visit(EnterIndexerExpression, LeaveIndexerExpression, indexerExpression); - } - - public event Action EnterInvocationExpression, LeaveInvocationExpression; - - void IAstVisitor.VisitInvocationExpression(InvocationExpression invocationExpression) - { - Visit(EnterInvocationExpression, LeaveInvocationExpression, invocationExpression); - } - - public event Action EnterDirectionExpression, LeaveDirectionExpression; - - void IAstVisitor.VisitDirectionExpression(DirectionExpression directionExpression) - { - Visit(EnterDirectionExpression, LeaveDirectionExpression, directionExpression); - } - - public event Action EnterMemberReferenceExpression, LeaveMemberReferenceExpression; - - void IAstVisitor.VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression) - { - Visit(EnterMemberReferenceExpression, LeaveMemberReferenceExpression, memberReferenceExpression); - } - - public event Action EnterNullReferenceExpression, LeaveNullReferenceExpression; - - void IAstVisitor.VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression) - { - Visit(EnterNullReferenceExpression, LeaveNullReferenceExpression, nullReferenceExpression); - } - - public event Action EnterObjectCreateExpression, LeaveObjectCreateExpression; - - void IAstVisitor.VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression) - { - Visit(EnterObjectCreateExpression, LeaveObjectCreateExpression, objectCreateExpression); - } - - public event Action EnterOutVarDeclarationExpression, LeaveOutVarDeclarationExpression; - - void IAstVisitor.VisitOutVarDeclarationExpression(OutVarDeclarationExpression outVarDeclarationExpression) - { - Visit(EnterOutVarDeclarationExpression, LeaveOutVarDeclarationExpression, outVarDeclarationExpression); - } - - public event Action EnterAnonymousTypeCreateExpression, LeaveAnonymousTypeCreateExpression; - - void IAstVisitor.VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression) - { - Visit(EnterAnonymousTypeCreateExpression, LeaveAnonymousTypeCreateExpression, anonymousTypeCreateExpression); - } - - public event Action EnterArrayCreateExpression, LeaveArrayCreateExpression; - - void IAstVisitor.VisitArrayCreateExpression(ArrayCreateExpression arraySCreateExpression) - { - Visit(EnterArrayCreateExpression, LeaveArrayCreateExpression, arraySCreateExpression); - } - - public event Action EnterParenthesizedExpression, LeaveParenthesizedExpression; - - void IAstVisitor.VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression) - { - Visit(EnterParenthesizedExpression, LeaveParenthesizedExpression, parenthesizedExpression); - } - - public event Action EnterPointerReferenceExpression, LeavePointerReferenceExpression; - - void IAstVisitor.VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression) - { - Visit(EnterPointerReferenceExpression, LeavePointerReferenceExpression, pointerReferenceExpression); - } - - public event Action EnterPrimitiveExpression, LeavePrimitiveExpression; - - void IAstVisitor.VisitPrimitiveExpression(PrimitiveExpression primitiveExpression) - { - Visit(EnterPrimitiveExpression, LeavePrimitiveExpression, primitiveExpression); - } - - public event Action EnterSizeOfExpression, LeaveSizeOfExpression; - - void IAstVisitor.VisitSizeOfExpression(SizeOfExpression sizeOfExpression) - { - Visit(EnterSizeOfExpression, LeaveSizeOfExpression, sizeOfExpression); - } - - public event Action EnterStackAllocExpression, LeaveStackAllocExpression; - - void IAstVisitor.VisitStackAllocExpression(StackAllocExpression stackAllocExpression) - { - Visit(EnterStackAllocExpression, LeaveStackAllocExpression, stackAllocExpression); - } - - public event Action EnterThisReferenceExpression, LeaveThisReferenceExpression; - - void IAstVisitor.VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression) - { - Visit(EnterThisReferenceExpression, LeaveThisReferenceExpression, thisReferenceExpression); - } - - public event Action EnterTypeOfExpression, LeaveTypeOfExpression; - - void IAstVisitor.VisitTypeOfExpression(TypeOfExpression typeOfExpression) - { - Visit(EnterTypeOfExpression, LeaveTypeOfExpression, typeOfExpression); - } - - public event Action EnterTypeReferenceExpression, LeaveTypeReferenceExpression; - - void IAstVisitor.VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression) - { - Visit(EnterTypeReferenceExpression, LeaveTypeReferenceExpression, typeReferenceExpression); - } - - public event Action EnterUnaryOperatorExpression, LeaveUnaryOperatorExpression; - - void IAstVisitor.VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression) - { - Visit(EnterUnaryOperatorExpression, LeaveUnaryOperatorExpression, unaryOperatorExpression); - } - - public event Action EnterUncheckedExpression, LeaveUncheckedExpression; - - void IAstVisitor.VisitUncheckedExpression(UncheckedExpression uncheckedExpression) - { - Visit(EnterUncheckedExpression, LeaveUncheckedExpression, uncheckedExpression); - } - - public event Action EnterQueryExpression, LeaveQueryExpression; - - void IAstVisitor.VisitQueryExpression(QueryExpression queryExpression) - { - Visit(EnterQueryExpression, LeaveQueryExpression, queryExpression); - } - - public event Action EnterQueryContinuationClause, LeaveQueryContinuationClause; - - void IAstVisitor.VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause) - { - Visit(EnterQueryContinuationClause, LeaveQueryContinuationClause, queryContinuationClause); - } - - public event Action EnterQueryFromClause, LeaveQueryFromClause; - - void IAstVisitor.VisitQueryFromClause(QueryFromClause queryFromClause) - { - Visit(EnterQueryFromClause, LeaveQueryFromClause, queryFromClause); - } - - public event Action EnterQueryLetClause, LeaveQueryLetClause; - - void IAstVisitor.VisitQueryLetClause(QueryLetClause queryLetClause) - { - Visit(EnterQueryLetClause, LeaveQueryLetClause, queryLetClause); - } - - public event Action EnterQueryWhereClause, LeaveQueryWhereClause; - - void IAstVisitor.VisitQueryWhereClause(QueryWhereClause queryWhereClause) - { - Visit(EnterQueryWhereClause, LeaveQueryWhereClause, queryWhereClause); - } - - public event Action EnterQueryJoinClause, LeaveQueryJoinClause; - - void IAstVisitor.VisitQueryJoinClause(QueryJoinClause queryJoinClause) - { - Visit(EnterQueryJoinClause, LeaveQueryJoinClause, queryJoinClause); - } - - public event Action EnterQueryOrderClause, LeaveQueryOrderClause; - - void IAstVisitor.VisitQueryOrderClause(QueryOrderClause queryOrderClause) - { - Visit(EnterQueryOrderClause, LeaveQueryOrderClause, queryOrderClause); - } - - public event Action EnterQueryOrdering, LeaveQueryOrdering; - - void IAstVisitor.VisitQueryOrdering(QueryOrdering queryOrdering) - { - Visit(EnterQueryOrdering, LeaveQueryOrdering, queryOrdering); - } - - public event Action EnterQuerySelectClause, LeaveQuerySelectClause; - - void IAstVisitor.VisitQuerySelectClause(QuerySelectClause querySelectClause) - { - Visit(EnterQuerySelectClause, LeaveQuerySelectClause, querySelectClause); - } - - public event Action EnterQueryGroupClause, LeaveQueryGroupClause; - - void IAstVisitor.VisitQueryGroupClause(QueryGroupClause queryGroupClause) - { - Visit(EnterQueryGroupClause, LeaveQueryGroupClause, queryGroupClause); - } - - public event Action EnterAsExpression, LeaveAsExpression; - - void IAstVisitor.VisitAsExpression(AsExpression asExpression) - { - Visit(EnterAsExpression, LeaveAsExpression, asExpression); - } - - public event Action EnterIsExpression, LeaveIsExpression; - - void IAstVisitor.VisitIsExpression(IsExpression isExpression) - { - Visit(EnterIsExpression, LeaveIsExpression, isExpression); - } - - public event Action EnterDefaultValueExpression, LeaveDefaultValueExpression; - - void IAstVisitor.VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression) - { - Visit(EnterDefaultValueExpression, LeaveDefaultValueExpression, defaultValueExpression); - } - - public event Action EnterUndocumentedExpression, LeaveUndocumentedExpression; - - void IAstVisitor.VisitUndocumentedExpression(UndocumentedExpression undocumentedExpression) - { - Visit(EnterUndocumentedExpression, LeaveUndocumentedExpression, undocumentedExpression); - } - - public event Action EnterArrayInitializerExpression, LeaveArrayInitializerExpression; - - void IAstVisitor.VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression) - { - Visit(EnterArrayInitializerExpression, LeaveArrayInitializerExpression, arrayInitializerExpression); - } - - public event Action EnterArraySpecifier, LeaveArraySpecifier; - - void IAstVisitor.VisitArraySpecifier(ArraySpecifier arraySpecifier) - { - Visit(EnterArraySpecifier, LeaveArraySpecifier, arraySpecifier); - } - - public event Action EnterNamedArgumentExpression, LeaveNamedArgumentExpression; - - void IAstVisitor.VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression) - { - Visit(EnterNamedArgumentExpression, LeaveNamedArgumentExpression, namedArgumentExpression); - } - - public event Action EnterNamedExpression, LeaveNamedExpression; - - void IAstVisitor.VisitNamedExpression(NamedExpression namedExpression) - { - Visit(EnterNamedExpression, LeaveNamedExpression, namedExpression); - } - - void IAstVisitor.VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern) - { - } - } -} diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs b/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs index 08de6c154..31ccf68de 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs @@ -24,7 +24,6 @@ using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; using ICSharpCode.Decompiler.CSharp.TypeSystem; using ICSharpCode.Decompiler.TypeSystem; -using ICSharpCode.Decompiler.CSharp.Analysis; using Mono.Cecil; using ICSharpCode.Decompiler.Semantics; @@ -313,34 +312,6 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return null; } - /// - /// Gets whether the old variable value (assigned inside 'targetStatement' or earlier) - /// is read anywhere in the remaining scope of the variable declaration. - /// - bool IsVariableValueUnused(VariableDeclarationStatement varDecl, Statement targetStatement) - { - Debug.Assert(targetStatement.Ancestors.Contains(varDecl.Parent)); - BlockStatement block = (BlockStatement)varDecl.Parent; - DefiniteAssignmentAnalysis daa = CreateDAA(block); - daa.SetAnalyzedRange(targetStatement, block, startInclusive: false); - daa.Analyze(varDecl.Variables.Single().Name); - return daa.UnassignedVariableUses.Count == 0; - } - - // I used this in the first implementation of the using-statement transform, but now no longer - // because there were problems when multiple using statements were using the same variable - // - no single using statement could be transformed without making the C# code invalid, - // but transforming both would work. - // We now use 'IsVariableValueUnused' which will perform the transform - // even if it results in two variables with the same name and overlapping scopes. - // (this issue could be fixed later by renaming one of the variables) - - private DefiniteAssignmentAnalysis CreateDAA(BlockStatement block) - { - var typeResolveContext = new CSharpTypeResolveContext(context.TypeSystem.MainAssembly); - return new DefiniteAssignmentAnalysis(block, (node, ct) => node.GetResolveResult(), typeResolveContext, context.CancellationToken); - } - /// /// Gets whether there is an assignment to 'variableName' anywhere within the given node. /// diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index ae7d5674e..5391e1b93 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -54,8 +54,6 @@ - - @@ -128,7 +126,6 @@ - @@ -204,22 +201,17 @@ - - - - -