summaryrefslogtreecommitdiff
path: root/ICSharpCode.Decompiler
diff options
context:
space:
mode:
authorStephane Delcroix <stephane@delcroix.org>2016-12-05 13:31:31 +0100
committerGitHub <noreply@github.com>2016-12-05 13:31:31 +0100
commit1a5bead2f2e24cc16da23753eaf0882d38d54ea1 (patch)
tree2fb4bf607ca11d9ed5163ed329796ca651054a6a /ICSharpCode.Decompiler
parent3692786c3a0f9ba01ffe9516caa624a018ac885a (diff)
downloadxamarin-forms-1a5bead2f2e24cc16da23753eaf0882d38d54ea1.tar.gz
xamarin-forms-1a5bead2f2e24cc16da23753eaf0882d38d54ea1.tar.bz2
xamarin-forms-1a5bead2f2e24cc16da23753eaf0882d38d54ea1.zip
[XamlC] drop ICSharpCode.Decompiler (#586)
* [XamlC] drop ICSharpCode.Decompiler * update nuspec * fix typo
Diffstat (limited to 'ICSharpCode.Decompiler')
-rw-r--r--ICSharpCode.Decompiler/Ast/Annotations.cs52
-rw-r--r--ICSharpCode.Decompiler/Ast/AstBuilder.cs1687
-rw-r--r--ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs1220
-rw-r--r--ICSharpCode.Decompiler/Ast/CommentStatement.cs69
-rw-r--r--ICSharpCode.Decompiler/Ast/DecompilerContext.cs71
-rw-r--r--ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs86
-rw-r--r--ICSharpCode.Decompiler/Ast/NameVariables.cs347
-rw-r--r--ICSharpCode.Decompiler/Ast/TextTokenWriter.cs369
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/AddCheckedBlocks.cs368
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/CombineQueryExpressions.cs179
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/ContextTrackingVisitor.cs111
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs183
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/CustomPatterns.cs109
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs58
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs368
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs502
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/ExpressionTreeConverter.cs875
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/FlattenSwitchBlocks.cs27
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/IntroduceExtensionMethods.cs66
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/IntroduceQueryExpressions.cs295
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs106
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs359
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs1123
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs164
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs356
-rw-r--r--ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs65
-rw-r--r--ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs536
-rw-r--r--ICSharpCode.Decompiler/CecilExtensions.cs374
-rw-r--r--ICSharpCode.Decompiler/CodeMappings.cs57
-rw-r--r--ICSharpCode.Decompiler/DecompilerException.cs42
-rw-r--r--ICSharpCode.Decompiler/DecompilerSettings.cs356
-rw-r--r--ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs447
-rw-r--r--ICSharpCode.Decompiler/Disassembler/ILStructure.cs228
-rw-r--r--ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs239
-rw-r--r--ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs1168
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/ControlFlowEdge.cs78
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/ControlFlowGraph.cs191
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/ControlFlowGraphBuilder.cs439
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/ControlFlowNode.cs305
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/ControlStructureDetector.cs241
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/OpCodeInfo.cs312
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/SimplifyByRefCalls.cs174
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/SsaBlock.cs60
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/SsaForm.cs162
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/SsaFormBuilder.cs257
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/SsaInstruction.cs191
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/SsaOptimization.cs138
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/SsaVariable.cs91
-rw-r--r--ICSharpCode.Decompiler/FlowAnalysis/TransformToSsa.cs254
-rw-r--r--ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj167
-rw-r--r--ICSharpCode.Decompiler/ICSharpCode.Decompiler.sln17
-rw-r--r--ICSharpCode.Decompiler/ILAst/AsyncDecompiler.cs704
-rw-r--r--ICSharpCode.Decompiler/ILAst/DefaultDictionary.cs128
-rw-r--r--ICSharpCode.Decompiler/ILAst/GotoRemoval.cs319
-rw-r--r--ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs839
-rw-r--r--ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs988
-rw-r--r--ICSharpCode.Decompiler/ILAst/ILAstTypes.cs601
-rw-r--r--ICSharpCode.Decompiler/ILAst/ILCodes.cs490
-rw-r--r--ICSharpCode.Decompiler/ILAst/ILInlining.cs524
-rw-r--r--ICSharpCode.Decompiler/ILAst/InitializerPeepholeTransforms.cs535
-rw-r--r--ICSharpCode.Decompiler/ILAst/LiftedOperators.cs528
-rw-r--r--ICSharpCode.Decompiler/ILAst/LoopsAndConditions.cs443
-rw-r--r--ICSharpCode.Decompiler/ILAst/PatternMatching.cs177
-rw-r--r--ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs1103
-rw-r--r--ICSharpCode.Decompiler/ILAst/SimpleControlFlow.cs376
-rw-r--r--ICSharpCode.Decompiler/ILAst/StateRange.cs312
-rw-r--r--ICSharpCode.Decompiler/ILAst/SymbolicExecution.cs157
-rw-r--r--ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs1294
-rw-r--r--ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs635
-rw-r--r--ICSharpCode.Decompiler/ITextOutput.cs62
-rw-r--r--ICSharpCode.Decompiler/PlainTextOutput.cs122
-rw-r--r--ICSharpCode.Decompiler/Properties/AssemblyInfo.template.cs27
-rw-r--r--ICSharpCode.Decompiler/ReferenceResolvingException.cs68
-rw-r--r--ICSharpCode.Decompiler/Tests/Async.cs155
-rw-r--r--ICSharpCode.Decompiler/Tests/BooleanConsumedAsInteger.il59
-rw-r--r--ICSharpCode.Decompiler/Tests/CallOverloadedMethod.cs52
-rw-r--r--ICSharpCode.Decompiler/Tests/CheckedUnchecked.cs117
-rw-r--r--ICSharpCode.Decompiler/Tests/CodeSampleFileParser.cs133
-rw-r--r--ICSharpCode.Decompiler/Tests/ControlFlow.cs97
-rw-r--r--ICSharpCode.Decompiler/Tests/CustomAttributes.code.cs41
-rw-r--r--ICSharpCode.Decompiler/Tests/CustomAttributes/CustomAttributeTests.cs30
-rw-r--r--ICSharpCode.Decompiler/Tests/CustomAttributes/S_AssemblyCustomAttribute.cs21
-rw-r--r--ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributeSamples.cs508
-rw-r--r--ICSharpCode.Decompiler/Tests/CustomAttributes/S_CustomAttributes.cs79
-rw-r--r--ICSharpCode.Decompiler/Tests/CustomShortCircuitOperators.cs88
-rw-r--r--ICSharpCode.Decompiler/Tests/DecompilerTestBase.cs89
-rw-r--r--ICSharpCode.Decompiler/Tests/DelegateConstruction.cs205
-rw-r--r--ICSharpCode.Decompiler/Tests/DoubleConstants.cs28
-rw-r--r--ICSharpCode.Decompiler/Tests/ExceptionHandling.cs128
-rw-r--r--ICSharpCode.Decompiler/Tests/ExpressionTrees.cs370
-rw-r--r--ICSharpCode.Decompiler/Tests/Generics.cs165
-rw-r--r--ICSharpCode.Decompiler/Tests/Helpers/CodeAssert.cs110
-rw-r--r--ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs38
-rw-r--r--ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj137
-rw-r--r--ICSharpCode.Decompiler/Tests/IL/ILTests.cs51
-rw-r--r--ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.Output.cs53
-rw-r--r--ICSharpCode.Decompiler/Tests/IL/SequenceOfNestedIfs.il140
-rw-r--r--ICSharpCode.Decompiler/Tests/IL/StackTests.il132
-rw-r--r--ICSharpCode.Decompiler/Tests/IncrementDecrement.cs254
-rw-r--r--ICSharpCode.Decompiler/Tests/InitializerTests.cs885
-rw-r--r--ICSharpCode.Decompiler/Tests/LiftedOperators.cs830
-rw-r--r--ICSharpCode.Decompiler/Tests/Lock.cs38
-rw-r--r--ICSharpCode.Decompiler/Tests/Loops.cs74
-rw-r--r--ICSharpCode.Decompiler/Tests/MultidimensionalArray.cs58
-rw-r--r--ICSharpCode.Decompiler/Tests/PInvoke.cs96
-rw-r--r--ICSharpCode.Decompiler/Tests/PropertiesAndEvents.cs80
-rw-r--r--ICSharpCode.Decompiler/Tests/QueryExpressions.cs188
-rw-r--r--ICSharpCode.Decompiler/Tests/Switch.cs89
-rw-r--r--ICSharpCode.Decompiler/Tests/TestRunner.cs198
-rw-r--r--ICSharpCode.Decompiler/Tests/TypeAnalysisTests.cs153
-rw-r--r--ICSharpCode.Decompiler/Tests/Types/EnumTests.cs18
-rw-r--r--ICSharpCode.Decompiler/Tests/Types/S_EnumSamples.cs129
-rw-r--r--ICSharpCode.Decompiler/Tests/Types/S_TypeDeclarations.cs17
-rw-r--r--ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs1138
-rw-r--r--ICSharpCode.Decompiler/Tests/Types/TypeTests.cs18
-rw-r--r--ICSharpCode.Decompiler/Tests/UndocumentedExpressions.cs41
-rw-r--r--ICSharpCode.Decompiler/Tests/UnsafeCode.cs145
-rw-r--r--ICSharpCode.Decompiler/Tests/ValueTypes.cs188
-rw-r--r--ICSharpCode.Decompiler/Tests/YieldReturn.cs148
-rw-r--r--ICSharpCode.Decompiler/Tests/packages.config6
-rw-r--r--ICSharpCode.Decompiler/TextOutputWriter.cs55
-rw-r--r--ICSharpCode.Decompiler/packages.config5
122 files changed, 0 insertions, 34048 deletions
diff --git a/ICSharpCode.Decompiler/Ast/Annotations.cs b/ICSharpCode.Decompiler/Ast/Annotations.cs
deleted file mode 100644
index ec9fd61f..00000000
--- a/ICSharpCode.Decompiler/Ast/Annotations.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using ICSharpCode.Decompiler.ILAst;
-using ICSharpCode.NRefactory.CSharp;
-using Mono.Cecil;
-
-namespace ICSharpCode.Decompiler.Ast
-{
- public class TypeInformation
- {
- public readonly TypeReference InferredType;
- public readonly TypeReference ExpectedType;
-
- public TypeInformation(TypeReference inferredType, TypeReference expectedType)
- {
- InferredType = inferredType;
- ExpectedType = expectedType;
- }
- }
-
- public class LdTokenAnnotation {}
-
- /// <summary>
- /// Annotation that is applied to the body expression of an Expression.Lambda() call.
- /// </summary>
- public class ParameterDeclarationAnnotation
- {
- public readonly List<ParameterDeclaration> Parameters = new List<ParameterDeclaration>();
-
- public ParameterDeclarationAnnotation(ILExpression expr)
- {
- Debug.Assert(expr.Code == ILCode.ExpressionTreeParameterDeclarations);
- for (int i = 0; i < expr.Arguments.Count - 1; i++) {
- ILExpression p = expr.Arguments[i];
- // p looks like this:
- // stloc(v, call(Expression::Parameter, call(Type::GetTypeFromHandle, ldtoken(...)), ldstr(...)))
- ILVariable v = (ILVariable)p.Operand;
- TypeReference typeRef = (TypeReference)p.Arguments[0].Arguments[0].Arguments[0].Operand;
- string name = (string)p.Arguments[0].Arguments[1].Operand;
- Parameters.Add(new ParameterDeclaration(AstBuilder.ConvertType(typeRef), name).WithAnnotation(v));
- }
- }
- }
-
- /// <summary>
- /// Annotation that is applied to a LambdaExpression that was produced by an expression tree.
- /// </summary>
- public class ExpressionTreeLambdaAnnotation
- {
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs
deleted file mode 100644
index 9a53237a..00000000
--- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs
+++ /dev/null
@@ -1,1687 +0,0 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this
-// software and associated documentation files (the "Software"), to deal in the Software
-// without restriction, including without limitation the rights to use, copy, modify, merge,
-// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
-// to whom the Software is furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-// DEALINGS IN THE SOFTWARE.
-
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Diagnostics;
-using System.IO;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Threading;
-
-using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Ast.Transforms;
-using ICSharpCode.Decompiler.ILAst;
-using ICSharpCode.NRefactory.CSharp;
-using ICSharpCode.NRefactory.Utils;
-using Mono.Cecil;
-using Mono.Cecil.Cil;
-
-namespace ICSharpCode.Decompiler.Ast
-{
- using Ast = NRefactory.CSharp;
- using VarianceModifier = NRefactory.TypeSystem.VarianceModifier;
-
- [Flags]
- public enum ConvertTypeOptions
- {
- None = 0,
- IncludeNamespace = 1,
- IncludeTypeParameterDefinitions = 2,
- DoNotUsePrimitiveTypeNames = 4
- }
-
- public class AstBuilder
- {
- DecompilerContext context;
- SyntaxTree syntaxTree = new SyntaxTree();
- Dictionary<string, NamespaceDeclaration> astNamespaces = new Dictionary<string, NamespaceDeclaration>();
- bool transformationsHaveRun;
-
- public AstBuilder(DecompilerContext context)
- {
- if (context == null)
- throw new ArgumentNullException("context");
- this.context = context;
- DecompileMethodBodies = true;
- }
-
- public static bool MemberIsHidden(MemberReference member, DecompilerSettings settings)
- {
- MethodDefinition method = member as MethodDefinition;
- if (method != null) {
- if (method.IsGetter || method.IsSetter || method.IsAddOn || method.IsRemoveOn)
- return true;
- if (settings.AnonymousMethods && method.HasGeneratedName() && method.IsCompilerGenerated())
- return true;
- }
-
- TypeDefinition type = member as TypeDefinition;
- if (type != null) {
- if (type.DeclaringType != null) {
- if (settings.AnonymousMethods && IsClosureType(type))
- return true;
- if (settings.YieldReturn && YieldReturnDecompiler.IsCompilerGeneratorEnumerator(type))
- return true;
- if (settings.AsyncAwait && AsyncDecompiler.IsCompilerGeneratedStateMachine(type))
- return true;
- } else if (type.IsCompilerGenerated()) {
- if (type.Name.StartsWith("<PrivateImplementationDetails>", StringComparison.Ordinal))
- return true;
- if (type.IsAnonymousType())
- return true;
- }
- }
-
- FieldDefinition field = member as FieldDefinition;
- if (field != null) {
- if (field.IsCompilerGenerated()) {
- if (settings.AnonymousMethods && IsAnonymousMethodCacheField(field))
- return true;
- if (settings.AutomaticProperties && IsAutomaticPropertyBackingField(field))
- return true;
- if (settings.SwitchStatementOnString && IsSwitchOnStringCache(field))
- return true;
- }
- // event-fields are not [CompilerGenerated]
- if (settings.AutomaticEvents && field.DeclaringType.Events.Any(ev => ev.Name == field.Name))
- return true;
- }
-
- return false;
- }
-
- static bool IsSwitchOnStringCache(FieldDefinition field)
- {
- return field.Name.StartsWith("<>f__switch", StringComparison.Ordinal);
- }
-
- static bool IsAutomaticPropertyBackingField(FieldDefinition field)
- {
- return field.HasGeneratedName() && field.Name.EndsWith("BackingField", StringComparison.Ordinal);
- }
-
- static bool IsAnonymousMethodCacheField(FieldDefinition field)
- {
- return field.Name.StartsWith("CS$<>", StringComparison.Ordinal) || field.Name.StartsWith("<>f__am", StringComparison.Ordinal);
- }
-
- static bool IsClosureType(TypeDefinition type)
- {
- return type.HasGeneratedName() && type.IsCompilerGenerated() && (type.Name.Contains("DisplayClass") || type.Name.Contains("AnonStorey"));
- }
-
- /// <summary>
- /// Runs the C# transformations on the compilation unit.
- /// </summary>
- public void RunTransformations()
- {
- RunTransformations(null);
- }
-
- public void RunTransformations(Predicate<IAstTransform> transformAbortCondition)
- {
- TransformationPipeline.RunTransformationsUntil(syntaxTree, transformAbortCondition, context);
- transformationsHaveRun = true;
- }
-
- /// <summary>
- /// Gets the abstract source tree.
- /// </summary>
- public SyntaxTree SyntaxTree {
- get { return syntaxTree; }
- }
-
- /// <summary>
- /// Generates C# code from the abstract source tree.
- /// </summary>
- public void GenerateCode(ITextOutput output)
- {
- if (!transformationsHaveRun)
- RunTransformations();
-
- syntaxTree.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true });
- var outputFormatter = new TextTokenWriter(output, context) { FoldBraces = context.Settings.FoldBraces };
- var formattingPolicy = context.Settings.CSharpFormattingOptions;
- syntaxTree.AcceptVisitor(new CSharpOutputVisitor(outputFormatter, formattingPolicy));
- }
-
- public void AddAssembly(AssemblyDefinition assemblyDefinition, bool onlyAssemblyLevel = false)
- {
- AddAssembly(assemblyDefinition.MainModule, onlyAssemblyLevel);
- }
-
- public void AddAssembly(ModuleDefinition moduleDefinition, bool onlyAssemblyLevel = false)
- {
- if (moduleDefinition.Assembly != null && moduleDefinition.Assembly.Name.Version != null) {
- syntaxTree.AddChild(
- new AttributeSection {
- AttributeTarget = "assembly",
- Attributes = {
- new NRefactory.CSharp.Attribute {
- Type = new SimpleType("AssemblyVersion")
- .WithAnnotation(new TypeReference(
- "System.Reflection", "AssemblyVersionAttribute",
- moduleDefinition, moduleDefinition.TypeSystem.Corlib)),
- Arguments = {
- new PrimitiveExpression(moduleDefinition.Assembly.Name.Version.ToString())
- }
- }
- }
- }, EntityDeclaration.AttributeRole);
- }
-
- if (moduleDefinition.Assembly != null) {
- ConvertCustomAttributes(syntaxTree, moduleDefinition.Assembly, "assembly");
- ConvertSecurityAttributes(syntaxTree, moduleDefinition.Assembly, "assembly");
- }
- ConvertCustomAttributes(syntaxTree, moduleDefinition, "module");
- AddTypeForwarderAttributes(syntaxTree, moduleDefinition, "assembly");
-
- if (!onlyAssemblyLevel) {
- foreach (TypeDefinition typeDef in moduleDefinition.Types) {
- // Skip the <Module> class
- if (typeDef.Name == "<Module>") continue;
- // Skip any hidden types
- if (MemberIsHidden(typeDef, context.Settings))
- continue;
-
- AddType(typeDef);
- }
- }
- }
-
- void AddTypeForwarderAttributes(SyntaxTree astCompileUnit, ModuleDefinition module, string target)
- {
- if (!module.HasExportedTypes)
- return;
- foreach (ExportedType type in module.ExportedTypes) {
- if (type.IsForwarder) {
- var forwardedType = CreateTypeOfExpression(new TypeReference(type.Namespace, type.Name, module, type.Scope));
- astCompileUnit.AddChild(
- new AttributeSection {
- AttributeTarget = target,
- Attributes = {
- new NRefactory.CSharp.Attribute {
- Type = new SimpleType("TypeForwardedTo")
- .WithAnnotation(new TypeReference(
- "System.Runtime.CompilerServices", "TypeForwardedToAttribute",
- module, module.TypeSystem.Corlib)),
- Arguments = { forwardedType }
- }
- }
- }, EntityDeclaration.AttributeRole);
- }
- }
- }
-
- NamespaceDeclaration GetCodeNamespace(string name)
- {
- if (string.IsNullOrEmpty(name)) {
- return null;
- }
- if (astNamespaces.ContainsKey(name)) {
- return astNamespaces[name];
- } else {
- // Create the namespace
- NamespaceDeclaration astNamespace = new NamespaceDeclaration { Name = name };
- syntaxTree.Members.Add(astNamespace);
- astNamespaces[name] = astNamespace;
- return astNamespace;
- }
- }
-
- public void AddType(TypeDefinition typeDef)
- {
- var astType = CreateType(typeDef);
- NamespaceDeclaration astNS = GetCodeNamespace(typeDef.Namespace);
- if (astNS != null) {
- astNS.Members.Add(astType);
- } else {
- syntaxTree.Members.Add(astType);
- }
- }
-
- public void AddMethod(MethodDefinition method)
- {
- AstNode node = method.IsConstructor ? (AstNode)CreateConstructor(method) : CreateMethod(method);
- syntaxTree.Members.Add(node);
- }
-
- public void AddProperty(PropertyDefinition property)
- {
- syntaxTree.Members.Add(CreateProperty(property));
- }
-
- public void AddField(FieldDefinition field)
- {
- syntaxTree.Members.Add(CreateField(field));
- }
-
- public void AddEvent(EventDefinition ev)
- {
- syntaxTree.Members.Add(CreateEvent(ev));
- }
-
- /// <summary>
- /// Creates the AST for a type definition.
- /// </summary>
- /// <param name="typeDef"></param>
- /// <returns>TypeDeclaration or DelegateDeclaration.</returns>
- public EntityDeclaration CreateType(TypeDefinition typeDef)
- {
- // create type
- TypeDefinition oldCurrentType = context.CurrentType;
- context.CurrentType = typeDef;
- TypeDeclaration astType = new TypeDeclaration();
- ConvertAttributes(astType, typeDef);
- astType.AddAnnotation(typeDef);
- astType.Modifiers = ConvertModifiers(typeDef);
- astType.Name = CleanName(typeDef.Name);
-
- if (typeDef.IsEnum) { // NB: Enum is value type
- astType.ClassType = ClassType.Enum;
- astType.Modifiers &= ~Modifiers.Sealed;
- } else if (typeDef.IsValueType) {
- astType.ClassType = ClassType.Struct;
- astType.Modifiers &= ~Modifiers.Sealed;
- } else if (typeDef.IsInterface) {
- astType.ClassType = ClassType.Interface;
- astType.Modifiers &= ~Modifiers.Abstract;
- } else {
- astType.ClassType = ClassType.Class;
- }
-
- IEnumerable<GenericParameter> genericParameters = typeDef.GenericParameters;
- if (typeDef.DeclaringType != null && typeDef.DeclaringType.HasGenericParameters)
- genericParameters = genericParameters.Skip(typeDef.DeclaringType.GenericParameters.Count);
- astType.TypeParameters.AddRange(MakeTypeParameters(genericParameters));
- astType.Constraints.AddRange(MakeConstraints(genericParameters));
-
- EntityDeclaration result = astType;
- if (typeDef.IsEnum) {
- long expectedEnumMemberValue = 0;
- bool forcePrintingInitializers = IsFlagsEnum(typeDef);
- TypeCode baseType = TypeCode.Int32;
- foreach (FieldDefinition field in typeDef.Fields) {
- if (!field.IsStatic) {
- // the value__ field
- if (field.FieldType != typeDef.Module.TypeSystem.Int32) {
- astType.AddChild(ConvertType(field.FieldType), Roles.BaseType);
- baseType = TypeAnalysis.GetTypeCode(field.FieldType);
- }
- } else {
- EnumMemberDeclaration enumMember = new EnumMemberDeclaration();
- enumMember.AddAnnotation(field);
- enumMember.Name = CleanName(field.Name);
- long memberValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false);
- if (forcePrintingInitializers || memberValue != expectedEnumMemberValue) {
- enumMember.AddChild(new PrimitiveExpression(CSharpPrimitiveCast.Cast(baseType, field.Constant, false)), EnumMemberDeclaration.InitializerRole);
- }
- expectedEnumMemberValue = memberValue + 1;
- astType.AddChild(enumMember, Roles.TypeMemberRole);
- }
- }
- } else if (typeDef.BaseType != null && typeDef.BaseType.FullName == "System.MulticastDelegate") {
- DelegateDeclaration dd = new DelegateDeclaration();
- dd.Modifiers = astType.Modifiers & ~Modifiers.Sealed;
- dd.Name = astType.Name;
- dd.AddAnnotation(typeDef);
- astType.Attributes.MoveTo(dd.Attributes);
- astType.TypeParameters.MoveTo(dd.TypeParameters);
- astType.Constraints.MoveTo(dd.Constraints);
- foreach (var m in typeDef.Methods) {
- if (m.Name == "Invoke") {
- dd.ReturnType = ConvertType(m.ReturnType, m.MethodReturnType);
- dd.Parameters.AddRange(MakeParameters(m));
- ConvertAttributes(dd, m.MethodReturnType, m.Module);
- }
- }
- result = dd;
- } else {
- // Base type
- if (typeDef.BaseType != null && !typeDef.IsValueType && typeDef.BaseType.FullName != "System.Object") {
- astType.AddChild(ConvertType(typeDef.BaseType), Roles.BaseType);
- }
- foreach (var i in typeDef.Interfaces)
- astType.AddChild(ConvertType(i), Roles.BaseType);
-
- AddTypeMembers(astType, typeDef);
-
- if (astType.Members.OfType<IndexerDeclaration>().Any(idx => idx.PrivateImplementationType.IsNull)) {
- // Remove the [DefaultMember] attribute if the class contains indexers
- foreach (AttributeSection section in astType.Attributes) {
- foreach (Ast.Attribute attr in section.Attributes) {
- TypeReference tr = attr.Type.Annotation<TypeReference>();
- if (tr != null && tr.Name == "DefaultMemberAttribute" && tr.Namespace == "System.Reflection") {
- attr.Remove();
- }
- }
- if (section.Attributes.Count == 0)
- section.Remove();
- }
- }
- }
-
- context.CurrentType = oldCurrentType;
- return result;
- }
-
- internal static string CleanName(string name)
- {
- int pos = name.LastIndexOf('`');
- if (pos >= 0)
- name = name.Substring(0, pos);
- pos = name.LastIndexOf('.');
- if (pos >= 0)
- name = name.Substring(pos + 1);
- return name;
- }
-
- #region Create TypeOf Expression
- /// <summary>
- /// Creates a typeof-expression for the specified type.
- /// </summary>
- public static TypeOfExpression CreateTypeOfExpression(TypeReference type)
- {
- return new TypeOfExpression(AddEmptyTypeArgumentsForUnboundGenerics(ConvertType(type)));
- }
-
- static AstType AddEmptyTypeArgumentsForUnboundGenerics(AstType type)
- {
- TypeReference typeRef = type.Annotation<TypeReference>();
- if (typeRef == null)
- return type;
- TypeDefinition typeDef = typeRef.Resolve(); // need to resolve to figure out the number of type parameters
- if (typeDef == null || !typeDef.HasGenericParameters)
- return type;
- SimpleType sType = type as SimpleType;
- MemberType mType = type as MemberType;
- if (sType != null) {
- while (typeDef.GenericParameters.Count > sType.TypeArguments.Count) {
- sType.TypeArguments.Add(new SimpleType(""));
- }
- }
-
- if (mType != null) {
- AddEmptyTypeArgumentsForUnboundGenerics(mType.Target);
-
- int outerTypeParamCount = typeDef.DeclaringType == null ? 0 : typeDef.DeclaringType.GenericParameters.Count;
-
- while (typeDef.GenericParameters.Count - outerTypeParamCount > mType.TypeArguments.Count) {
- mType.TypeArguments.Add(new SimpleType(""));
- }
- }
-
- return type;
- }
- #endregion
-
- #region Convert Type Reference
- /// <summary>
- /// Converts a type reference.
- /// </summary>
- public static AstType ConvertType(TypeReference type, ICustomAttributeProvider typeAttributes = null, ConvertTypeOptions options = ConvertTypeOptions.None)
- {
- int typeIndex = 0;
- return ConvertType(type, typeAttributes, ref typeIndex, options);
- }
-
- static AstType ConvertType(TypeReference type, ICustomAttributeProvider typeAttributes, ref int typeIndex, ConvertTypeOptions options)
- {
- while (type is OptionalModifierType || type is RequiredModifierType) {
- type = ((TypeSpecification)type).ElementType;
- }
- if (type == null) {
- return AstType.Null;
- }
-
- if (type is ByReferenceType) {
- typeIndex++;
- // by reference type cannot be represented in C#; so we'll represent it as a pointer instead
- return ConvertType((type as ByReferenceType).ElementType, typeAttributes, ref typeIndex, options)
- .MakePointerType();
- } else if (type is PointerType) {
- typeIndex++;
- return ConvertType((type as PointerType).ElementType, typeAttributes, ref typeIndex, options)
- .MakePointerType();
- } else if (type is ArrayType) {
- typeIndex++;
- return ConvertType((type as ArrayType).ElementType, typeAttributes, ref typeIndex, options)
- .MakeArrayType((type as ArrayType).Rank);
- } else if (type is GenericInstanceType) {
- GenericInstanceType gType = (GenericInstanceType)type;
- if (gType.ElementType.Namespace == "System" && gType.ElementType.Name == "Nullable`1" && gType.GenericArguments.Count == 1) {
- typeIndex++;
- return new ComposedType {
- BaseType = ConvertType(gType.GenericArguments[0], typeAttributes, ref typeIndex, options),
- HasNullableSpecifier = true
- };
- }
- AstType baseType = ConvertType(gType.ElementType, typeAttributes, ref typeIndex, options & ~ConvertTypeOptions.IncludeTypeParameterDefinitions);
- List<AstType> typeArguments = new List<AstType>();
- foreach (var typeArgument in gType.GenericArguments) {
- typeIndex++;
- typeArguments.Add(ConvertType(typeArgument, typeAttributes, ref typeIndex, options));
- }
- ApplyTypeArgumentsTo(baseType, typeArguments);
- return baseType;
- } else if (type is GenericParameter) {
- return new SimpleType(type.Name);
- } else if (type.IsNested) {
- AstType typeRef = ConvertType(type.DeclaringType, typeAttributes, ref typeIndex, options & ~ConvertTypeOptions.IncludeTypeParameterDefinitions);
- string namepart = NRefactory.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name);
- MemberType memberType = new MemberType { Target = typeRef, MemberName = namepart };
- memberType.AddAnnotation(type);
- if ((options & ConvertTypeOptions.IncludeTypeParameterDefinitions) == ConvertTypeOptions.IncludeTypeParameterDefinitions) {
- AddTypeParameterDefininitionsTo(type, memberType);
- }
- return memberType;
- } else {
- string ns = type.Namespace ?? string.Empty;
- string name = type.Name;
- if (name == null)
- throw new InvalidOperationException("type.Name returned null. Type: " + type.ToString());
-
- if (name == "Object" && ns == "System" && HasDynamicAttribute(typeAttributes, typeIndex)) {
- return new PrimitiveType("dynamic");
- } else {
- if (ns == "System") {
- if ((options & ConvertTypeOptions.DoNotUsePrimitiveTypeNames)
- != ConvertTypeOptions.DoNotUsePrimitiveTypeNames) {
- switch (name) {
- case "SByte":
- return new PrimitiveType("sbyte");
- case "Int16":
- return new PrimitiveType("short");
- case "Int32":
- return new PrimitiveType("int");
- case "Int64":
- return new PrimitiveType("long");
- case "Byte":
- return new PrimitiveType("byte");
- case "UInt16":
- return new PrimitiveType("ushort");
- case "UInt32":
- return new PrimitiveType("uint");
- case "UInt64":
- return new PrimitiveType("ulong");
- case "String":
- return new PrimitiveType("string");
- case "Single":
- return new PrimitiveType("float");
- case "Double":
- return new PrimitiveType("double");
- case "Decimal":
- return new PrimitiveType("decimal");
- case "Char":
- return new PrimitiveType("char");
- case "Boolean":
- return new PrimitiveType("bool");
- case "Void":
- return new PrimitiveType("void");
- case "Object":
- return new PrimitiveType("object");
- }
- }
- }
-
- name = NRefactory.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(name);
-
- AstType astType;
- if ((options & ConvertTypeOptions.IncludeNamespace) == ConvertTypeOptions.IncludeNamespace && ns.Length > 0) {
- string[] parts = ns.Split('.');
- AstType nsType = new SimpleType(parts[0]);
- for (int i = 1; i < parts.Length; i++) {
- nsType = new MemberType { Target = nsType, MemberName = parts[i] };
- }
- astType = new MemberType { Target = nsType, MemberName = name };
- } else {
- astType = new SimpleType(name);
- }
- astType.AddAnnotation(type);
-
- if ((options & ConvertTypeOptions.IncludeTypeParameterDefinitions) == ConvertTypeOptions.IncludeTypeParameterDefinitions) {
- AddTypeParameterDefininitionsTo(type, astType);
- }
- return astType;
- }
- }
- }
-
- static void AddTypeParameterDefininitionsTo(TypeReference type, AstType astType)
- {
- if (type.HasGenericParameters) {
- List<AstType> typeArguments = new List<AstType>();
- foreach (GenericParameter gp in type.GenericParameters) {
- typeArguments.Add(new SimpleType(gp.Name));
- }
- ApplyTypeArgumentsTo(astType, typeArguments);
- }
- }
-
- static void ApplyTypeArgumentsTo(AstType baseType, List<AstType> typeArguments)
- {
- SimpleType st = baseType as SimpleType;
- if (st != null) {
- st.TypeArguments.AddRange(typeArguments);
- }
- MemberType mt = baseType as MemberType;
- if (mt != null) {
- TypeReference type = mt.Annotation<TypeReference>();
- if (type != null) {
- int typeParameterCount;
- NRefactory.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount);
- if (typeParameterCount > typeArguments.Count)
- typeParameterCount = typeArguments.Count;
- mt.TypeArguments.AddRange(typeArguments.GetRange(typeArguments.Count - typeParameterCount, typeParameterCount));
- typeArguments.RemoveRange(typeArguments.Count - typeParameterCount, typeParameterCount);
- if (typeArguments.Count > 0)
- ApplyTypeArgumentsTo(mt.Target, typeArguments);
- } else {
- mt.TypeArguments.AddRange(typeArguments);
- }
- }
- }
-
- const string DynamicAttributeFullName = "System.Runtime.CompilerServices.DynamicAttribute";
-
- static bool HasDynamicAttribute(ICustomAttributeProvider attributeProvider, int typeIndex)
- {
- if (attributeProvider == null || !attributeProvider.HasCustomAttributes)
- return false;
- foreach (CustomAttribute a in attributeProvider.CustomAttributes) {
- if (a.Constructor.DeclaringType.FullName == DynamicAttributeFullName) {
- if (a.ConstructorArguments.Count == 1) {
- CustomAttributeArgument[] values = a.ConstructorArguments[0].Value as CustomAttributeArgument[];
- if (values != null && typeIndex < values.Length && values[typeIndex].Value is bool)
- return (bool)values[typeIndex].Value;
- }
- return true;
- }
- }
- return false;
- }
- #endregion
-
- #region ConvertModifiers
- Modifiers ConvertModifiers(TypeDefinition typeDef)
- {
- Modifiers modifiers = Modifiers.None;
- if (typeDef.IsNestedPrivate)
- modifiers |= Modifiers.Private;
- else if (typeDef.IsNestedAssembly || typeDef.IsNestedFamilyAndAssembly || typeDef.IsNotPublic)
- modifiers |= Modifiers.Internal;
- else if (typeDef.IsNestedFamily)
- modifiers |= Modifiers.Protected;
- else if (typeDef.IsNestedFamilyOrAssembly)
- modifiers |= Modifiers.Protected | Modifiers.Internal;
- else if (typeDef.IsPublic || typeDef.IsNestedPublic)
- modifiers |= Modifiers.Public;
-
- if (typeDef.IsAbstract && typeDef.IsSealed)
- modifiers |= Modifiers.Static;
- else if (typeDef.IsAbstract)
- modifiers |= Modifiers.Abstract;
- else if (typeDef.IsSealed)
- modifiers |= Modifiers.Sealed;
-
- return modifiers;
- }
-
- Modifiers ConvertModifiers(FieldDefinition fieldDef)
- {
- Modifiers modifiers = Modifiers.None;
- if (fieldDef.IsPrivate)
- modifiers |= Modifiers.Private;
- else if (fieldDef.IsAssembly || fieldDef.IsFamilyAndAssembly)
- modifiers |= Modifiers.Internal;
- else if (fieldDef.IsFamily)
- modifiers |= Modifiers.Protected;
- else if (fieldDef.IsFamilyOrAssembly)
- modifiers |= Modifiers.Protected | Modifiers.Internal;
- else if (fieldDef.IsPublic)
- modifiers |= Modifiers.Public;
-
- if (fieldDef.IsLiteral) {
- modifiers |= Modifiers.Const;
- } else {
- if (fieldDef.IsStatic)
- modifiers |= Modifiers.Static;
-
- if (fieldDef.IsInitOnly)
- modifiers |= Modifiers.Readonly;
- }
-
- RequiredModifierType modreq = fieldDef.FieldType as RequiredModifierType;
- if (modreq != null && modreq.ModifierType.FullName == typeof(IsVolatile).FullName)
- modifiers |= Modifiers.Volatile;
-
- return modifiers;
- }
-
- Modifiers ConvertModifiers(MethodDefinition methodDef)
- {
- if (methodDef == null)
- return Modifiers.None;
- Modifiers modifiers = Modifiers.None;
- if (methodDef.IsPrivate)
- modifiers |= Modifiers.Private;
- else if (methodDef.IsAssembly || methodDef.IsFamilyAndAssembly)
- modifiers |= Modifiers.Internal;
- else if (methodDef.IsFamily)
- modifiers |= Modifiers.Protected;
- else if (methodDef.IsFamilyOrAssembly)
- modifiers |= Modifiers.Protected | Modifiers.Internal;
- else if (methodDef.IsPublic)
- modifiers |= Modifiers.Public;
-
- if (methodDef.IsStatic)
- modifiers |= Modifiers.Static;
-
- if (methodDef.IsAbstract) {
- modifiers |= Modifiers.Abstract;
- if (!methodDef.IsNewSlot)
- modifiers |= Modifiers.Override;
- } else if (methodDef.IsFinal) {
- if (!methodDef.IsNewSlot) {
- modifiers |= Modifiers.Sealed | Modifiers.Override;
- }
- } else if (methodDef.IsVirtual) {
- if (methodDef.IsNewSlot)
- modifiers |= Modifiers.Virtual;
- else
- modifiers |= Modifiers.Override;
- }
- if (!methodDef.HasBody && !methodDef.IsAbstract)
- modifiers |= Modifiers.Extern;
-
- return modifiers;
- }
-
- #endregion
-
- void AddTypeMembers(TypeDeclaration astType, TypeDefinition typeDef)
- {
- // Nested types
- foreach (TypeDefinition nestedTypeDef in typeDef.NestedTypes) {
- if (MemberIsHidden(nestedTypeDef, context.Settings))
- continue;
- var nestedType = CreateType(nestedTypeDef);
- SetNewModifier(nestedType);
- astType.AddChild(nestedType, Roles.TypeMemberRole);
- }
-
- // Add fields
- foreach(FieldDefinition fieldDef in typeDef.Fields) {
- if (MemberIsHidden(fieldDef, context.Settings)) continue;
- astType.AddChild(CreateField(fieldDef), Roles.TypeMemberRole);
- }
-
- // Add events
- foreach(EventDefinition eventDef in typeDef.Events) {
- astType.AddChild(CreateEvent(eventDef), Roles.TypeMemberRole);
- }
-
- // Add properties
- foreach(PropertyDefinition propDef in typeDef.Properties) {
- astType.Members.Add(CreateProperty(propDef));
- }
-
- // Add methods
- foreach(MethodDefinition methodDef in typeDef.Methods) {
- if (MemberIsHidden(methodDef, context.Settings)) continue;
-
- if (methodDef.IsConstructor)
- astType.Members.Add(CreateConstructor(methodDef));
- else
- astType.Members.Add(CreateMethod(methodDef));
- }
- }
-
- EntityDeclaration CreateMethod(MethodDefinition methodDef)
- {
- MethodDeclaration astMethod = new MethodDeclaration();
- astMethod.AddAnnotation(methodDef);
- astMethod.ReturnType = ConvertType(methodDef.ReturnType, methodDef.MethodReturnType);
- astMethod.Name = CleanName(methodDef.Name);
- astMethod.TypeParameters.AddRange(MakeTypeParameters(methodDef.GenericParameters));
- astMethod.Parameters.AddRange(MakeParameters(methodDef));
- // constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly
- if (!methodDef.IsVirtual || (methodDef.IsNewSlot && !methodDef.IsPrivate)) astMethod.Constraints.AddRange(MakeConstraints(methodDef.GenericParameters));
- if (!methodDef.DeclaringType.IsInterface) {
- if (IsExplicitInterfaceImplementation(methodDef)) {
- astMethod.PrivateImplementationType = ConvertType(methodDef.Overrides.First().DeclaringType);
- } else {
- astMethod.Modifiers = ConvertModifiers(methodDef);
- if (methodDef.IsVirtual == methodDef.IsNewSlot)
- SetNewModifier(astMethod);
- }
- astMethod.Body = CreateMethodBody(methodDef, astMethod.Parameters);
- if (context.CurrentMethodIsAsync) {
- astMethod.Modifiers |= Modifiers.Async;
- context.CurrentMethodIsAsync = false;
- }
- }
- ConvertAttributes(astMethod, methodDef);
- if (methodDef.HasCustomAttributes && astMethod.Parameters.Count > 0) {
- foreach (CustomAttribute ca in methodDef.CustomAttributes) {
- if (ca.AttributeType.Name == "ExtensionAttribute" && ca.AttributeType.Namespace == "System.Runtime.CompilerServices") {
- astMethod.Parameters.First().ParameterModifier = ParameterModifier.This;
- }
- }
- }
-
- // Convert MethodDeclaration to OperatorDeclaration if possible
- if (methodDef.IsSpecialName && !methodDef.HasGenericParameters) {
- OperatorType? opType = OperatorDeclaration.GetOperatorType(methodDef.Name);
- if (opType.HasValue) {
- OperatorDeclaration op = new OperatorDeclaration();
- op.CopyAnnotationsFrom(astMethod);
- op.ReturnType = astMethod.ReturnType.Detach();
- op.OperatorType = opType.Value;
- op.Modifiers = astMethod.Modifiers;
- astMethod.Parameters.MoveTo(op.Parameters);
- astMethod.Attributes.MoveTo(op.Attributes);
- op.Body = astMethod.Body.Detach();
- return op;
- }
- }
- return astMethod;
- }
-
- bool IsExplicitInterfaceImplementation(MethodDefinition methodDef)
- {
- return methodDef.HasOverrides && methodDef.IsPrivate;
- }
-
- IEnumerable<TypeParameterDeclaration> MakeTypeParameters(IEnumerable<GenericParameter> genericParameters)
- {
- foreach (var gp in genericParameters) {
- TypeParameterDeclaration tp = new TypeParameterDeclaration();
- tp.Name = CleanName(gp.Name);
- if (gp.IsContravariant)
- tp.Variance = VarianceModifier.Contravariant;
- else if (gp.IsCovariant)
- tp.Variance = VarianceModifier.Covariant;
- ConvertCustomAttributes(tp, gp);
- yield return tp;
- }
- }
-
- IEnumerable<Constraint> MakeConstraints(IEnumerable<GenericParameter> genericParameters)
- {
- foreach (var gp in genericParameters) {
- Constraint c = new Constraint();
- c.TypeParameter = new SimpleType(CleanName(gp.Name));
- // class/struct must be first
- if (gp.HasReferenceTypeConstraint)
- c.BaseTypes.Add(new PrimitiveType("class"));
- if (gp.HasNotNullableValueTypeConstraint)
- c.BaseTypes.Add(new PrimitiveType("struct"));
-
- foreach (var constraintType in gp.Constraints) {
- if (gp.HasNotNullableValueTypeConstraint && constraintType.FullName == "System.ValueType")
- continue;
- c.BaseTypes.Add(ConvertType(constraintType));
- }
-
- if (gp.HasDefaultConstructorConstraint && !gp.HasNotNullableValueTypeConstraint)
- c.BaseTypes.Add(new PrimitiveType("new")); // new() must be last
- if (c.BaseTypes.Any())
- yield return c;
- }
- }
-
- ConstructorDeclaration CreateConstructor(MethodDefinition methodDef)
- {
- ConstructorDeclaration astMethod = new ConstructorDeclaration();
- astMethod.AddAnnotation(methodDef);
- astMethod.Modifiers = ConvertModifiers(methodDef);
- if (methodDef.IsStatic) {
- // don't show visibility for static ctors
- astMethod.Modifiers &= ~Modifiers.VisibilityMask;
- }
- astMethod.Name = CleanName(methodDef.DeclaringType.Name);
- astMethod.Parameters.AddRange(MakeParameters(methodDef));
- astMethod.Body = CreateMethodBody(methodDef, astMethod.Parameters);
- ConvertAttributes(astMethod, methodDef);
- if (methodDef.IsStatic && methodDef.DeclaringType.IsBeforeFieldInit && !astMethod.Body.IsNull) {
- astMethod.Body.InsertChildAfter(null, new Comment(" Note: this type is marked as 'beforefieldinit'."), Roles.Comment);
- }
- return astMethod;
- }
-
- Modifiers FixUpVisibility(Modifiers m)
- {
- Modifiers v = m & Modifiers.VisibilityMask;
- // If any of the modifiers is public, use that
- if ((v & Modifiers.Public) == Modifiers.Public)
- return Modifiers.Public | (m & ~Modifiers.VisibilityMask);
- // If both modifiers are private, no need to fix anything
- if (v == Modifiers.Private)
- return m;
- // Otherwise, use the other modifiers (internal and/or protected)
- return m & ~Modifiers.Private;
- }
-
- EntityDeclaration CreateProperty(PropertyDefinition propDef)
- {
- PropertyDeclaration astProp = new PropertyDeclaration();
- astProp.AddAnnotation(propDef);
- var accessor = propDef.GetMethod ?? propDef.SetMethod;
- Modifiers getterModifiers = Modifiers.None;
- Modifiers setterModifiers = Modifiers.None;
- if (IsExplicitInterfaceImplementation(accessor)) {
- astProp.PrivateImplementationType = ConvertType(accessor.Overrides.First().DeclaringType);
- } else if (!propDef.DeclaringType.IsInterface) {
- getterModifiers = ConvertModifiers(propDef.GetMethod);
- setterModifiers = ConvertModifiers(propDef.SetMethod);
- astProp.Modifiers = FixUpVisibility(getterModifiers | setterModifiers);
- try {
- if (accessor.IsVirtual && !accessor.IsNewSlot && (propDef.GetMethod == null || propDef.SetMethod == null)) {
- foreach (var basePropDef in TypesHierarchyHelpers.FindBaseProperties(propDef)) {
- if (basePropDef.GetMethod != null && basePropDef.SetMethod != null) {
- var propVisibilityModifiers = ConvertModifiers(basePropDef.GetMethod) | ConvertModifiers(basePropDef.SetMethod);
- astProp.Modifiers = FixUpVisibility((astProp.Modifiers & ~Modifiers.VisibilityMask) | (propVisibilityModifiers & Modifiers.VisibilityMask));
- break;
- } else if ((basePropDef.GetMethod ?? basePropDef.SetMethod).IsNewSlot) {
- break;
- }
- }
- }
- } catch (ReferenceResolvingException) {
- // TODO: add some kind of notification (a comment?) about possible problems with decompiled code due to unresolved references.
- }
- }
- astProp.Name = CleanName(propDef.Name);
- astProp.ReturnType = ConvertType(propDef.PropertyType, propDef);
-
- if (propDef.GetMethod != null) {
- astProp.Getter = new Accessor();
- astProp.Getter.Body = CreateMethodBody(propDef.GetMethod);
- astProp.Getter.AddAnnotation(propDef.GetMethod);
- ConvertAttributes(astProp.Getter, propDef.GetMethod);
-
- if ((getterModifiers & Modifiers.VisibilityMask) != (astProp.Modifiers & Modifiers.VisibilityMask))
- astProp.Getter.Modifiers = getterModifiers & Modifiers.VisibilityMask;
- }
- if (propDef.SetMethod != null) {
- astProp.Setter = new Accessor();
- astProp.Setter.Body = CreateMethodBody(propDef.SetMethod);
- astProp.Setter.AddAnnotation(propDef.SetMethod);
- ConvertAttributes(astProp.Setter, propDef.SetMethod);
- ParameterDefinition lastParam = propDef.SetMethod.Parameters.LastOrDefault();
- if (lastParam != null) {
- ConvertCustomAttributes(astProp.Setter, lastParam, "param");
- if (lastParam.HasMarshalInfo) {
- astProp.Setter.Attributes.Add(new AttributeSection(ConvertMarshalInfo(lastParam, propDef.Module)) { AttributeTarget = "param" });
- }
- }
-
- if ((setterModifiers & Modifiers.VisibilityMask) != (astProp.Modifiers & Modifiers.VisibilityMask))
- astProp.Setter.Modifiers = setterModifiers & Modifiers.VisibilityMask;
- }
- ConvertCustomAttributes(astProp, propDef);
-
- EntityDeclaration member = astProp;
- if(propDef.IsIndexer())
- member = ConvertPropertyToIndexer(astProp, propDef);
- if(!accessor.HasOverrides && !accessor.DeclaringType.IsInterface)
- if (accessor.IsVirtual == accessor.IsNewSlot)
- SetNewModifier(member);
- return member;
- }
-
- IndexerDeclaration ConvertPropertyToIndexer(PropertyDeclaration astProp, PropertyDefinition propDef)
- {
- var astIndexer = new IndexerDeclaration();
- astIndexer.CopyAnnotationsFrom(astProp);
- astProp.Attributes.MoveTo(astIndexer.Attributes);
- astIndexer.Modifiers = astProp.Modifiers;
- astIndexer.PrivateImplementationType = astProp.PrivateImplementationType.Detach();
- astIndexer.ReturnType = astProp.ReturnType.Detach();
- astIndexer.Getter = astProp.Getter.Detach();
- astIndexer.Setter = astProp.Setter.Detach();
- astIndexer.Parameters.AddRange(MakeParameters(propDef.Parameters));
- return astIndexer;
- }
-
- EntityDeclaration CreateEvent(EventDefinition eventDef)
- {
- if (eventDef.AddMethod != null && eventDef.AddMethod.IsAbstract) {
- // An abstract event cannot be custom
- EventDeclaration astEvent = new EventDeclaration();
- ConvertCustomAttributes(astEvent, eventDef);
- astEvent.AddAnnotation(eventDef);
- astEvent.Variables.Add(new VariableInitializer(CleanName(eventDef.Name)));
- astEvent.ReturnType = ConvertType(eventDef.EventType, eventDef);
- if (!eventDef.DeclaringType.IsInterface)
- astEvent.Modifiers = ConvertModifiers(eventDef.AddMethod);
- return astEvent;
- } else {
- CustomEventDeclaration astEvent = new CustomEventDeclaration();
- ConvertCustomAttributes(astEvent, eventDef);
- astEvent.AddAnnotation(eventDef);
- astEvent.Name = CleanName(eventDef.Name);
- astEvent.ReturnType = ConvertType(eventDef.EventType, eventDef);
- if (eventDef.AddMethod == null || !IsExplicitInterfaceImplementation(eventDef.AddMethod))
- astEvent.Modifiers = ConvertModifiers(eventDef.AddMethod);
- else
- astEvent.PrivateImplementationType = ConvertType(eventDef.AddMethod.Overrides.First().DeclaringType);
-
- if (eventDef.AddMethod != null) {
- astEvent.AddAccessor = new Accessor {
- Body = CreateMethodBody(eventDef.AddMethod)
- }.WithAnnotation(eventDef.AddMethod);
- ConvertAttributes(astEvent.AddAccessor, eventDef.AddMethod);
- }
- if (eventDef.RemoveMethod != null) {
- astEvent.RemoveAccessor = new Accessor {
- Body = CreateMethodBody(eventDef.RemoveMethod)
- }.WithAnnotation(eventDef.RemoveMethod);
- ConvertAttributes(astEvent.RemoveAccessor, eventDef.RemoveMethod);
- }
- MethodDefinition accessor = eventDef.AddMethod ?? eventDef.RemoveMethod;
- if (accessor.IsVirtual == accessor.IsNewSlot) {
- SetNewModifier(astEvent);
- }
- return astEvent;
- }
- }
-
- public bool DecompileMethodBodies { get; set; }
-
- BlockStatement CreateMethodBody(MethodDefinition method, IEnumerable<ParameterDeclaration> parameters = null)
- {
- if (DecompileMethodBodies)
- return AstMethodBodyBuilder.CreateMethodBody(method, context, parameters);
- else
- return null;
- }
-
- FieldDeclaration CreateField(FieldDefinition fieldDef)
- {
- FieldDeclaration astField = new FieldDeclaration();
- astField.AddAnnotation(fieldDef);
- VariableInitializer initializer = new VariableInitializer(CleanName(fieldDef.Name));
- astField.AddChild(initializer, Roles.Variable);
- astField.ReturnType = ConvertType(fieldDef.FieldType, fieldDef);
- astField.Modifiers = ConvertModifiers(fieldDef);
- if (fieldDef.HasConstant) {
- initializer.Initializer = CreateExpressionForConstant(fieldDef.Constant, fieldDef.FieldType, fieldDef.DeclaringType.IsEnum);
- }
- ConvertAttributes(astField, fieldDef);
- SetNewModifier(astField);
- return astField;
- }
-
- static Expression CreateExpressionForConstant(object constant, TypeReference type, bool isEnumMemberDeclaration = false)
- {
- if (constant == null) {
- if (type.IsValueType && !(type.Namespace == "System" && type.Name == "Nullable`1"))
- return new DefaultValueExpression(ConvertType(type));
- else
- return new NullReferenceExpression();
- } else {
- TypeCode c = Type.GetTypeCode(constant.GetType());
- if (c >= TypeCode.SByte && c <= TypeCode.UInt64 && !isEnumMemberDeclaration) {
- return MakePrimitive((long)CSharpPrimitiveCast.Cast(TypeCode.Int64, constant, false), type);
- } else {
- return new PrimitiveExpression(constant);
- }
- }
- }
-
- public static IEnumerable<ParameterDeclaration> MakeParameters(MethodDefinition method, bool isLambda = false)
- {
- var parameters = MakeParameters(method.Parameters, isLambda);
- if (method.CallingConvention == MethodCallingConvention.VarArg) {
- return parameters.Concat(new[] { new ParameterDeclaration { Type = new PrimitiveType("__arglist") } });
- } else {
- return parameters;
- }
- }
-
- public static IEnumerable<ParameterDeclaration> MakeParameters(IEnumerable<ParameterDefinition> paramCol, bool isLambda = false)
- {
- foreach(ParameterDefinition paramDef in paramCol) {
- ParameterDeclaration astParam = new ParameterDeclaration();
- astParam.AddAnnotation(paramDef);
- if (!(isLambda && paramDef.ParameterType.ContainsAnonymousType()))
- astParam.Type = ConvertType(paramDef.ParameterType, paramDef);
- astParam.Name = paramDef.Name;
-
- if (paramDef.ParameterType is ByReferenceType) {
- astParam.ParameterModifier = (!paramDef.IsIn && paramDef.IsOut) ? ParameterModifier.Out : ParameterModifier.Ref;
- ComposedType ct = astParam.Type as ComposedType;
- if (ct != null && ct.PointerRank > 0)
- ct.PointerRank--;
- }
-
- if (paramDef.HasCustomAttributes) {
- foreach (CustomAttribute ca in paramDef.CustomAttributes) {
- if (ca.AttributeType.Name == "ParamArrayAttribute" && ca.AttributeType.Namespace == "System")
- astParam.ParameterModifier = ParameterModifier.Params;
- }
- }
- if (paramDef.IsOptional) {
- astParam.DefaultExpression = CreateExpressionForConstant(paramDef.Constant, paramDef.ParameterType);
- }
-
- ConvertCustomAttributes(astParam, paramDef);
- ModuleDefinition module = ((MethodDefinition)paramDef.Method).Module;
- if (paramDef.HasMarshalInfo) {
- astParam.Attributes.Add(new AttributeSection(ConvertMarshalInfo(paramDef, module)));
- }
- if (astParam.ParameterModifier != ParameterModifier.Out) {
- if (paramDef.IsIn)
- astParam.Attributes.Add(new AttributeSection(CreateNonCustomAttribute(typeof(InAttribute), module)));
- if (paramDef.IsOut)
- astParam.Attributes.Add(new AttributeSection(CreateNonCustomAttribute(typeof(OutAttribute), module)));
- }
- yield return astParam;
- }
- }
-
- #region ConvertAttributes
- void ConvertAttributes(EntityDeclaration attributedNode, TypeDefinition typeDefinition)
- {
- ConvertCustomAttributes(attributedNode, typeDefinition);
- ConvertSecurityAttributes(attributedNode, typeDefinition);
-
- // Handle the non-custom attributes:
- #region SerializableAttribute
- if (typeDefinition.IsSerializable)
- attributedNode.Attributes.Add(new AttributeSection(CreateNonCustomAttribute(typeof(SerializableAttribute))));
- #endregion
-
- #region ComImportAttribute
- if (typeDefinition.IsImport)
- attributedNode.Attributes.Add(new AttributeSection(CreateNonCustomAttribute(typeof(ComImportAttribute))));
- #endregion
-
- #region StructLayoutAttribute
- LayoutKind layoutKind = LayoutKind.Auto;
- switch (typeDefinition.Attributes & TypeAttributes.LayoutMask) {
- case TypeAttributes.SequentialLayout:
- layoutKind = LayoutKind.Sequential;
- break;
- case TypeAttributes.ExplicitLayout:
- layoutKind = LayoutKind.Explicit;
- break;
- }
- CharSet charSet = CharSet.None;
- switch (typeDefinition.Attributes & TypeAttributes.StringFormatMask) {
- case TypeAttributes.AnsiClass:
- charSet = CharSet.Ansi;
- break;
- case TypeAttributes.AutoClass:
- charSet = CharSet.Auto;
- break;
- case TypeAttributes.UnicodeClass:
- charSet = CharSet.Unicode;
- break;
- }
- LayoutKind defaultLayoutKind = (typeDefinition.IsValueType && !typeDefinition.IsEnum) ? LayoutKind.Sequential: LayoutKind.Auto;
- if (layoutKind != defaultLayoutKind || charSet != CharSet.Ansi || typeDefinition.PackingSize > 0 || typeDefinition.ClassSize > 0) {
- var structLayout = CreateNonCustomAttribute(typeof(StructLayoutAttribute));
- structLayout.Arguments.Add(new IdentifierExpression("LayoutKind").Member(layoutKind.ToString()));
- if (charSet != CharSet.Ansi) {
- structLayout.AddNamedArgument("CharSet", new IdentifierExpression("CharSet").Member(charSet.ToString()));
- }
- if (typeDefinition.PackingSize > 0) {
- structLayout.AddNamedArgument("Pack", new PrimitiveExpression((int)typeDefinition.PackingSize));
- }
- if (typeDefinition.ClassSize > 0) {
- structLayout.AddNamedArgument("Size", new PrimitiveExpression((int)typeDefinition.ClassSize));
- }
- attributedNode.Attributes.Add(new AttributeSection(structLayout));
- }
- #endregion
- }
-
- void ConvertAttributes(EntityDeclaration attributedNode, MethodDefinition methodDefinition)
- {
- ConvertCustomAttributes(attributedNode, methodDefinition);
- ConvertSecurityAttributes(attributedNode, methodDefinition);
-
- MethodImplAttributes implAttributes = methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask;
-
- #region DllImportAttribute
- if (methodDefinition.HasPInvokeInfo && methodDefinition.PInvokeInfo != null) {
- PInvokeInfo info = methodDefinition.PInvokeInfo;
- Ast.Attribute dllImport = CreateNonCustomAttribute(typeof(DllImportAttribute));
- dllImport.Arguments.Add(new PrimitiveExpression(info.Module.Name));
-
- if (info.IsBestFitDisabled)
- dllImport.AddNamedArgument("BestFitMapping", new PrimitiveExpression(false));
- if (info.IsBestFitEnabled)
- dllImport.AddNamedArgument("BestFitMapping", new PrimitiveExpression(true));
-
- CallingConvention callingConvention;
- switch (info.Attributes & PInvokeAttributes.CallConvMask) {
- case PInvokeAttributes.CallConvCdecl:
- callingConvention = CallingConvention.Cdecl;
- break;
- case PInvokeAttributes.CallConvFastcall:
- callingConvention = CallingConvention.FastCall;
- break;
- case PInvokeAttributes.CallConvStdCall:
- callingConvention = CallingConvention.StdCall;
- break;
- case PInvokeAttributes.CallConvThiscall:
- callingConvention = CallingConvention.ThisCall;
- break;
- case PInvokeAttributes.CallConvWinapi:
- callingConvention = CallingConvention.Winapi;
- break;
- default:
- throw new NotSupportedException("unknown calling convention");
- }
- if (callingConvention != CallingConvention.Winapi)
- dllImport.AddNamedArgument("CallingConvention", new IdentifierExpression("CallingConvention").Member(callingConvention.ToString()));
-
- CharSet charSet = CharSet.None;
- switch (info.Attributes & PInvokeAttributes.CharSetMask) {
- case PInvokeAttributes.CharSetAnsi:
- charSet = CharSet.Ansi;
- break;
- case PInvokeAttributes.CharSetAuto:
- charSet = CharSet.Auto;
- break;
- case PInvokeAttributes.CharSetUnicode:
- charSet = CharSet.Unicode;
- break;
- }
- if (charSet != CharSet.None)
- dllImport.AddNamedArgument("CharSet", new IdentifierExpression("CharSet").Member(charSet.ToString()));
-
- if (!string.IsNullOrEmpty(info.EntryPoint) && info.EntryPoint != methodDefinition.Name)
- dllImport.AddNamedArgument("EntryPoint", new PrimitiveExpression(info.EntryPoint));
-
- if (info.IsNoMangle)
- dllImport.AddNamedArgument("ExactSpelling", new PrimitiveExpression(true));
-
- if ((implAttributes & MethodImplAttributes.PreserveSig) == MethodImplAttributes.PreserveSig)
- implAttributes &= ~MethodImplAttributes.PreserveSig;
- else
- dllImport.AddNamedArgument("PreserveSig", new PrimitiveExpression(false));
-
- if (info.SupportsLastError)
- dllImport.AddNamedArgument("SetLastError", new PrimitiveExpression(true));
-
- if (info.IsThrowOnUnmappableCharDisabled)
- dllImport.AddNamedArgument("ThrowOnUnmappableChar", new PrimitiveExpression(false));
- if (info.IsThrowOnUnmappableCharEnabled)
- dllImport.AddNamedArgument("ThrowOnUnmappableChar", new PrimitiveExpression(true));
-
- attributedNode.Attributes.Add(new AttributeSection(dllImport));
- }
- #endregion
-
- #region PreserveSigAttribute
- if (implAttributes == MethodImplAttributes.PreserveSig) {
- attributedNode.Attributes.Add(new AttributeSection(CreateNonCustomAttribute(typeof(PreserveSigAttribute))));
- implAttributes = 0;
- }
- #endregion
-
- #region MethodImplAttribute
- if (implAttributes != 0) {
- Ast.Attribute methodImpl = CreateNonCustomAttribute(typeof(MethodImplAttribute));
- TypeReference methodImplOptions = new TypeReference(
- "System.Runtime.CompilerServices", "MethodImplOptions",
- methodDefinition.Module, methodDefinition.Module.TypeSystem.Corlib);
- methodImpl.Arguments.Add(MakePrimitive((long)implAttributes, methodImplOptions));
- attributedNode.Attributes.Add(new AttributeSection(methodImpl));
- }
- #endregion
-
- ConvertAttributes(attributedNode, methodDefinition.MethodReturnType, methodDefinition.Module);
- }
-
- void ConvertAttributes(EntityDeclaration attributedNode, MethodReturnType methodReturnType, ModuleDefinition module)
- {
- ConvertCustomAttributes(attributedNode, methodReturnType, "return");
- if (methodReturnType.HasMarshalInfo) {
- var marshalInfo = ConvertMarshalInfo(methodReturnType, module);
- attributedNode.Attributes.Add(new AttributeSection(marshalInfo) { AttributeTarget = "return" });
- }
- }
-
- internal static void ConvertAttributes(EntityDeclaration attributedNode, FieldDefinition fieldDefinition, string attributeTarget = null)
- {
- ConvertCustomAttributes(attributedNode, fieldDefinition);
-
- #region FieldOffsetAttribute
- if (fieldDefinition.HasLayoutInfo) {
- Ast.Attribute fieldOffset = CreateNonCustomAttribute(typeof(FieldOffsetAttribute), fieldDefinition.Module);
- fieldOffset.Arguments.Add(new PrimitiveExpression(fieldDefinition.Offset));
- attributedNode.Attributes.Add(new AttributeSection(fieldOffset) { AttributeTarget = attributeTarget });
- }
- #endregion
-
- #region NonSerializedAttribute
- if (fieldDefinition.IsNotSerialized) {
- Ast.Attribute nonSerialized = CreateNonCustomAttribute(typeof(NonSerializedAttribute), fieldDefinition.Module);
- attributedNode.Attributes.Add(new AttributeSection(nonSerialized) { AttributeTarget = attributeTarget });
- }
- #endregion
-
- if (fieldDefinition.HasMarshalInfo) {
- attributedNode.Attributes.Add(new AttributeSection(ConvertMarshalInfo(fieldDefinition, fieldDefinition.Module)) { AttributeTarget = attributeTarget });
- }
- }
-
- #region MarshalAsAttribute (ConvertMarshalInfo)
- static Ast.Attribute ConvertMarshalInfo(IMarshalInfoProvider marshalInfoProvider, ModuleDefinition module)
- {
- MarshalInfo marshalInfo = marshalInfoProvider.MarshalInfo;
- Ast.Attribute attr = CreateNonCustomAttribute(typeof(MarshalAsAttribute), module);
- var unmanagedType = new TypeReference("System.Runtime.InteropServices", "UnmanagedType", module, module.TypeSystem.Corlib);
- attr.Arguments.Add(MakePrimitive((int)marshalInfo.NativeType, unmanagedType));
-
- FixedArrayMarshalInfo fami = marshalInfo as FixedArrayMarshalInfo;
- if (fami != null) {
- attr.AddNamedArgument("SizeConst", new PrimitiveExpression(fami.Size));
- if (fami.ElementType != NativeType.None)
- attr.AddNamedArgument("ArraySubType", MakePrimitive((int)fami.ElementType, unmanagedType));
- }
- SafeArrayMarshalInfo sami = marshalInfo as SafeArrayMarshalInfo;
- if (sami != null && sami.ElementType != VariantType.None) {
- var varEnum = new TypeReference("System.Runtime.InteropServices", "VarEnum", module, module.TypeSystem.Corlib);
- attr.AddNamedArgument("SafeArraySubType", MakePrimitive((int)sami.ElementType, varEnum));
- }
- ArrayMarshalInfo ami = marshalInfo as ArrayMarshalInfo;
- if (ami != null) {
- if (ami.ElementType != NativeType.Max)
- attr.AddNamedArgument("ArraySubType", MakePrimitive((int)ami.ElementType, unmanagedType));
- if (ami.Size >= 0)
- attr.AddNamedArgument("SizeConst", new PrimitiveExpression(ami.Size));
- if (ami.SizeParameterMultiplier != 0 && ami.SizeParameterIndex >= 0)
- attr.AddNamedArgument("SizeParamIndex", new PrimitiveExpression(ami.SizeParameterIndex));
- }
- CustomMarshalInfo cmi = marshalInfo as CustomMarshalInfo;
- if (cmi != null) {
- attr.AddNamedArgument("MarshalType", new PrimitiveExpression(cmi.ManagedType.FullName));
- if (!string.IsNullOrEmpty(cmi.Cookie))
- attr.AddNamedArgument("MarshalCookie", new PrimitiveExpression(cmi.Cookie));
- }
- FixedSysStringMarshalInfo fssmi = marshalInfo as FixedSysStringMarshalInfo;
- if (fssmi != null) {
- attr.AddNamedArgument("SizeConst", new PrimitiveExpression(fssmi.Size));
- }
- return attr;
- }
- #endregion
-
- Ast.Attribute CreateNonCustomAttribute(Type attributeType)
- {
- return CreateNonCustomAttribute(attributeType, context.CurrentType != null ? context.CurrentType.Module : null);
- }
-
- static Ast.Attribute CreateNonCustomAttribute(Type attributeType, ModuleDefinition module)
- {
- Debug.Assert(attributeType.Name.EndsWith("Attribute", StringComparison.Ordinal));
- Ast.Attribute attr = new Ast.Attribute();
- attr.Type = new SimpleType(attributeType.Name.Substring(0, attributeType.Name.Length - "Attribute".Length));
- if (module != null) {
- attr.Type.AddAnnotation(new TypeReference(attributeType.Namespace, attributeType.Name, module, module.TypeSystem.Corlib));
- }
- return attr;
- }
-
- static void ConvertCustomAttributes(AstNode attributedNode, ICustomAttributeProvider customAttributeProvider, string attributeTarget = null)
- {
- EntityDeclaration entityDecl = attributedNode as EntityDeclaration;
- if (customAttributeProvider.HasCustomAttributes) {
- var attributes = new List<NRefactory.CSharp.Attribute>();
- foreach (var customAttribute in customAttributeProvider.CustomAttributes.OrderBy(a => a.AttributeType.FullName)) {
- if (customAttribute.AttributeType.Name == "ExtensionAttribute" && customAttribute.AttributeType.Namespace == "System.Runtime.CompilerServices") {
- // don't show the ExtensionAttribute (it's converted to the 'this' modifier)
- continue;
- }
- if (customAttribute.AttributeType.Name == "ParamArrayAttribute" && customAttribute.AttributeType.Namespace == "System") {
- // don't show the ParamArrayAttribute (it's converted to the 'params' modifier)
- continue;
- }
- // if the method is async, remove [DebuggerStepThrough] and [Async
- if (entityDecl != null && entityDecl.HasModifier(Modifiers.Async)) {
- if (customAttribute.AttributeType.Name == "DebuggerStepThroughAttribute" && customAttribute.AttributeType.Namespace == "System.Diagnostics") {
- continue;
- }
- if (customAttribute.AttributeType.Name == "AsyncStateMachineAttribute" && customAttribute.AttributeType.Namespace == "System.Runtime.CompilerServices") {
- continue;
- }
- }
-
- var attribute = new NRefactory.CSharp.Attribute();
- attribute.AddAnnotation(customAttribute);
- attribute.Type = ConvertType(customAttribute.AttributeType);
- attributes.Add(attribute);
-
- SimpleType st = attribute.Type as SimpleType;
- if (st != null && st.Identifier.EndsWith("Attribute", StringComparison.Ordinal)) {
- st.Identifier = st.Identifier.Substring(0, st.Identifier.Length - "Attribute".Length);
- }
-
- if(customAttribute.HasConstructorArguments) {
- foreach (var parameter in customAttribute.ConstructorArguments) {
- Expression parameterValue = ConvertArgumentValue(parameter);
- attribute.Arguments.Add(parameterValue);
- }
- }
- if (customAttribute.HasProperties) {
- TypeDefinition resolvedAttributeType = customAttribute.AttributeType.Resolve();
- foreach (var propertyNamedArg in customAttribute.Properties) {
- var propertyReference = resolvedAttributeType != null ? resolvedAttributeType.Properties.FirstOrDefault(pr => pr.Name == propertyNamedArg.Name) : null;
- var propertyName = new IdentifierExpression(propertyNamedArg.Name).WithAnnotation(propertyReference);
- var argumentValue = ConvertArgumentValue(propertyNamedArg.Argument);
- attribute.Arguments.Add(new AssignmentExpression(propertyName, argumentValue));
- }
- }
-
- if (customAttribute.HasFields) {
- TypeDefinition resolvedAttributeType = customAttribute.AttributeType.Resolve();
- foreach (var fieldNamedArg in customAttribute.Fields) {
- var fieldReference = resolvedAttributeType != null ? resolvedAttributeType.Fields.FirstOrDefault(f => f.Name == fieldNamedArg.Name) : null;
- var fieldName = new IdentifierExpression(fieldNamedArg.Name).WithAnnotation(fieldReference);
- var argumentValue = ConvertArgumentValue(fieldNamedArg.Argument);
- attribute.Arguments.Add(new AssignmentExpression(fieldName, argumentValue));
- }
- }
- }
-
- if (attributeTarget == "module" || attributeTarget == "assembly") {
- // use separate section for each attribute
- foreach (var attribute in attributes) {
- var section = new AttributeSection();
- section.AttributeTarget = attributeTarget;
- section.Attributes.Add(attribute);
- attributedNode.AddChild(section, EntityDeclaration.AttributeRole);
- }
- } else if (attributes.Count > 0) {
- // use single section for all attributes
- var section = new AttributeSection();
- section.AttributeTarget = attributeTarget;
- section.Attributes.AddRange(attributes);
- attributedNode.AddChild(section, EntityDeclaration.AttributeRole);
- }
- }
- }
-
- static void ConvertSecurityAttributes(AstNode attributedNode, ISecurityDeclarationProvider secDeclProvider, string attributeTarget = null)
- {
- if (!secDeclProvider.HasSecurityDeclarations)
- return;
- var attributes = new List<NRefactory.CSharp.Attribute>();
- foreach (var secDecl in secDeclProvider.SecurityDeclarations.OrderBy(d => d.Action)) {
- foreach (var secAttribute in secDecl.SecurityAttributes.OrderBy(a => a.AttributeType.FullName)) {
- var attribute = new NRefactory.CSharp.Attribute();
- attribute.AddAnnotation(secAttribute);
- attribute.Type = ConvertType(secAttribute.AttributeType);
- attributes.Add(attribute);
-
- SimpleType st = attribute.Type as SimpleType;
- if (st != null && st.Identifier.EndsWith("Attribute", StringComparison.Ordinal)) {
- st.Identifier = st.Identifier.Substring(0, st.Identifier.Length - "Attribute".Length);
- }
-
- var module = secAttribute.AttributeType.Module;
- var securityActionType = new TypeReference("System.Security.Permissions", "SecurityAction", module, module.TypeSystem.Corlib);
- attribute.Arguments.Add(MakePrimitive((int)secDecl.Action, securityActionType));
-
- if (secAttribute.HasProperties) {
- TypeDefinition resolvedAttributeType = secAttribute.AttributeType.Resolve();
- foreach (var propertyNamedArg in secAttribute.Properties) {
- var propertyReference = resolvedAttributeType != null ? resolvedAttributeType.Properties.FirstOrDefault(pr => pr.Name == propertyNamedArg.Name) : null;
- var propertyName = new IdentifierExpression(propertyNamedArg.Name).WithAnnotation(propertyReference);
- var argumentValue = ConvertArgumentValue(propertyNamedArg.Argument);
- attribute.Arguments.Add(new AssignmentExpression(propertyName, argumentValue));
- }
- }
-
- if (secAttribute.HasFields) {
- TypeDefinition resolvedAttributeType = secAttribute.AttributeType.Resolve();
- foreach (var fieldNamedArg in secAttribute.Fields) {
- var fieldReference = resolvedAttributeType != null ? resolvedAttributeType.Fields.FirstOrDefault(f => f.Name == fieldNamedArg.Name) : null;
- var fieldName = new IdentifierExpression(fieldNamedArg.Name).WithAnnotation(fieldReference);
- var argumentValue = ConvertArgumentValue(fieldNamedArg.Argument);
- attribute.Arguments.Add(new AssignmentExpression(fieldName, argumentValue));
- }
- }
- }
- }
- if (attributeTarget == "module" || attributeTarget == "assembly") {
- // use separate section for each attribute
- foreach (var attribute in attributes) {
- var section = new AttributeSection();
- section.AttributeTarget = attributeTarget;
- section.Attributes.Add(attribute);
- attributedNode.AddChild(section, EntityDeclaration.AttributeRole);
- }
- } else if (attributes.Count > 0) {
- // use single section for all attributes
- var section = new AttributeSection();
- section.AttributeTarget = attributeTarget;
- section.Attributes.AddRange(attributes);
- attributedNode.AddChild(section, EntityDeclaration.AttributeRole);
- }
- }
-
- static Expression ConvertArgumentValue(CustomAttributeArgument argument)
- {
- if (argument.Value is CustomAttributeArgument[]) {
- ArrayInitializerExpression arrayInit = new ArrayInitializerExpression();
- foreach (CustomAttributeArgument element in (CustomAttributeArgument[])argument.Value) {
- arrayInit.Elements.Add(ConvertArgumentValue(element));
- }
- ArrayType arrayType = argument.Type as ArrayType;
- return new ArrayCreateExpression {
- Type = ConvertType(arrayType != null ? arrayType.ElementType : argument.Type),
- AdditionalArraySpecifiers = { new ArraySpecifier() },
- Initializer = arrayInit
- };
- } else if (argument.Value is CustomAttributeArgument) {
- // occurs with boxed arguments
- return ConvertArgumentValue((CustomAttributeArgument)argument.Value);
- }
- var type = argument.Type.Resolve();
- if (type != null && type.IsEnum) {
- return MakePrimitive(Convert.ToInt64(argument.Value), type);
- } else if (argument.Value is TypeReference) {
- return CreateTypeOfExpression((TypeReference)argument.Value);
- } else {
- return new PrimitiveExpression(argument.Value);
- }
- }
- #endregion
-
- internal static Expression MakePrimitive(long val, TypeReference type)
- {
- if (TypeAnalysis.IsBoolean(type) && val == 0)
- return new PrimitiveExpression(false);
- else if (TypeAnalysis.IsBoolean(type) && val == 1)
- return new PrimitiveExpression(true);
- else if (val == 0 && type is PointerType)
- return new NullReferenceExpression();
- if (type != null)
- { // cannot rely on type.IsValueType, it's not set for typerefs (but is set for typespecs)
- TypeDefinition enumDefinition = type.Resolve();
- if (enumDefinition != null && enumDefinition.IsEnum) {
- TypeCode enumBaseTypeCode = TypeCode.Int32;
- foreach (FieldDefinition field in enumDefinition.Fields) {
- if (field.IsStatic && Equals(CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false), val))
- return ConvertType(type).Member(field.Name).WithAnnotation(field);
- else if (!field.IsStatic)
- enumBaseTypeCode = TypeAnalysis.GetTypeCode(field.FieldType); // use primitive type of the enum
- }
- if (IsFlagsEnum(enumDefinition)) {
- long enumValue = val;
- Expression expr = null;
- long negatedEnumValue = ~val;
- // limit negatedEnumValue to the appropriate range
- switch (enumBaseTypeCode) {
- case TypeCode.Byte:
- case TypeCode.SByte:
- negatedEnumValue &= byte.MaxValue;
- break;
- case TypeCode.Int16:
- case TypeCode.UInt16:
- negatedEnumValue &= ushort.MaxValue;
- break;
- case TypeCode.Int32:
- case TypeCode.UInt32:
- negatedEnumValue &= uint.MaxValue;
- break;
- }
- Expression negatedExpr = null;
- foreach (FieldDefinition field in enumDefinition.Fields.Where(fld => fld.IsStatic)) {
- long fieldValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.Constant, false);
- if (fieldValue == 0)
- continue; // skip None enum value
-
- if ((fieldValue & enumValue) == fieldValue) {
- var fieldExpression = ConvertType(type).Member(field.Name).WithAnnotation(field);
- if (expr == null)
- expr = fieldExpression;
- else
- expr = new BinaryOperatorExpression(expr, BinaryOperatorType.BitwiseOr, fieldExpression);
-
- enumValue &= ~fieldValue;
- }
- if ((fieldValue & negatedEnumValue) == fieldValue) {
- var fieldExpression = ConvertType(type).Member(field.Name).WithAnnotation(field);
- if (negatedExpr == null)
- negatedExpr = fieldExpression;
- else
- negatedExpr = new BinaryOperatorExpression(negatedExpr, BinaryOperatorType.BitwiseOr, fieldExpression);
-
- negatedEnumValue &= ~fieldValue;
- }
- }
- if (enumValue == 0 && expr != null) {
- if (!(negatedEnumValue == 0 && negatedExpr != null && negatedExpr.Descendants.Count() < expr.Descendants.Count())) {
- return expr;
- }
- }
- if (negatedEnumValue == 0 && negatedExpr != null) {
- return new UnaryOperatorExpression(UnaryOperatorType.BitNot, negatedExpr);
- }
- }
- return new PrimitiveExpression(CSharpPrimitiveCast.Cast(enumBaseTypeCode, val, false)).CastTo(ConvertType(type));
- }
- }
- TypeCode code = TypeAnalysis.GetTypeCode(type);
- if (code == TypeCode.Object || code == TypeCode.Empty)
- code = TypeCode.Int32;
- return new PrimitiveExpression(CSharpPrimitiveCast.Cast(code, val, false));
- }
-
- static bool IsFlagsEnum(TypeDefinition type)
- {
- if (!type.HasCustomAttributes)
- return false;
-
- return type.CustomAttributes.Any(attr => attr.AttributeType.FullName == "System.FlagsAttribute");
- }
-
- /// <summary>
- /// Sets new modifier if the member hides some other member from a base type.
- /// </summary>
- /// <param name="member">The node of the member which new modifier state should be determined.</param>
- static void SetNewModifier(EntityDeclaration member)
- {
- try {
- bool addNewModifier = false;
- if (member is IndexerDeclaration) {
- var propertyDef = member.Annotation<PropertyDefinition>();
- var baseProperties =
- TypesHierarchyHelpers.FindBaseProperties(propertyDef);
- addNewModifier = baseProperties.Any();
- } else
- addNewModifier = HidesBaseMember(member);
-
- if (addNewModifier)
- member.Modifiers |= Modifiers.New;
- }
- catch (ReferenceResolvingException) {
- // TODO: add some kind of notification (a comment?) about possible problems with decompiled code due to unresolved references.
- }
- }
-
- static bool HidesBaseMember(EntityDeclaration member)
- {
- var memberDefinition = member.Annotation<IMemberDefinition>();
- bool addNewModifier = false;
- var methodDefinition = memberDefinition as MethodDefinition;
- if (methodDefinition != null) {
- addNewModifier = HidesByName(memberDefinition, includeBaseMethods: false);
- if (!addNewModifier)
- addNewModifier = TypesHierarchyHelpers.FindBaseMethods(methodDefinition).Any();
- } else
- addNewModifier = HidesByName(memberDefinition, includeBaseMethods: true);
- return addNewModifier;
- }
-
- /// <summary>
- /// Determines whether any base class member has the same name as the given member.
- /// </summary>
- /// <param name="member">The derived type's member.</param>
- /// <param name="includeBaseMethods">true if names of methods declared in base types should also be checked.</param>
- /// <returns>true if any base member has the same name as given member, otherwise false.</returns>
- static bool HidesByName(IMemberDefinition member, bool includeBaseMethods)
- {
- Debug.Assert(!(member is PropertyDefinition) || !((PropertyDefinition)member).IsIndexer());
-
- if (member.DeclaringType.BaseType != null) {
- var baseTypeRef = member.DeclaringType.BaseType;
- while (baseTypeRef != null) {
-#pragma warning disable 618
- var baseType = baseTypeRef.ResolveOrThrow();
-#pragma warning restore 618
- if (baseType.HasProperties && AnyIsHiddenBy(baseType.Properties, member, m => !m.IsIndexer()))
- return true;
- if (baseType.HasEvents && AnyIsHiddenBy(baseType.Events, member))
- return true;
- if (baseType.HasFields && AnyIsHiddenBy(baseType.Fields, member))
- return true;
- if (includeBaseMethods && baseType.HasMethods
- && AnyIsHiddenBy(baseType.Methods, member, m => !m.IsSpecialName))
- return true;
- if (baseType.HasNestedTypes && AnyIsHiddenBy(baseType.NestedTypes, member))
- return true;
- baseTypeRef = baseType.BaseType;
- }
- }
- return false;
- }
-
- static bool AnyIsHiddenBy<T>(IEnumerable<T> members, IMemberDefinition derived, Predicate<T> condition = null)
- where T : IMemberDefinition
- {
- return members.Any(m => m.Name == derived.Name
- && (condition == null || condition(m))
- && TypesHierarchyHelpers.IsVisibleFromDerived(m, derived.DeclaringType));
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
deleted file mode 100644
index a4d80e59..00000000
--- a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
+++ /dev/null
@@ -1,1220 +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 = NRefactory.CSharp;
- using Cecil = Mono.Cecil;
-
- public class AstMethodBodyBuilder
- {
- MethodDefinition methodDef;
- TypeSystem typeSystem;
- DecompilerContext context;
- HashSet<ILVariable> localVariablesToDefine = new HashSet<ILVariable>(); // local variables that are missing a definition
-
- /// <summary>
- /// Creates the body for the method definition.
- /// </summary>
- /// <param name="methodDef">Method definition to decompile.</param>
- /// <param name="context">Decompilation context.</param>
- /// <param name="parameters">Parameter declarations of the method being decompiled.
- /// These are used to update the parameter names when the decompiler generates names for the parameters.</param>
- /// <returns>Block for the method body</returns>
- public static BlockStatement CreateMethodBody(MethodDefinition methodDef,
- DecompilerContext context,
- IEnumerable<ParameterDeclaration> 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 DecompilerException(methodDef, ex);
- }
- }
- } finally {
- context.CurrentMethod = oldCurrentMethod;
- }
- }
-
- public BlockStatement CreateMethodBody(IEnumerable<ParameterDeclaration> 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<ILExpression>().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<ParameterDefinition>() equals v.OriginalParameter
- select new { p, v.Name }))
- {
- pair.p.Name = pair.Name;
- }
- }
-
- context.CancellationToken.ThrowIfCancellationRequested();
- 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;
- }
-
- BlockStatement TransformBlock(ILBlock block)
- {
- BlockStatement astBlock = new BlockStatement();
- if (block != null) {
- foreach(ILNode node in block.GetChildren()) {
- astBlock.Statements.AddRange(TransformNode(node));
- }
- }
- return astBlock;
- }
-
- IEnumerable<Statement> TransformNode(ILNode node)
- {
- if (node is ILLabel) {
- yield return new LabelStatement { Label = ((ILLabel)node).Name };
- } else if (node is ILExpression) {
- List<ILRange> ilRanges = ILRange.OrderAndJoin(node.GetSelfAndChildrenRecursive<ILExpression>().SelectMany(e => e.ILRanges));
- AstNode codeExpr = TransformExpression((ILExpression)node);
- if (codeExpr != null) {
- codeExpr = codeExpr.WithAnnotation(ilRanges);
- if (codeExpr is Expression) {
- yield return new ExpressionStatement { Expression = (Expression)codeExpr };
- } else if (codeExpr is Statement) {
- yield return (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 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 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 CatchClause { Body = TransformBlock(catchClause) });
- } else {
- tryCatchStmt.CatchClauses.Add(
- new 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<ILRange> ilRanges = ILRange.OrderAndJoin(expr.GetSelfAndChildrenRecursive<ILExpression>().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 TypeReference);
-
- List<Expression> args = new List<Expression>();
- foreach(ILExpression arg in byteCode.Arguments) {
- args.Add((Expression)TransformExpression(arg));
- }
- Expression arg1 = args.Count >= 1 ? args[0] : null;
- Expression arg2 = args.Count >= 2 ? args[1] : null;
- 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 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 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 BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
- if (byteCode.Arguments[0].ExpectedType is PointerType) {
- boe.WithAnnotation(IntroduceUnsafeModifier.PointerArithmeticAnnotation);
- }
- } else {
- boe = new BinaryOperatorExpression(arg1, BinaryOperatorType.Subtract, arg2);
- }
- boe.AddAnnotation(byteCode.Code == ILCode.Sub ? AddCheckedBlocks.UncheckedAnnotation : AddCheckedBlocks.CheckedAnnotation);
- return boe;
- }
- case ILCode.Div: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2);
- case ILCode.Div_Un: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Divide, arg2);
- case ILCode.Mul: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2).WithAnnotation(AddCheckedBlocks.UncheckedAnnotation);
- case ILCode.Mul_Ovf: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2).WithAnnotation(AddCheckedBlocks.CheckedAnnotation);
- case ILCode.Mul_Ovf_Un: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Multiply, arg2).WithAnnotation(AddCheckedBlocks.CheckedAnnotation);
- case ILCode.Rem: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2);
- case ILCode.Rem_Un: return new BinaryOperatorExpression(arg1, BinaryOperatorType.Modulus, arg2);
- case ILCode.And: return new BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseAnd, arg2);
- case ILCode.Or: return new BinaryOperatorExpression(arg1, BinaryOperatorType.BitwiseOr, arg2);
- case ILCode.Xor: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ExclusiveOr, arg2);
- case ILCode.Shl: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftLeft, arg2);
- case ILCode.Shr: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2);
- case ILCode.Shr_Un: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ShiftRight, arg2);
- case ILCode.Neg: return new UnaryOperatorExpression(UnaryOperatorType.Minus, arg1).WithAnnotation(AddCheckedBlocks.UncheckedAnnotation);
- case ILCode.Not: return new 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 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 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 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<Expression>();
- 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 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 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 BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2);
- case ILCode.Cne: return new BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2);
- case ILCode.Cgt: return new 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 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 PrimitiveExpression;
- if (p != null && p.Value.IsZero()) goto case ILCode.Ceq;
- }
-
- goto case ILCode.Cle;
- }
- case ILCode.Cle: return new BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2);
- case ILCode.Cge_Un:
- case ILCode.Cge: return new BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2);
- case ILCode.Clt_Un:
- case ILCode.Clt: return new BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2);
- #endregion
- #region Logical
- case ILCode.LogicNot: return new UnaryOperatorExpression(UnaryOperatorType.Not, arg1);
- case ILCode.LogicAnd: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ConditionalAnd, arg2);
- case ILCode.LogicOr: return new BinaryOperatorExpression(arg1, BinaryOperatorType.ConditionalOr, arg2);
- case ILCode.TernaryOp: return new ConditionalExpression() { Condition = arg1, TrueExpression = arg2, FalseExpression = arg3 };
- case ILCode.NullCoalescing: return new BinaryOperatorExpression(arg1, BinaryOperatorType.NullCoalescing, arg2);
- #endregion
- #region Branch
- case ILCode.Br: return new GotoStatement(((ILLabel)byteCode.Operand).Name);
- case ILCode.Brtrue:
- return new IfElseStatement() {
- Condition = arg1,
- TrueStatement = new BlockStatement() {
- new GotoStatement(((ILLabel)byteCode.Operand).Name)
- }
- };
- case ILCode.LoopOrSwitchBreak: return new BreakStatement();
- case ILCode.LoopContinue: return new 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) || ((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: {
- MethodReference cecilMethod = ((MethodReference)operand);
- var expr = new IdentifierExpression(cecilMethod.Name);
- expr.TypeArguments.AddRange(ConvertTypeArguments(cecilMethod));
- expr.AddAnnotation(cecilMethod);
- return new IdentifierExpression("ldftn").Invoke(expr)
- .WithAnnotation(new DelegateConstruction.Annotation(false));
- }
- case ILCode.Ldvirtftn: {
- MethodReference cecilMethod = ((MethodReference)operand);
- var expr = new IdentifierExpression(cecilMethod.Name);
- expr.TypeArguments.AddRange(ConvertTypeArguments(cecilMethod));
- expr.AddAnnotation(cecilMethod);
- return new IdentifierExpression("ldvirtftn").Invoke(expr)
- .WithAnnotation(new 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 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 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 IdentifierExpression(((ILVariable)operand).Name).WithAnnotation(operand));
- }
- case ILCode.Ldnull: return new NullReferenceExpression();
- case ILCode.Ldstr: return new PrimitiveExpression(operand);
- case ILCode.Ldtoken:
- if (operand is TypeReference) {
- return AstBuilder.CreateTypeOfExpression((TypeReference)operand).Member("TypeHandle");
- } else {
- Expression referencedEntity;
- string loadName;
- string handleName;
- if (operand is FieldReference) {
- loadName = "fieldof";
- handleName = "FieldHandle";
- FieldReference fr = (FieldReference)operand;
- referencedEntity = AstBuilder.ConvertType(fr.DeclaringType).Member(fr.Name).WithAnnotation(fr);
- } else if (operand is 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: {
- 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 ArrayCreateExpression();
- ct.ArraySpecifiers.First().Remove();
- ct.ArraySpecifiers.MoveTo(ace.AdditionalArraySpecifiers);
- ace.Type = ct;
- ace.Arguments.AddRange(args);
- return ace;
- }
- }
- if (declaringType.IsAnonymousType()) {
- MethodDefinition ctor = ((MethodReference)operand).Resolve();
- if (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 ObjectCreateExpression();
- oce.Type = AstBuilder.ConvertType(declaringType);
- 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 ReturnStatement { Expression = arg1 };
- } else {
- return new ReturnStatement();
- }
- case ILCode.Rethrow: return new ThrowStatement();
- case ILCode.Sizeof: return new SizeOfExpression { Type = operandAsTypeRef };
- case ILCode.Stloc: {
- ILVariable locVar = (ILVariable)operand;
- if (!locVar.IsParameter)
- localVariablesToDefine.Add(locVar);
- return new AssignmentExpression(new 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 ThrowStatement { Expression = arg1 };
- case ILCode.Unaligned: return InlineAssembly(byteCode, args);
- case ILCode.Volatile: return InlineAssembly(byteCode, args);
- case ILCode.YieldBreak:
- return new YieldBreakStatement();
- case ILCode.YieldReturn:
- return new 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<MemberReferenceExpression>("left").Single();
- initializer.Elements.Add(
- new NamedExpression {
- Name = mre.MemberName,
- Expression = m.Get<Expression>("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<Expression>("arg").Single().Detach());
- } else {
- ArrayInitializerExpression argList = new ArrayInitializerExpression();
- foreach (var expr in m.Get<Expression>("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<Expression> args, IList<ParameterDefinition> 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<Expression> args)
- {
- MethodReference cecilMethod = (MethodReference)byteCode.Operand;
- MethodDefinition cecilMethodDef = cecilMethod.Resolve();
- Expression target;
- List<Expression> methodArgs = new List<Expression>(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 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 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 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<Expression> 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<ILCode, int> unhandledOpcodes = new ConcurrentDictionary<ILCode, int>();
- #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<Expression> 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 TypeReference) {
- return ((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<AstType> 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 DirectionExpression MakeRef(Expression expr)
- {
- return new DirectionExpression { Expression = expr, FieldDirection = FieldDirection.Ref };
- }
-
- Expression Convert(Expression expr, TypeReference actualType, 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 39bc2450..00000000
--- 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
-{
- /// <summary>
- /// Allows storing comments inside IEnumerable{Statement}. Used in the AstMethodBuilder.
- /// CommentStatement nodes are replaced with regular comments later on.
- /// </summary>
- internal 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<T>(IAstVisitor<T> visitor)
- {
- return default(T);
- }
-
- public override S AcceptVisitor<T, S>(IAstVisitor<T, S> visitor, T data)
- {
- return default(S);
- }
-
- public static void ReplaceAll(AstNode tree)
- {
- foreach (var cs in tree.Descendants.OfType<CommentStatement>()) {
- 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 d055de1d..00000000
--- a/ICSharpCode.Decompiler/Ast/DecompilerContext.cs
+++ /dev/null
@@ -1,71 +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 ITypeResolveContext TypeResolveContext;
-// public IProjectContent ProjectContent;
-
- public DecompilerContext(ModuleDefinition currentModule)
- {
- if (currentModule == null)
- throw new ArgumentNullException("currentModule");
- CurrentModule = currentModule;
-
-// this.ProjectContent = new CecilTypeResolveContext(currentModule);
-// List<ITypeResolveContext> resolveContexts = new List<ITypeResolveContext>();
-// resolveContexts.Add(this.ProjectContent);
-// foreach (AssemblyNameReference r in currentModule.AssemblyReferences) {
-// AssemblyDefinition d = currentModule.AssemblyResolver.Resolve(r);
-// if (d != null) {
-// resolveContexts.Add(new CecilTypeResolveContext(d.MainModule));
-// }
-// }
-// this.TypeResolveContext = new CompositeTypeResolveContext(resolveContexts);
- }
-
- /// <summary>
- /// Used to pass variable names from a method to its anonymous methods.
- /// </summary>
- internal List<string> ReservedVariableNames = new List<string>();
-
- public DecompilerContext Clone()
- {
- DecompilerContext ctx = (DecompilerContext)MemberwiseClone();
- ctx.ReservedVariableNames = new List<string>(ctx.ReservedVariableNames);
- return ctx;
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs b/ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs
deleted file mode 100644
index 80730061..00000000
--- a/ICSharpCode.Decompiler/Ast/NRefactoryExtensions.cs
+++ /dev/null
@@ -1,86 +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 ICSharpCode.NRefactory.CSharp;
-using ICSharpCode.NRefactory.PatternMatching;
-
-namespace ICSharpCode.Decompiler.Ast
-{
- internal static class NRefactoryExtensions
- {
- public static T WithAnnotation<T>(this T node, object annotation) where T : AstNode
- {
- if (annotation != null)
- node.AddAnnotation(annotation);
- return node;
- }
-
- public static T CopyAnnotationsFrom<T>(this T node, AstNode other) where T : AstNode
- {
- foreach (object annotation in other.Annotations) {
- node.AddAnnotation(annotation);
- }
- return node;
- }
-
- public static T Detach<T>(this T node) where T : AstNode
- {
- node.Remove();
- return node;
- }
-
- public static Expression WithName(this Expression node, string patternGroupName)
- {
- return new NamedNode(patternGroupName, node);
- }
-
- public static Statement WithName(this Statement node, string patternGroupName)
- {
- return new NamedNode(patternGroupName, node);
- }
-
- public static void AddNamedArgument(this NRefactory.CSharp.Attribute attribute, string name, Expression argument)
- {
- attribute.Arguments.Add(new AssignmentExpression(new IdentifierExpression(name), argument));
- }
-
- public static AstType ToType(this Pattern pattern)
- {
- return pattern;
- }
-
- public static Expression ToExpression(this Pattern pattern)
- {
- return pattern;
- }
-
- public static Statement ToStatement(this Pattern pattern)
- {
- return pattern;
- }
-
- public static Statement GetNextStatement(this Statement statement)
- {
- AstNode next = statement.NextSibling;
- while (next != null && !(next is Statement))
- next = next.NextSibling;
- return (Statement)next;
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/NameVariables.cs b/ICSharpCode.Decompiler/Ast/NameVariables.cs
deleted file mode 100644
index 3da808cb..00000000
--- 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<string, string> typeNameToVariableNameDict = new Dictionary<string, string> {
- { "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<ILVariable> parameters, IEnumerable<ILVariable> 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<string> fieldNamesInCurrentType;
- Dictionary<string, int> typeNames = new Dictionary<string, int>();
-
- 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<ILWhileLoop>()) {
- 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<ILExpression>()
- 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<ILExpression>()
- 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] == '_')
- 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 fed08aaa..00000000
--- a/ICSharpCode.Decompiler/Ast/TextTokenWriter.cs
+++ /dev/null
@@ -1,369 +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<AstNode> nodeStack = new Stack<AstNode>();
- 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)
- {
- 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<MemberReference>();
- if (memberRef == null && node.Role == Roles.TargetExpression && (node.Parent is InvocationExpression || node.Parent is ObjectCreateExpression)) {
- memberRef = node.Parent.Annotation<MemberReference>();
- }
- 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<ILVariable>();
- 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<MethodReference>()).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<ParameterDefinition>();
- if (parameterDef != null)
- return parameterDef;
-
- if (node is VariableInitializer || node is CatchClause || node is ForeachStatement) {
- var variable = node.Annotation<ILVariable>();
- 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<MethodReference>()).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<MemberReference>();
-
- 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<BlockStatement>().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<BlockStatement>().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<TextLocation> startLocations = new Stack<TextLocation>();
- Stack<MethodDebugSymbols> symbolsStack = new Stack<MethodDebugSymbols>();
-
- 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<MemberReference>() != null && node.GetChildByRole(Roles.Identifier).IsNull)
- output.WriteDefinition("", node.Annotation<MemberReference>(), false);
-
- if (node.Annotation<MethodDebugSymbols>() != null) {
- symbolsStack.Push(node.Annotation<MethodDebugSymbols>());
- symbolsStack.Peek().StartLocation = startLocations.Peek();
- }
- }
-
- 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<List<ILRange>>();
- 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<MethodDebugSymbols>() != null) {
- symbolsStack.Peek().EndLocation = output.Location;
- output.AddDebugSymbols(symbolsStack.Pop());
- }
- }
-
- static bool IsDefinition(AstNode node)
- {
- return node is EntityDeclaration
- || (node is VariableInitializer && node.Parent is FieldDeclaration)
- || node is FixedVariableInitializer;
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/AddCheckedBlocks.cs b/ICSharpCode.Decompiler/Ast/Transforms/AddCheckedBlocks.cs
deleted file mode 100644
index dc018eb1..00000000
--- a/ICSharpCode.Decompiler/Ast/Transforms/AddCheckedBlocks.cs
+++ /dev/null
@@ -1,368 +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.Decompiler.ILAst;
-using ICSharpCode.NRefactory.CSharp;
-
-namespace ICSharpCode.Decompiler.Ast.Transforms
-{
- /// <summary>
- /// Add checked/unchecked blocks.
- /// </summary>
- public class AddCheckedBlocks : IAstTransform
- {
- #region Annotation
- sealed class CheckedUncheckedAnnotation {
- /// <summary>
- /// true=checked, false=unchecked
- /// </summary>
- public bool IsChecked;
- }
-
- public static readonly object CheckedAnnotation = new CheckedUncheckedAnnotation { IsChecked = true };
- public static readonly object UncheckedAnnotation = new CheckedUncheckedAnnotation { IsChecked = false };
- #endregion
-
- /*
- We treat placing checked/unchecked blocks as an optimization problem, with the following goals:
- 1. Use minimum number of checked blocks+expressions
- 2. Prefer checked expressions over checked blocks
- 3. Make the scope of checked expressions as small as possible
- 4. Open checked blocks as late as possible, and close checked blocks as late as possible
- (where goal 1 has the highest priority)
-
- Goal 4a (open checked blocks as late as possible) is necessary so that we don't move variable declarations
- into checked blocks, as the variable might still be used after the checked block.
- (this could cause DeclareVariables to omit the variable declaration, producing incorrect code)
- Goal 4b (close checked blocks as late as possible) makes the code look nicer in this case:
- checked {
- int c = a + b;
- int r = a + c;
- return r;
- }
- If the checked block was closed as early as possible, the variable r would have to be declared outside
- (this would work, but look badly)
- */
-
- #region struct Cost
- struct Cost
- {
- // highest possible cost so that the Blocks+Expressions addition doesn't overflow
- public static readonly Cost Infinite = new Cost(0x3fffffff, 0x3fffffff);
-
- public readonly int Blocks;
- public readonly int Expressions;
-
- public Cost(int blocks, int expressions)
- {
- Blocks = blocks;
- Expressions = expressions;
- }
-
- public static bool operator <(Cost a, Cost b)
- {
- return a.Blocks + a.Expressions < b.Blocks + b.Expressions
- || a.Blocks + a.Expressions == b.Blocks + b.Expressions && a.Blocks < b.Blocks;
- }
-
- public static bool operator >(Cost a, Cost b)
- {
- return a.Blocks + a.Expressions > b.Blocks + b.Expressions
- || a.Blocks + a.Expressions == b.Blocks + b.Expressions && a.Blocks > b.Blocks;
- }
-
- public static bool operator <=(Cost a, Cost b)
- {
- return a.Blocks + a.Expressions < b.Blocks + b.Expressions
- || a.Blocks + a.Expressions == b.Blocks + b.Expressions && a.Blocks <= b.Blocks;
- }
-
- public static bool operator >=(Cost a, Cost b)
- {
- return a.Blocks + a.Expressions > b.Blocks + b.Expressions
- || a.Blocks + a.Expressions == b.Blocks + b.Expressions && a.Blocks >= b.Blocks;
- }
-
- public static Cost operator +(Cost a, Cost b)
- {
- return new Cost(a.Blocks + b.Blocks, a.Expressions + b.Expressions);
- }
-
- public override string ToString()
- {
- return string.Format("[{0} + {1}]", Blocks, Expressions);
- }
- }
- #endregion
-
- #region class InsertedNode
- /// <summary>
- /// Holds the blocks and expressions that should be inserted
- /// </summary>
- abstract class InsertedNode
- {
- public static InsertedNode operator +(InsertedNode a, InsertedNode b)
- {
- if (a == null)
- return b;
- if (b == null)
- return a;
- return new InsertedNodeList(a, b);
- }
-
- public abstract void Insert();
- }
-
- class InsertedNodeList : InsertedNode
- {
- readonly InsertedNode child1, child2;
-
- public InsertedNodeList(InsertedNode child1, InsertedNode child2)
- {
- this.child1 = child1;
- this.child2 = child2;
- }
-
- public override void Insert()
- {
- child1.Insert();
- child2.Insert();
- }
- }
-
- class InsertedExpression : InsertedNode
- {
- readonly Expression expression;
- readonly bool isChecked;
-
- public InsertedExpression(Expression expression, bool isChecked)
- {
- this.expression = expression;
- this.isChecked = isChecked;
- }
-
- public override void Insert()
- {
- if (isChecked)
- expression.ReplaceWith(e => new CheckedExpression { Expression = e });
- else
- expression.ReplaceWith(e => new UncheckedExpression { Expression = e });
- }
- }
-
- class ConvertCompoundAssignment : InsertedNode
- {
- readonly Expression expression;
- readonly bool isChecked;
-
- public ConvertCompoundAssignment(Expression expression, bool isChecked)
- {
- this.expression = expression;
- this.isChecked = isChecked;
- }
-
- public override void Insert()
- {
- AssignmentExpression assign = expression.Annotation<ReplaceMethodCallsWithOperators.RestoreOriginalAssignOperatorAnnotation>().Restore(expression);
- expression.ReplaceWith(assign);
- if (isChecked)
- assign.Right = new CheckedExpression { Expression = assign.Right.Detach() };
- else
- assign.Right = new UncheckedExpression { Expression = assign.Right.Detach() };
- }
- }
-
- class InsertedBlock : InsertedNode
- {
- readonly Statement firstStatement; // inclusive
- readonly Statement lastStatement; // exclusive
- readonly bool isChecked;
-
- public InsertedBlock(Statement firstStatement, Statement lastStatement, bool isChecked)
- {
- this.firstStatement = firstStatement;
- this.lastStatement = lastStatement;
- this.isChecked = isChecked;
- }
-
- public override void Insert()
- {
- BlockStatement newBlock = new BlockStatement();
- // Move all statements except for the first
- Statement next;
- for (Statement stmt = firstStatement.GetNextStatement(); stmt != lastStatement; stmt = next) {
- next = stmt.GetNextStatement();
- newBlock.Add(stmt.Detach());
- }
- // Replace the first statement with the new (un)checked block
- if (isChecked)
- firstStatement.ReplaceWith(new CheckedStatement { Body = newBlock });
- else
- firstStatement.ReplaceWith(new UncheckedStatement { Body = newBlock });
- // now also move the first node into the new block
- newBlock.Statements.InsertAfter(null, firstStatement);
- }
- }
- #endregion
-
- #region class Result
- /// <summary>
- /// Holds the result of an insertion operation.
- /// </summary>
- class Result
- {
- public Cost CostInCheckedContext;
- public InsertedNode NodesToInsertInCheckedContext;
- public Cost CostInUncheckedContext;
- public InsertedNode NodesToInsertInUncheckedContext;
- }
- #endregion
-
- public void Run(AstNode node)
- {
- BlockStatement block = node as BlockStatement;
- if (block == null) {
- for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
- Run(child);
- }
- } else {
- Result r = GetResultFromBlock(block);
- if (r.NodesToInsertInUncheckedContext != null)
- r.NodesToInsertInUncheckedContext.Insert();
- }
- }
-
- Result GetResultFromBlock(BlockStatement block)
- {
- // For a block, we are tracking 4 possibilities:
- // a) context is checked, no unchecked block open
- Cost costCheckedContext = new Cost(0, 0);
- InsertedNode nodesCheckedContext = null;
- // b) context is checked, an unchecked block is open
- Cost costCheckedContextUncheckedBlockOpen = Cost.Infinite;
- InsertedNode nodesCheckedContextUncheckedBlockOpen = null;
- Statement uncheckedBlockStart = null;
- // c) context is unchecked, no checked block open
- Cost costUncheckedContext = new Cost(0, 0);
- InsertedNode nodesUncheckedContext = null;
- // d) context is unchecked, a checked block is open
- Cost costUncheckedContextCheckedBlockOpen = Cost.Infinite;
- InsertedNode nodesUncheckedContextCheckedBlockOpen = null;
- Statement checkedBlockStart = null;
-
- Statement statement = block.Statements.FirstOrDefault();
- while (true) {
- // Blocks can be closed 'for free'. We use '<=' so that blocks are closed as late as possible (goal 4b)
- if (costCheckedContextUncheckedBlockOpen <= costCheckedContext) {
- costCheckedContext = costCheckedContextUncheckedBlockOpen;
- nodesCheckedContext = nodesCheckedContextUncheckedBlockOpen + new InsertedBlock(uncheckedBlockStart, statement, false);
- }
- if (costUncheckedContextCheckedBlockOpen <= costUncheckedContext) {
- costUncheckedContext = costUncheckedContextCheckedBlockOpen;
- nodesUncheckedContext = nodesUncheckedContextCheckedBlockOpen + new InsertedBlock(checkedBlockStart, statement, true);
- }
- if (statement == null)
- break;
- // Now try opening blocks. We use '<=' so that blocks are opened as late as possible. (goal 4a)
- if (costCheckedContext + new Cost(1, 0) <= costCheckedContextUncheckedBlockOpen) {
- costCheckedContextUncheckedBlockOpen = costCheckedContext + new Cost(1, 0);
- nodesCheckedContextUncheckedBlockOpen = nodesCheckedContext;
- uncheckedBlockStart = statement;
- }
- if (costUncheckedContext + new Cost(1, 0) <= costUncheckedContextCheckedBlockOpen) {
- costUncheckedContextCheckedBlockOpen = costUncheckedContext + new Cost(1, 0);
- nodesUncheckedContextCheckedBlockOpen = nodesUncheckedContext;
- checkedBlockStart = statement;
- }
- // Now handle the statement
- Result stmtResult = GetResult(statement);
-
- costCheckedContext += stmtResult.CostInCheckedContext;
- nodesCheckedContext += stmtResult.NodesToInsertInCheckedContext;
- costCheckedContextUncheckedBlockOpen += stmtResult.CostInUncheckedContext;
- nodesCheckedContextUncheckedBlockOpen += stmtResult.NodesToInsertInUncheckedContext;
- costUncheckedContext += stmtResult.CostInUncheckedContext;
- nodesUncheckedContext += stmtResult.NodesToInsertInUncheckedContext;
- costUncheckedContextCheckedBlockOpen += stmtResult.CostInCheckedContext;
- nodesUncheckedContextCheckedBlockOpen += stmtResult.NodesToInsertInCheckedContext;
-
- statement = statement.GetNextStatement();
- }
-
- return new Result {
- CostInCheckedContext = costCheckedContext, NodesToInsertInCheckedContext = nodesCheckedContext,
- CostInUncheckedContext = costUncheckedContext, NodesToInsertInUncheckedContext = nodesUncheckedContext
- };
- }
-
- Result GetResult(AstNode node)
- {
- if (node is BlockStatement)
- return GetResultFromBlock((BlockStatement)node);
- Result result = new Result();
- for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
- Result childResult = GetResult(child);
- result.CostInCheckedContext += childResult.CostInCheckedContext;
- result.NodesToInsertInCheckedContext += childResult.NodesToInsertInCheckedContext;
- result.CostInUncheckedContext += childResult.CostInUncheckedContext;
- result.NodesToInsertInUncheckedContext += childResult.NodesToInsertInUncheckedContext;
- }
- Expression expr = node as Expression;
- if (expr != null) {
- CheckedUncheckedAnnotation annotation = expr.Annotation<CheckedUncheckedAnnotation>();
- if (annotation != null) {
- // If the annotation requires this node to be in a specific context, add a huge cost to the other context
- // That huge cost gives us the option to ignore a required checked/unchecked expression when there wouldn't be any
- // solution otherwise. (e.g. "for (checked(M().x += 1); true; unchecked(M().x += 2)) {}")
- if (annotation.IsChecked)
- result.CostInUncheckedContext += new Cost(10000, 0);
- else
- result.CostInCheckedContext += new Cost(10000, 0);
- }
- // Embed this node in an checked/unchecked expression:
- if (expr.Parent is ExpressionStatement) {
- // We cannot use checked/unchecked for top-level-expressions.
- // However, we could try converting a compound assignment (checked(a+=b);) or unary operator (checked(a++);)
- // back to its old form.
- if (expr.Annotation<ReplaceMethodCallsWithOperators.RestoreOriginalAssignOperatorAnnotation>() != null) {
- // We use '<' so that expressions are introduced on the deepest level possible (goal 3)
- if (result.CostInCheckedContext + new Cost(1, 1) < result.CostInUncheckedContext) {
- result.CostInUncheckedContext = result.CostInCheckedContext + new Cost(1, 1);
- result.NodesToInsertInUncheckedContext = result.NodesToInsertInCheckedContext + new ConvertCompoundAssignment(expr, true);
- } else if (result.CostInUncheckedContext + new Cost(1, 1) < result.CostInCheckedContext) {
- result.CostInCheckedContext = result.CostInUncheckedContext + new Cost(1, 1);
- result.NodesToInsertInCheckedContext = result.NodesToInsertInUncheckedContext + new ConvertCompoundAssignment(expr, false);
- }
- }
- } else if (expr.Role.IsValid(Expression.Null)) {
- // We use '<' so that expressions are introduced on the deepest level possible (goal 3)
- if (result.CostInCheckedContext + new Cost(0, 1) < result.CostInUncheckedContext) {
- result.CostInUncheckedContext = result.CostInCheckedContext + new Cost(0, 1);
- result.NodesToInsertInUncheckedContext = result.NodesToInsertInCheckedContext + new InsertedExpression(expr, true);
- } else if (result.CostInUncheckedContext + new Cost(0, 1) < result.CostInCheckedContext) {
- result.CostInCheckedContext = result.CostInUncheckedContext + new Cost(0, 1);
- result.NodesToInsertInCheckedContext = result.NodesToInsertInUncheckedContext + new InsertedExpression(expr, false);
- }
- }
- }
- return result;
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/CombineQueryExpressions.cs b/ICSharpCode.Decompiler/Ast/Transforms/CombineQueryExpressions.cs
deleted file mode 100644
index a0d1ca8c..00000000
--- a/ICSharpCode.Decompiler/Ast/Transforms/CombineQueryExpressions.cs
+++ /dev/null
@@ -1,179 +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.Transforms
-{
- /// <summary>
- /// Combines query expressions and removes transparent identifiers.
- /// </summary>
- public class CombineQueryExpressions : IAstTransform
- {
- readonly DecompilerContext context;
-
- public CombineQueryExpressions(DecompilerContext context)
- {
- this.context = context;
- }
-
- public void Run(AstNode compilationUnit)
- {
- if (!context.Settings.QueryExpressions)
- return;
- CombineQueries(compilationUnit);
- }
-
- static readonly InvocationExpression castPattern = new InvocationExpression {
- Target = new MemberReferenceExpression {
- Target = new AnyNode("inExpr"),
- MemberName = "Cast",
- TypeArguments = { new AnyNode("targetType") }
- }};
-
- void CombineQueries(AstNode node)
- {
- for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
- CombineQueries(child);
- }
- QueryExpression query = node as QueryExpression;
- if (query != null) {
- QueryFromClause fromClause = (QueryFromClause)query.Clauses.First();
- QueryExpression innerQuery = fromClause.Expression as QueryExpression;
- if (innerQuery != null) {
- if (TryRemoveTransparentIdentifier(query, fromClause, innerQuery)) {
- RemoveTransparentIdentifierReferences(query);
- } else {
- QueryContinuationClause continuation = new QueryContinuationClause();
- continuation.PrecedingQuery = innerQuery.Detach();
- continuation.Identifier = fromClause.Identifier;
- fromClause.ReplaceWith(continuation);
- }
- } else {
- Match m = castPattern.Match(fromClause.Expression);
- if (m.Success) {
- fromClause.Type = m.Get<AstType>("targetType").Single().Detach();
- fromClause.Expression = m.Get<Expression>("inExpr").Single().Detach();
- }
- }
- }
- }
-
- static readonly QuerySelectClause selectTransparentIdentifierPattern = new QuerySelectClause {
- Expression = new Choice {
- new AnonymousTypeCreateExpression {
- Initializers = {
- new NamedExpression {
- Name = Pattern.AnyString,
- Expression = new IdentifierExpression(Pattern.AnyString)
- }.WithName("nae1"),
- new NamedExpression {
- Name = Pattern.AnyString,
- Expression = new AnyNode("nae2Expr")
- }.WithName("nae2")
- }
- },
- new AnonymousTypeCreateExpression {
- Initializers = {
- new NamedNode("identifier", new IdentifierExpression(Pattern.AnyString)),
- new AnyNode("nae2Expr")
- }
- }
- }};
-
- bool IsTransparentIdentifier(string identifier)
- {
- return identifier.StartsWith("<>", StringComparison.Ordinal) && identifier.Contains("TransparentIdentifier");
- }
-
- bool TryRemoveTransparentIdentifier(QueryExpression query, QueryFromClause fromClause, QueryExpression innerQuery)
- {
- if (!IsTransparentIdentifier(fromClause.Identifier))
- return false;
- Match match = selectTransparentIdentifierPattern.Match(innerQuery.Clauses.Last());
- if (!match.Success)
- return false;
- QuerySelectClause selectClause = (QuerySelectClause)innerQuery.Clauses.Last();
- NamedExpression nae1 = match.Get<NamedExpression>("nae1").SingleOrDefault();
- NamedExpression nae2 = match.Get<NamedExpression>("nae2").SingleOrDefault();
- if (nae1 != null && nae1.Name != ((IdentifierExpression)nae1.Expression).Identifier)
- return false;
- Expression nae2Expr = match.Get<Expression>("nae2Expr").Single();
- IdentifierExpression nae2IdentExpr = nae2Expr as IdentifierExpression;
- if (nae2IdentExpr != null && (nae2 == null || nae2.Name == nae2IdentExpr.Identifier)) {
- // from * in (from x in ... select new { x = x, y = y }) ...
- // =>
- // from x in ... ...
- fromClause.Remove();
- selectClause.Remove();
- // Move clauses from innerQuery to query
- QueryClause insertionPos = null;
- foreach (var clause in innerQuery.Clauses) {
- query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach());
- }
- } else {
- // from * in (from x in ... select new { x = x, y = expr }) ...
- // =>
- // from x in ... let y = expr ...
- fromClause.Remove();
- selectClause.Remove();
- // Move clauses from innerQuery to query
- QueryClause insertionPos = null;
- foreach (var clause in innerQuery.Clauses) {
- query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach());
- }
- string ident;
- if (nae2 != null)
- ident = nae2.Name;
- else if (nae2Expr is IdentifierExpression)
- ident = ((IdentifierExpression)nae2Expr).Identifier;
- else if (nae2Expr is MemberReferenceExpression)
- ident = ((MemberReferenceExpression)nae2Expr).MemberName;
- else
- throw new InvalidOperationException("Could not infer name from initializer in AnonymousTypeCreateExpression");
- query.Clauses.InsertAfter(insertionPos, new QueryLetClause { Identifier = ident, Expression = nae2Expr.Detach() });
- }
- return true;
- }
-
- /// <summary>
- /// Removes all occurrences of transparent identifiers
- /// </summary>
- void RemoveTransparentIdentifierReferences(AstNode node)
- {
- foreach (AstNode child in node.Children) {
- RemoveTransparentIdentifierReferences(child);
- }
- MemberReferenceExpression mre = node as MemberReferenceExpression;
- if (mre != null) {
- IdentifierExpression ident = mre.Target as IdentifierExpression;
- if (ident != null && IsTransparentIdentifier(ident.Identifier)) {
- IdentifierExpression newIdent = new IdentifierExpression(mre.MemberName);
- mre.TypeArguments.MoveTo(newIdent.TypeArguments);
- newIdent.CopyAnnotationsFrom(mre);
- newIdent.RemoveAnnotations<PropertyDeclaration>(); // remove the reference to the property of the anonymous type
- mre.ReplaceWith(newIdent);
- return;
- }
- }
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/ContextTrackingVisitor.cs b/ICSharpCode.Decompiler/Ast/Transforms/ContextTrackingVisitor.cs
deleted file mode 100644
index 1d1f3d08..00000000
--- a/ICSharpCode.Decompiler/Ast/Transforms/ContextTrackingVisitor.cs
+++ /dev/null
@@ -1,111 +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.Diagnostics;
-using ICSharpCode.NRefactory.CSharp;
-using Mono.Cecil;
-
-namespace ICSharpCode.Decompiler.Ast.Transforms
-{
- /// <summary>
- /// Base class for AST visitors that need the current type/method context info.
- /// </summary>
- public abstract class ContextTrackingVisitor<TResult> : DepthFirstAstVisitor<object, TResult>, IAstTransform
- {
- protected readonly DecompilerContext context;
-
- protected ContextTrackingVisitor(DecompilerContext context)
- {
- if (context == null)
- throw new ArgumentNullException("context");
- this.context = context;
- }
-
- public override TResult VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data)
- {
- TypeDefinition oldType = context.CurrentType;
- try {
- context.CurrentType = typeDeclaration.Annotation<TypeDefinition>();
- return base.VisitTypeDeclaration(typeDeclaration, data);
- } finally {
- context.CurrentType = oldType;
- }
- }
-
- public override TResult VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data)
- {
- Debug.Assert(context.CurrentMethod == null);
- try {
- context.CurrentMethod = methodDeclaration.Annotation<MethodDefinition>();
- return base.VisitMethodDeclaration(methodDeclaration, data);
- } finally {
- context.CurrentMethod = null;
- }
- }
-
- public override TResult VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data)
- {
- Debug.Assert(context.CurrentMethod == null);
- try {
- context.CurrentMethod = constructorDeclaration.Annotation<MethodDefinition>();
- return base.VisitConstructorDeclaration(constructorDeclaration, data);
- } finally {
- context.CurrentMethod = null;
- }
- }
-
- public override TResult VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration, object data)
- {
- Debug.Assert(context.CurrentMethod == null);
- try {
- context.CurrentMethod = destructorDeclaration.Annotation<MethodDefinition>();
- return base.VisitDestructorDeclaration(destructorDeclaration, data);
- } finally {
- context.CurrentMethod = null;
- }
- }
-
- public override TResult VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data)
- {
- Debug.Assert(context.CurrentMethod == null);
- try {
- context.CurrentMethod = operatorDeclaration.Annotation<MethodDefinition>();
- return base.VisitOperatorDeclaration(operatorDeclaration, data);
- } finally {
- context.CurrentMethod = null;
- }
- }
-
- public override TResult VisitAccessor(Accessor accessor, object data)
- {
- Debug.Assert(context.CurrentMethod == null);
- try {
- context.CurrentMethod = accessor.Annotation<MethodDefinition>();
- return base.VisitAccessor(accessor, data);
- } finally {
- context.CurrentMethod = null;
- }
- }
-
- void IAstTransform.Run(AstNode node)
- {
- node.AcceptVisitor(this, null);
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs b/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs
deleted file mode 100644
index 36811c18..00000000
--- a/ICSharpCode.Decompiler/Ast/Transforms/ConvertConstructorCallIntoInitializer.cs
+++ /dev/null
@@ -1,183 +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.NRefactory.CSharp;
-using ICSharpCode.NRefactory.PatternMatching;
-using Mono.Cecil;
-
-namespace ICSharpCode.Decompiler.Ast.Transforms
-{
- /// <summary>
- /// If the first element of a constructor is a chained constructor call, convert it into a constructor initializer.
- /// </summary>
- public class ConvertConstructorCallIntoInitializer : DepthFirstAstVisitor<object, object>, IAstTransform
- {
- public override object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data)
- {
- ExpressionStatement stmt = constructorDeclaration.Body.Statements.FirstOrDefault() as ExpressionStatement;
- if (stmt == null)
- return null;
- InvocationExpression invocation = stmt.Expression as InvocationExpression;
- if (invocation == null)
- return null;
- MemberReferenceExpression mre = invocation.Target as MemberReferenceExpression;
- if (mre != null && mre.MemberName == ".ctor") {
- ConstructorInitializer ci = new ConstructorInitializer();
- if (mre.Target is ThisReferenceExpression)
- ci.ConstructorInitializerType = ConstructorInitializerType.This;
- else if (mre.Target is BaseReferenceExpression)
- ci.ConstructorInitializerType = ConstructorInitializerType.Base;
- else
- return null;
- // Move arguments from invocation to initializer:
- invocation.Arguments.MoveTo(ci.Arguments);
- // Add the initializer: (unless it is the default 'base()')
- if (!(ci.ConstructorInitializerType == ConstructorInitializerType.Base && ci.Arguments.Count == 0))
- constructorDeclaration.Initializer = ci.WithAnnotation(invocation.Annotation<MethodReference>());
- // Remove the statement:
- stmt.Remove();
- }
- return null;
- }
-
- static readonly ExpressionStatement fieldInitializerPattern = new ExpressionStatement {
- Expression = new AssignmentExpression {
- Left = new NamedNode("fieldAccess", new MemberReferenceExpression {
- Target = new ThisReferenceExpression(),
- MemberName = Pattern.AnyString
- }),
- Operator = AssignmentOperatorType.Assign,
- Right = new AnyNode("initializer")
- }
- };
-
- static readonly AstNode thisCallPattern = new ExpressionStatement(new ThisReferenceExpression().Invoke(".ctor", new Repeat(new AnyNode())));
-
- public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data)
- {
- // Handle initializers on instance fields
- HandleInstanceFieldInitializers(typeDeclaration.Members);
-
- // Now convert base constructor calls to initializers:
- base.VisitTypeDeclaration(typeDeclaration, data);
-
- // Remove single empty constructor:
- RemoveSingleEmptyConstructor(typeDeclaration);
-
- // Handle initializers on static fields:
- HandleStaticFieldInitializers(typeDeclaration.Members);
- return null;
- }
-
- void HandleInstanceFieldInitializers(IEnumerable<AstNode> members)
- {
- var instanceCtors = members.OfType<ConstructorDeclaration>().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray();
- var instanceCtorsNotChainingWithThis = instanceCtors.Where(ctor => !thisCallPattern.IsMatch(ctor.Body.Statements.FirstOrDefault())).ToArray();
- if (instanceCtorsNotChainingWithThis.Length > 0) {
- MethodDefinition ctorMethodDef = instanceCtorsNotChainingWithThis[0].Annotation<MethodDefinition>();
- if (ctorMethodDef != null && ctorMethodDef.DeclaringType.IsValueType)
- return;
-
- // Recognize field initializers:
- // Convert first statement in all ctors (if all ctors have the same statement) into a field initializer.
- bool allSame;
- do {
- Match m = fieldInitializerPattern.Match(instanceCtorsNotChainingWithThis[0].Body.FirstOrDefault());
- if (!m.Success)
- break;
-
- FieldDefinition fieldDef = m.Get<AstNode>("fieldAccess").Single().Annotation<FieldReference>().ResolveWithinSameModule();
- if (fieldDef == null)
- break;
- AstNode fieldOrEventDecl = members.FirstOrDefault(f => f.Annotation<FieldDefinition>() == fieldDef);
- if (fieldOrEventDecl == null)
- break;
- Expression initializer = m.Get<Expression>("initializer").Single();
- // 'this'/'base' cannot be used in field initializers
- if (initializer.DescendantsAndSelf.Any(n => n is ThisReferenceExpression || n is BaseReferenceExpression))
- break;
-
- allSame = true;
- for (int i = 1; i < instanceCtorsNotChainingWithThis.Length; i++) {
- if (!instanceCtors[0].Body.First().IsMatch(instanceCtorsNotChainingWithThis[i].Body.FirstOrDefault()))
- allSame = false;
- }
- if (allSame) {
- foreach (var ctor in instanceCtorsNotChainingWithThis)
- ctor.Body.First().Remove();
- fieldOrEventDecl.GetChildrenByRole(Roles.Variable).Single().Initializer = initializer.Detach();
- }
- } while (allSame);
- }
- }
-
- void RemoveSingleEmptyConstructor(TypeDeclaration typeDeclaration)
- {
- var instanceCtors = typeDeclaration.Members.OfType<ConstructorDeclaration>().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray();
- if (instanceCtors.Length == 1) {
- ConstructorDeclaration emptyCtor = new ConstructorDeclaration();
- emptyCtor.Modifiers = ((typeDeclaration.Modifiers & Modifiers.Abstract) == Modifiers.Abstract ? Modifiers.Protected : Modifiers.Public);
- emptyCtor.Body = new BlockStatement();
- if (emptyCtor.IsMatch(instanceCtors[0]))
- instanceCtors[0].Remove();
- }
- }
-
- void HandleStaticFieldInitializers(IEnumerable<AstNode> members)
- {
- // Convert static constructor into field initializers if the class is BeforeFieldInit
- var staticCtor = members.OfType<ConstructorDeclaration>().FirstOrDefault(c => (c.Modifiers & Modifiers.Static) == Modifiers.Static);
- if (staticCtor != null) {
- MethodDefinition ctorMethodDef = staticCtor.Annotation<MethodDefinition>();
- if (ctorMethodDef != null && ctorMethodDef.DeclaringType.IsBeforeFieldInit) {
- while (true) {
- ExpressionStatement es = staticCtor.Body.Statements.FirstOrDefault() as ExpressionStatement;
- if (es == null)
- break;
- AssignmentExpression assignment = es.Expression as AssignmentExpression;
- if (assignment == null || assignment.Operator != AssignmentOperatorType.Assign)
- break;
- FieldDefinition fieldDef = assignment.Left.Annotation<FieldReference>().ResolveWithinSameModule();
- if (fieldDef == null || !fieldDef.IsStatic)
- break;
- FieldDeclaration fieldDecl = members.OfType<FieldDeclaration>().FirstOrDefault(f => f.Annotation<FieldDefinition>() == fieldDef);
- if (fieldDecl == null)
- break;
- fieldDecl.Variables.Single().Initializer = assignment.Right.Detach();
- es.Remove();
- }
- if (staticCtor.Body.Statements.Count == 0)
- staticCtor.Remove();
- }
- }
- }
-
- void IAstTransform.Run(AstNode node)
- {
- // If we're viewing some set of members (fields are direct children of CompilationUnit),
- // we also need to handle those:
- HandleInstanceFieldInitializers(node.Children);
- HandleStaticFieldInitializers(node.Children);
-
- node.AcceptVisitor(this, null);
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/CustomPatterns.cs b/ICSharpCode.Decompiler/Ast/Transforms/CustomPatterns.cs
deleted file mode 100644
index b80c56af..00000000
--- a/ICSharpCode.Decompiler/Ast/Transforms/CustomPatterns.cs
+++ /dev/null
@@ -1,109 +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 System.Reflection;
-using ICSharpCode.NRefactory.CSharp;
-using ICSharpCode.NRefactory.PatternMatching;
-using Mono.Cecil;
-
-namespace ICSharpCode.Decompiler.Ast.Transforms
-{
- internal sealed class TypePattern : Pattern
- {
- readonly string ns;
- readonly string name;
-
- public TypePattern(Type type)
- {
- ns = type.Namespace;
- name = type.Name;
- }
-
- public override bool DoMatch(INode other, Match match)
- {
- ComposedType ct = other as ComposedType;
- AstType o;
- if (ct != null && !ct.HasNullableSpecifier && ct.PointerRank == 0 && !ct.ArraySpecifiers.Any()) {
- // Special case: ILSpy sometimes produces a ComposedType but then removed all array specifiers
- // from it. In that case, we need to look at the base type for the annotations.
- o = ct.BaseType;
- } else {
- o = other as AstType;
- if (o == null)
- return false;
- }
- TypeReference tr = o.Annotation<TypeReference>();
- return tr != null && tr.Namespace == ns && tr.Name == name;
- }
-
- public override string ToString()
- {
- return name;
- }
- }
-
- internal sealed class LdTokenPattern : Pattern
- {
- AnyNode childNode;
-
- public LdTokenPattern(string groupName)
- {
- childNode = new AnyNode(groupName);
- }
-
- public override bool DoMatch(INode other, Match match)
- {
- InvocationExpression ie = other as InvocationExpression;
- if (ie != null && ie.Annotation<LdTokenAnnotation>() != null && ie.Arguments.Count == 1) {
- return childNode.DoMatch(ie.Arguments.Single(), match);
- }
- return false;
- }
-
- public override string ToString()
- {
- return "ldtoken(...)";
- }
- }
-
- /// <summary>
- /// typeof-Pattern that applies on the expanded form of typeof (prior to ReplaceMethodCallsWithOperators)
- /// </summary>
- internal sealed class TypeOfPattern : Pattern
- {
- INode childNode;
-
- public TypeOfPattern(string groupName)
- {
- childNode = new TypePattern(typeof(Type)).ToType().Invoke(
- "GetTypeFromHandle", new TypeOfExpression(new AnyNode(groupName)).Member("TypeHandle"));
- }
-
- public override bool DoMatch(INode other, Match match)
- {
- return childNode.DoMatch(other, match);
- }
-
- public override string ToString()
- {
- return "typeof(...)";
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs b/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs
deleted file mode 100644
index 298682af..00000000
--- a/ICSharpCode.Decompiler/Ast/Transforms/DecimalConstantTransform.cs
+++ /dev/null
@@ -1,58 +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 ICSharpCode.NRefactory.CSharp;
-using ICSharpCode.NRefactory.PatternMatching;
-using Mono.Cecil;
-
-namespace ICSharpCode.Decompiler.Ast.Transforms
-{
- /// <summary>
- /// Transforms decimal constant fields.
- /// </summary>
- public class DecimalConstantTransform : DepthFirstAstVisitor<object, object>, IAstTransform
- {
- static readonly PrimitiveType decimalType = new PrimitiveType("decimal");
-
- public override object VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data)
- {
- const Modifiers staticReadOnly = Modifiers.Static | Modifiers.Readonly;
- if ((fieldDeclaration.Modifiers & staticReadOnly) == staticReadOnly && decimalType.IsMatch(fieldDeclaration.ReturnType)) {
- foreach (var attributeSection in fieldDeclaration.Attributes) {
- foreach (var attribute in attributeSection.Attributes) {
- TypeReference tr = attribute.Type.Annotation<TypeReference>();
- if (tr != null && tr.Name == "DecimalConstantAttribute" && tr.Namespace == "System.Runtime.CompilerServices") {
- attribute.Remove();
- if (attributeSection.Attributes.Count == 0)
- attributeSection.Remove();
- fieldDeclaration.Modifiers = (fieldDeclaration.Modifiers & ~staticReadOnly) | Modifiers.Const;
- return null;
- }
- }
- }
- }
- return null;
- }
-
- public void Run(AstNode compilationUnit)
- {
- compilationUnit.AcceptVisitor(this, null);
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs b/ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs
deleted file mode 100644
index a27f30b4..00000000
--- a/ICSharpCode.Decompiler/Ast/Transforms/DeclareVariables.cs
+++ /dev/null
@@ -1,368 +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.Diagnostics;
-using System.Linq;
-using System.Threading;
-using ICSharpCode.Decompiler.ILAst;
-using ICSharpCode.NRefactory.CSharp;
-using ICSharpCode.NRefactory.CSharp.Analysis;
-
-namespace ICSharpCode.Decompiler.Ast.Transforms
-{
- /// <summary>
- /// Moves variable declarations to improved positions.
- /// </summary>
- public class DeclareVariables : IAstTransform
- {
- sealed class VariableToDeclare
- {
- public AstType Type;
- public string Name;
- public ILVariable ILVariable;
-
- public AssignmentExpression ReplacedAssignment;
- public Statement InsertionPoint;
- }
-
- readonly CancellationToken cancellationToken;
- List<VariableToDeclare> variablesToDeclare = new List<VariableToDeclare>();
-
- public DeclareVariables(DecompilerContext context)
- {
- cancellationToken = context.CancellationToken;
- }
-
- public void Run(AstNode node)
- {
- Run(node, null);
- // Declare all the variables at the end, after all the logic has run.
- // This is done so that definite assignment analysis can work on a single representation and doesn't have to be updated
- // when we change the AST.
- foreach (var v in variablesToDeclare) {
- if (v.ReplacedAssignment == null) {
- BlockStatement block = (BlockStatement)v.InsertionPoint.Parent;
- var decl = new VariableDeclarationStatement((AstType)v.Type.Clone(), v.Name);
- if (v.ILVariable != null)
- decl.Variables.Single().AddAnnotation(v.ILVariable);
- block.Statements.InsertBefore(
- v.InsertionPoint,
- decl);
- }
- }
- // First do all the insertions, then do all the replacements. This is necessary because a replacement might remove our reference point from the AST.
- foreach (var v in variablesToDeclare) {
- if (v.ReplacedAssignment != null) {
- // We clone the right expression so that it doesn't get removed from the old ExpressionStatement,
- // which might be still in use by the definite assignment graph.
- VariableInitializer initializer = new VariableInitializer(v.Name, v.ReplacedAssignment.Right.Detach()).CopyAnnotationsFrom(v.ReplacedAssignment).WithAnnotation(v.ILVariable);
- VariableDeclarationStatement varDecl = new VariableDeclarationStatement {
- Type = (AstType)v.Type.Clone(),
- Variables = { initializer }
- };
- ExpressionStatement es = v.ReplacedAssignment.Parent as ExpressionStatement;
- if (es != null) {
- // Note: if this crashes with 'Cannot replace the root node', check whether two variables were assigned the same name
- es.ReplaceWith(varDecl.CopyAnnotationsFrom(es));
- } else {
- v.ReplacedAssignment.ReplaceWith(varDecl);
- }
- }
- }
- variablesToDeclare = null;
- }
-
- void Run(AstNode node, DefiniteAssignmentAnalysis daa)
- {
- BlockStatement block = node as BlockStatement;
- if (block != null) {
- var variables = block.Statements.TakeWhile(stmt => stmt is VariableDeclarationStatement)
- .Cast<VariableDeclarationStatement>().ToList();
- if (variables.Count > 0) {
- // remove old variable declarations:
- foreach (VariableDeclarationStatement varDecl in variables) {
- Debug.Assert(varDecl.Variables.Single().Initializer.IsNull);
- varDecl.Remove();
- }
- if (daa == null) {
- // If possible, reuse the DefiniteAssignmentAnalysis that was created for the parent block
- daa = new DefiniteAssignmentAnalysis(block, cancellationToken);
- }
- foreach (VariableDeclarationStatement varDecl in variables) {
- VariableInitializer initializer = varDecl.Variables.Single();
- string variableName = initializer.Name;
- ILVariable v = initializer.Annotation<ILVariable>();
- bool allowPassIntoLoops = initializer.Annotation<DelegateConstruction.CapturedVariableAnnotation>() == null;
- DeclareVariableInBlock(daa, block, varDecl.Type, variableName, v, allowPassIntoLoops);
- }
- }
- }
- for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
- Run(child, daa);
- }
- }
-
- void DeclareVariableInBlock(DefiniteAssignmentAnalysis daa, BlockStatement block, AstType type, string variableName, ILVariable v, bool allowPassIntoLoops)
- {
- // declarationPoint: The point where the variable would be declared, if we decide to declare it in this block
- Statement declarationPoint = null;
- // Check whether we can move down the variable into the sub-blocks
- bool canMoveVariableIntoSubBlocks = FindDeclarationPoint(daa, variableName, allowPassIntoLoops, block, out declarationPoint);
- if (declarationPoint == null) {
- // The variable isn't used at all
- return;
- }
- if (canMoveVariableIntoSubBlocks) {
- // Declare the variable within the sub-blocks
- foreach (Statement stmt in block.Statements) {
- ForStatement forStmt = stmt as ForStatement;
- if (forStmt != null && forStmt.Initializers.Count == 1) {
- // handle the special case of moving a variable into the for initializer
- if (TryConvertAssignmentExpressionIntoVariableDeclaration(forStmt.Initializers.Single(), type, variableName))
- continue;
- }
- UsingStatement usingStmt = stmt as UsingStatement;
- if (usingStmt != null && usingStmt.ResourceAcquisition is AssignmentExpression) {
- // handle the special case of moving a variable into a using statement
- if (TryConvertAssignmentExpressionIntoVariableDeclaration((Expression)usingStmt.ResourceAcquisition, type, variableName))
- continue;
- }
- IfElseStatement ies = stmt as IfElseStatement;
- if (ies != null) {
- foreach (var child in IfElseChainChildren(ies)) {
- BlockStatement subBlock = child as BlockStatement;
- if (subBlock != null)
- DeclareVariableInBlock(daa, subBlock, type, variableName, v, allowPassIntoLoops);
- }
- continue;
- }
- foreach (AstNode child in stmt.Children) {
- BlockStatement subBlock = child as BlockStatement;
- if (subBlock != null) {
- DeclareVariableInBlock(daa, subBlock, type, variableName, v, allowPassIntoLoops);
- } else if (HasNestedBlocks(child)) {
- foreach (BlockStatement nestedSubBlock in child.Children.OfType<BlockStatement>()) {
- DeclareVariableInBlock(daa, nestedSubBlock, type, variableName, v, allowPassIntoLoops);
- }
- }
- }
- }
- } else {
- // Try converting an assignment expression into a VariableDeclarationStatement
- if (!TryConvertAssignmentExpressionIntoVariableDeclaration(declarationPoint, type, variableName)) {
- // Declare the variable in front of declarationPoint
- variablesToDeclare.Add(new VariableToDeclare { Type = type, Name = variableName, ILVariable = v, InsertionPoint = declarationPoint });
- }
- }
- }
-
- bool TryConvertAssignmentExpressionIntoVariableDeclaration(Statement declarationPoint, AstType type, string variableName)
- {
- // convert the declarationPoint into a VariableDeclarationStatement
- ExpressionStatement es = declarationPoint as ExpressionStatement;
- if (es != null) {
- return TryConvertAssignmentExpressionIntoVariableDeclaration(es.Expression, type, variableName);
- }
- return false;
- }
-
- bool TryConvertAssignmentExpressionIntoVariableDeclaration(Expression expression, AstType type, string variableName)
- {
- AssignmentExpression ae = expression as AssignmentExpression;
- if (ae != null && ae.Operator == AssignmentOperatorType.Assign) {
- IdentifierExpression ident = ae.Left as IdentifierExpression;
- if (ident != null && ident.Identifier == variableName) {
- variablesToDeclare.Add(new VariableToDeclare { Type = type, Name = variableName, ILVariable = ident.Annotation<ILVariable>(), ReplacedAssignment = ae });
- return true;
- }
- }
- return false;
- }
-
- /// <summary>
- /// Finds the declaration point for the variable within the specified block.
- /// </summary>
- /// <param name="daa">
- /// Definite assignment analysis, must be prepared for 'block' or one of its parents.
- /// </param>
- /// <param name="varDecl">The variable to declare</param>
- /// <param name="block">The block in which the variable should be declared</param>
- /// <param name="declarationPoint">
- /// Output parameter: the first statement within 'block' where the variable needs to be declared.
- /// </param>
- /// <returns>
- /// Returns whether it is possible to move the variable declaration into sub-blocks.
- /// </returns>
- public static bool FindDeclarationPoint(DefiniteAssignmentAnalysis daa, VariableDeclarationStatement varDecl, BlockStatement block, out Statement declarationPoint)
- {
- string variableName = varDecl.Variables.Single().Name;
- bool allowPassIntoLoops = varDecl.Variables.Single().Annotation<DelegateConstruction.CapturedVariableAnnotation>() == null;
- return FindDeclarationPoint(daa, variableName, allowPassIntoLoops, block, out declarationPoint);
- }
-
- static bool FindDeclarationPoint(DefiniteAssignmentAnalysis daa, string variableName, bool allowPassIntoLoops, BlockStatement block, out Statement declarationPoint)
- {
- // declarationPoint: The point where the variable would be declared, if we decide to declare it in this block
- declarationPoint = null;
- foreach (Statement stmt in block.Statements) {
- if (UsesVariable(stmt, variableName)) {
- if (declarationPoint == null)
- declarationPoint = stmt;
- if (!CanMoveVariableUseIntoSubBlock(stmt, variableName, allowPassIntoLoops)) {
- // If it's not possible to move the variable use into a nested block,
- // we need to declare the variable in this block
- return false;
- }
- // If we can move the variable into the sub-block, we need to ensure that the remaining code
- // does not use the value that was assigned by the first sub-block
- Statement nextStatement = stmt.GetNextStatement();
- if (nextStatement != null) {
- // Analyze the range from the next statement to the end of the block
- daa.SetAnalyzedRange(nextStatement, block);
- daa.Analyze(variableName);
- if (daa.UnassignedVariableUses.Count > 0) {
- return false;
- }
- }
- }
- }
- return true;
- }
-
- static bool CanMoveVariableUseIntoSubBlock(Statement stmt, string variableName, bool allowPassIntoLoops)
- {
- if (!allowPassIntoLoops && (stmt is ForStatement || stmt is ForeachStatement || stmt is DoWhileStatement || stmt is WhileStatement))
- return false;
-
- ForStatement forStatement = stmt as ForStatement;
- if (forStatement != null && forStatement.Initializers.Count == 1) {
- // for-statement is special case: we can move variable declarations into the initializer
- ExpressionStatement es = forStatement.Initializers.Single() as ExpressionStatement;
- if (es != null) {
- AssignmentExpression ae = es.Expression as AssignmentExpression;
- if (ae != null && ae.Operator == AssignmentOperatorType.Assign) {
- IdentifierExpression ident = ae.Left as IdentifierExpression;
- if (ident != null && ident.Identifier == variableName) {
- return !UsesVariable(ae.Right, variableName);
- }
- }
- }
- }
-
- UsingStatement usingStatement = stmt as UsingStatement;
- if (usingStatement != null) {
- // using-statement is special case: we can move variable declarations into the initializer
- AssignmentExpression ae = usingStatement.ResourceAcquisition as AssignmentExpression;
- if (ae != null && ae.Operator == AssignmentOperatorType.Assign) {
- IdentifierExpression ident = ae.Left as IdentifierExpression;
- if (ident != null && ident.Identifier == variableName) {
- return !UsesVariable(ae.Right, variableName);
- }
- }
- }
-
- IfElseStatement ies = stmt as IfElseStatement;
- if (ies != null) {
- foreach (var child in IfElseChainChildren(ies)) {
- if (!(child is BlockStatement) && UsesVariable(child, variableName))
- return false;
- }
- return true;
- }
-
- // We can move the variable into a sub-block only if the variable is used in only that sub-block (and not in expressions such as the loop condition)
- for (AstNode child = stmt.FirstChild; child != null; child = child.NextSibling) {
- if (!(child is BlockStatement) && UsesVariable(child, variableName)) {
- if (HasNestedBlocks(child)) {
- // catch clauses/switch sections can contain nested blocks
- for (AstNode grandchild = child.FirstChild; grandchild != null; grandchild = grandchild.NextSibling) {
- if (!(grandchild is BlockStatement) && UsesVariable(grandchild, variableName))
- return false;
- }
- } else {
- return false;
- }
- }
- }
- return true;
- }
-
- static IEnumerable<AstNode> IfElseChainChildren(IfElseStatement ies)
- {
- IfElseStatement prev;
- do {
- yield return ies.Condition;
- yield return ies.TrueStatement;
- prev = ies;
- ies = ies.FalseStatement as IfElseStatement;
- } while (ies != null);
- if (!prev.FalseStatement.IsNull)
- yield return prev.FalseStatement;
- }
-
- static bool HasNestedBlocks(AstNode node)
- {
- return node is CatchClause || node is SwitchSection;
- }
-
- static bool UsesVariable(AstNode node, string variableName)
- {
- IdentifierExpression ie = node as IdentifierExpression;
- if (ie != null && ie.Identifier == variableName)
- return true;
-
- FixedStatement fixedStatement = node as FixedStatement;
- if (fixedStatement != null) {
- foreach (VariableInitializer v in fixedStatement.Variables) {
- if (v.Name == variableName)
- return false; // no need to introduce the variable here
- }
- }
-
- ForeachStatement foreachStatement = node as ForeachStatement;
- if (foreachStatement != null) {
- if (foreachStatement.VariableName == variableName)
- return false; // no need to introduce the variable here
- }
-
- UsingStatement usingStatement = node as UsingStatement;
- if (usingStatement != null) {
- VariableDeclarationStatement varDecl = usingStatement.ResourceAcquisition as VariableDeclarationStatement;
- if (varDecl != null) {
- foreach (VariableInitializer v in varDecl.Variables) {
- if (v.Name == variableName)
- return false; // no need to introduce the variable here
- }
- }
- }
-
- CatchClause catchClause = node as CatchClause;
- if (catchClause != null && catchClause.VariableName == variableName) {
- return false; // no need to introduce the variable here
- }
-
- for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
- if (UsesVariable(child, variableName))
- return true;
- }
- return false;
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs b/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
deleted file mode 100644
index 04b2293d..00000000
--- a/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
+++ /dev/null
@@ -1,502 +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.Diagnostics;
-using System.Linq;
-using System.Threading;
-using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.ILAst;
-using ICSharpCode.NRefactory.CSharp;
-using ICSharpCode.NRefactory.PatternMatching;
-using Mono.Cecil;
-
-namespace ICSharpCode.Decompiler.Ast.Transforms
-{
- /// <summary>
- /// Converts "new Action(obj, ldftn(func))" into "new Action(obj.func)".
- /// For anonymous methods, creates an AnonymousMethodExpression.
- /// Also gets rid of any "Display Classes" left over after inlining an anonymous method.
- /// </summary>
- public class DelegateConstruction : ContextTrackingVisitor<object>
- {
- internal sealed class Annotation
- {
- /// <summary>
- /// ldftn or ldvirtftn?
- /// </summary>
- public readonly bool IsVirtual;
-
- public Annotation(bool isVirtual)
- {
- IsVirtual = isVirtual;
- }
- }
-
- internal sealed class CapturedVariableAnnotation
- {
- }
-
- List<string> currentlyUsedVariableNames = new List<string>();
-
- public DelegateConstruction(DecompilerContext context) : base(context)
- {
- }
-
- public override object VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data)
- {
- if (objectCreateExpression.Arguments.Count == 2) {
- Expression obj = objectCreateExpression.Arguments.First();
- Expression func = objectCreateExpression.Arguments.Last();
- Annotation annotation = func.Annotation<Annotation>();
- if (annotation != null) {
- IdentifierExpression methodIdent = (IdentifierExpression)((InvocationExpression)func).Arguments.Single();
- MethodReference method = methodIdent.Annotation<MethodReference>();
- if (method != null) {
- if (HandleAnonymousMethod(objectCreateExpression, obj, method))
- return null;
- // Perform the transformation to "new Action(obj.func)".
- obj.Remove();
- methodIdent.Remove();
- if (!annotation.IsVirtual && obj is ThisReferenceExpression) {
- // maybe it's getting the pointer of a base method?
- if (method.DeclaringType.GetElementType() != context.CurrentType) {
- obj = new BaseReferenceExpression();
- }
- }
- if (!annotation.IsVirtual && obj is NullReferenceExpression && !method.HasThis) {
- // We're loading a static method.
- // However it is possible to load extension methods with an instance, so we compare the number of arguments:
- bool isExtensionMethod = false;
- TypeReference delegateType = objectCreateExpression.Type.Annotation<TypeReference>();
- if (delegateType != null) {
- TypeDefinition delegateTypeDef = delegateType.Resolve();
- if (delegateTypeDef != null) {
- MethodDefinition invokeMethod = delegateTypeDef.Methods.FirstOrDefault(m => m.Name == "Invoke");
- if (invokeMethod != null) {
- isExtensionMethod = (invokeMethod.Parameters.Count + 1 == method.Parameters.Count);
- }
- }
- }
- if (!isExtensionMethod) {
- obj = new TypeReferenceExpression { Type = AstBuilder.ConvertType(method.DeclaringType) };
- }
- }
- // now transform the identifier into a member reference
- MemberReferenceExpression mre = new MemberReferenceExpression();
- mre.Target = obj;
- mre.MemberName = methodIdent.Identifier;
- methodIdent.TypeArguments.MoveTo(mre.TypeArguments);
- mre.AddAnnotation(method);
- objectCreateExpression.Arguments.Clear();
- objectCreateExpression.Arguments.Add(mre);
- return null;
- }
- }
- }
- return base.VisitObjectCreateExpression(objectCreateExpression, data);
- }
-
- internal static bool IsAnonymousMethod(DecompilerContext context, MethodDefinition method)
- {
- if (method == null || !(method.HasGeneratedName() || method.Name.Contains("$")))
- return false;
- if (!(method.IsCompilerGenerated() || IsPotentialClosure(context, method.DeclaringType)))
- return false;
- return true;
- }
-
- bool HandleAnonymousMethod(ObjectCreateExpression objectCreateExpression, Expression target, MethodReference methodRef)
- {
- if (!context.Settings.AnonymousMethods)
- return false; // anonymous method decompilation is disabled
- if (target != null && !(target is IdentifierExpression || target is ThisReferenceExpression || target is NullReferenceExpression))
- return false; // don't copy arbitrary expressions, deal with identifiers only
-
- // Anonymous methods are defined in the same assembly
- MethodDefinition method = methodRef.ResolveWithinSameModule();
- if (!IsAnonymousMethod(context, method))
- return false;
-
- // Create AnonymousMethodExpression and prepare parameters
- AnonymousMethodExpression ame = new AnonymousMethodExpression();
- ame.CopyAnnotationsFrom(objectCreateExpression); // copy ILRanges etc.
- ame.RemoveAnnotations<MethodReference>(); // remove reference to delegate ctor
- ame.AddAnnotation(method); // add reference to anonymous method
- ame.Parameters.AddRange(AstBuilder.MakeParameters(method, isLambda: true));
- ame.HasParameterList = true;
-
- // rename variables so that they don't conflict with the parameters:
- foreach (ParameterDeclaration pd in ame.Parameters) {
- EnsureVariableNameIsAvailable(objectCreateExpression, pd.Name);
- }
-
- // Decompile the anonymous method:
-
- DecompilerContext subContext = context.Clone();
- subContext.CurrentMethod = method;
- subContext.CurrentMethodIsAsync = false;
- subContext.ReservedVariableNames.AddRange(currentlyUsedVariableNames);
- BlockStatement body = AstMethodBodyBuilder.CreateMethodBody(method, subContext, ame.Parameters);
- TransformationPipeline.RunTransformationsUntil(body, v => v is DelegateConstruction, subContext);
- body.AcceptVisitor(this, null);
-
-
- bool isLambda = false;
- if (ame.Parameters.All(p => p.ParameterModifier == ParameterModifier.None)) {
- isLambda = (body.Statements.Count == 1 && body.Statements.Single() is ReturnStatement);
- }
- // Remove the parameter list from an AnonymousMethodExpression if the original method had no names,
- // and the parameters are not used in the method body
- if (!isLambda && method.Parameters.All(p => string.IsNullOrEmpty(p.Name))) {
- var parameterReferencingIdentifiers =
- from ident in body.Descendants.OfType<IdentifierExpression>()
- let v = ident.Annotation<ILVariable>()
- where v != null && v.IsParameter && method.Parameters.Contains(v.OriginalParameter)
- select ident;
- if (!parameterReferencingIdentifiers.Any()) {
- ame.Parameters.Clear();
- ame.HasParameterList = false;
- }
- }
-
- // Replace all occurrences of 'this' in the method body with the delegate's target:
- foreach (AstNode node in body.Descendants) {
- if (node is ThisReferenceExpression)
- node.ReplaceWith(target.Clone());
- }
- Expression replacement;
- if (isLambda) {
- LambdaExpression lambda = new LambdaExpression();
- lambda.CopyAnnotationsFrom(ame);
- ame.Parameters.MoveTo(lambda.Parameters);
- Expression returnExpr = ((ReturnStatement)body.Statements.Single()).Expression;
- returnExpr.Remove();
- lambda.Body = returnExpr;
- replacement = lambda;
- } else {
- ame.Body = body;
- replacement = ame;
- }
- var expectedType = objectCreateExpression.Annotation<TypeInformation>().ExpectedType.Resolve();
- if (expectedType != null && !expectedType.IsDelegate()) {
- var simplifiedDelegateCreation = (ObjectCreateExpression)objectCreateExpression.Clone();
- simplifiedDelegateCreation.Arguments.Clear();
- simplifiedDelegateCreation.Arguments.Add(replacement);
- replacement = simplifiedDelegateCreation;
- }
- objectCreateExpression.ReplaceWith(replacement);
- return true;
- }
-
- internal static bool IsPotentialClosure(DecompilerContext context, TypeDefinition potentialDisplayClass)
- {
- if (potentialDisplayClass == null || !potentialDisplayClass.IsCompilerGeneratedOrIsInCompilerGeneratedClass())
- return false;
- // check that methodContainingType is within containingType
- while (potentialDisplayClass != context.CurrentType) {
- potentialDisplayClass = potentialDisplayClass.DeclaringType;
- if (potentialDisplayClass == null)
- return false;
- }
- return true;
- }
-
- public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data)
- {
- if (context.Settings.ExpressionTrees && ExpressionTreeConverter.CouldBeExpressionTree(invocationExpression)) {
- Expression converted = ExpressionTreeConverter.TryConvert(context, invocationExpression);
- if (converted != null) {
- invocationExpression.ReplaceWith(converted);
- return converted.AcceptVisitor(this, data);
- }
- }
- return base.VisitInvocationExpression(invocationExpression, data);
- }
-
- #region Track current variables
- public override object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data)
- {
- Debug.Assert(currentlyUsedVariableNames.Count == 0);
- try {
- currentlyUsedVariableNames.AddRange(methodDeclaration.Parameters.Select(p => p.Name));
- return base.VisitMethodDeclaration(methodDeclaration, data);
- } finally {
- currentlyUsedVariableNames.Clear();
- }
- }
-
- public override object VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data)
- {
- Debug.Assert(currentlyUsedVariableNames.Count == 0);
- try {
- currentlyUsedVariableNames.AddRange(operatorDeclaration.Parameters.Select(p => p.Name));
- return base.VisitOperatorDeclaration(operatorDeclaration, data);
- } finally {
- currentlyUsedVariableNames.Clear();
- }
- }
-
- public override object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data)
- {
- Debug.Assert(currentlyUsedVariableNames.Count == 0);
- try {
- currentlyUsedVariableNames.AddRange(constructorDeclaration.Parameters.Select(p => p.Name));
- return base.VisitConstructorDeclaration(constructorDeclaration, data);
- } finally {
- currentlyUsedVariableNames.Clear();
- }
- }
-
- public override object VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration, object data)
- {
- Debug.Assert(currentlyUsedVariableNames.Count == 0);
- try {
- currentlyUsedVariableNames.AddRange(indexerDeclaration.Parameters.Select(p => p.Name));
- return base.VisitIndexerDeclaration(indexerDeclaration, data);
- } finally {
- currentlyUsedVariableNames.Clear();
- }
- }
-
- public override object VisitAccessor(Accessor accessor, object data)
- {
- try {
- currentlyUsedVariableNames.Add("value");
- return base.VisitAccessor(accessor, data);
- } finally {
- currentlyUsedVariableNames.RemoveAt(currentlyUsedVariableNames.Count - 1);
- }
- }
-
- public override object VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement, object data)
- {
- foreach (VariableInitializer v in variableDeclarationStatement.Variables)
- currentlyUsedVariableNames.Add(v.Name);
- return base.VisitVariableDeclarationStatement(variableDeclarationStatement, data);
- }
-
- public override object VisitFixedStatement(FixedStatement fixedStatement, object data)
- {
- foreach (VariableInitializer v in fixedStatement.Variables)
- currentlyUsedVariableNames.Add(v.Name);
- return base.VisitFixedStatement(fixedStatement, data);
- }
- #endregion
-
- static readonly ExpressionStatement displayClassAssignmentPattern =
- new ExpressionStatement(new AssignmentExpression(
- new NamedNode("variable", new IdentifierExpression(Pattern.AnyString)),
- new ObjectCreateExpression { Type = new AnyNode("type") }
- ));
-
- public override object VisitBlockStatement(BlockStatement blockStatement, object data)
- {
- int numberOfVariablesOutsideBlock = currentlyUsedVariableNames.Count;
- base.VisitBlockStatement(blockStatement, data);
- foreach (ExpressionStatement stmt in blockStatement.Statements.OfType<ExpressionStatement>().ToArray()) {
- Match displayClassAssignmentMatch = displayClassAssignmentPattern.Match(stmt);
- if (!displayClassAssignmentMatch.Success)
- continue;
-
- ILVariable variable = displayClassAssignmentMatch.Get<AstNode>("variable").Single().Annotation<ILVariable>();
- if (variable == null)
- continue;
- TypeDefinition type = variable.Type.ResolveWithinSameModule();
- if (!IsPotentialClosure(context, type))
- continue;
- if (displayClassAssignmentMatch.Get<AstType>("type").Single().Annotation<TypeReference>().ResolveWithinSameModule() != type)
- continue;
-
- // Looks like we found a display class creation. Now let's verify that the variable is used only for field accesses:
- bool ok = true;
- foreach (var identExpr in blockStatement.Descendants.OfType<IdentifierExpression>()) {
- if (identExpr.Identifier == variable.Name && identExpr != displayClassAssignmentMatch.Get("variable").Single()) {
- if (!(identExpr.Parent is MemberReferenceExpression && identExpr.Parent.Annotation<FieldReference>() != null))
- ok = false;
- }
- }
- if (!ok)
- continue;
- Dictionary<FieldReference, AstNode> dict = new Dictionary<FieldReference, AstNode>();
-
- // Delete the variable declaration statement:
- VariableDeclarationStatement displayClassVarDecl = PatternStatementTransform.FindVariableDeclaration(stmt, variable.Name);
- if (displayClassVarDecl != null)
- displayClassVarDecl.Remove();
-
- // Delete the assignment statement:
- AstNode cur = stmt.NextSibling;
- stmt.Remove();
-
- // Delete any following statements as long as they assign parameters to the display class
- BlockStatement rootBlock = blockStatement.Ancestors.OfType<BlockStatement>().LastOrDefault() ?? blockStatement;
- List<ILVariable> parameterOccurrances = rootBlock.Descendants.OfType<IdentifierExpression>()
- .Select(n => n.Annotation<ILVariable>()).Where(p => p != null && p.IsParameter).ToList();
- AstNode next;
- for (; cur != null; cur = next) {
- next = cur.NextSibling;
-
- // Test for the pattern:
- // "variableName.MemberName = right;"
- ExpressionStatement closureFieldAssignmentPattern = new ExpressionStatement(
- new AssignmentExpression(
- new NamedNode("left", new MemberReferenceExpression {
- Target = new IdentifierExpression(variable.Name),
- MemberName = Pattern.AnyString
- }),
- new AnyNode("right")
- )
- );
- Match m = closureFieldAssignmentPattern.Match(cur);
- if (m.Success) {
- FieldDefinition fieldDef = m.Get<MemberReferenceExpression>("left").Single().Annotation<FieldReference>().ResolveWithinSameModule();
- AstNode right = m.Get<AstNode>("right").Single();
- bool isParameter = false;
- bool isDisplayClassParentPointerAssignment = false;
- if (right is ThisReferenceExpression) {
- isParameter = true;
- } else if (right is IdentifierExpression) {
- // handle parameters only if the whole method contains no other occurrence except for 'right'
- ILVariable v = right.Annotation<ILVariable>();
- isParameter = v.IsParameter && parameterOccurrances.Count(c => c == v) == 1;
- if (!isParameter && IsPotentialClosure(context, v.Type.ResolveWithinSameModule())) {
- // parent display class within the same method
- // (closure2.localsX = closure1;)
- isDisplayClassParentPointerAssignment = true;
- }
- } else if (right is MemberReferenceExpression) {
- // copy of parent display class reference from an outer lambda
- // closure2.localsX = this.localsY
- MemberReferenceExpression mre = m.Get<MemberReferenceExpression>("right").Single();
- do {
- // descend into the targets of the mre as long as the field types are closures
- FieldDefinition fieldDef2 = mre.Annotation<FieldReference>().ResolveWithinSameModule();
- if (fieldDef2 == null || !IsPotentialClosure(context, fieldDef2.FieldType.ResolveWithinSameModule())) {
- break;
- }
- // if we finally get to a this reference, it's copying a display class parent pointer
- if (mre.Target is ThisReferenceExpression) {
- isDisplayClassParentPointerAssignment = true;
- }
- mre = mre.Target as MemberReferenceExpression;
- } while (mre != null);
- }
- if (isParameter || isDisplayClassParentPointerAssignment) {
- dict[fieldDef] = right;
- cur.Remove();
- } else {
- break;
- }
- } else {
- break;
- }
- }
-
- // Now create variables for all fields of the display class (except for those that we already handled as parameters)
- List<Tuple<AstType, ILVariable>> variablesToDeclare = new List<Tuple<AstType, ILVariable>>();
- foreach (FieldDefinition field in type.Fields) {
- if (field.IsStatic)
- continue; // skip static fields
- if (dict.ContainsKey(field)) // skip field if it already was handled as parameter
- continue;
- string capturedVariableName = field.Name;
- if (capturedVariableName.StartsWith("$VB$Local_", StringComparison.Ordinal) && capturedVariableName.Length > 10)
- capturedVariableName = capturedVariableName.Substring(10);
- EnsureVariableNameIsAvailable(blockStatement, capturedVariableName);
- currentlyUsedVariableNames.Add(capturedVariableName);
- ILVariable ilVar = new ILVariable
- {
- IsGenerated = true,
- Name = capturedVariableName,
- Type = field.FieldType,
- };
- variablesToDeclare.Add(Tuple.Create(AstBuilder.ConvertType(field.FieldType, field), ilVar));
- dict[field] = new IdentifierExpression(capturedVariableName).WithAnnotation(ilVar);
- }
-
- // Now figure out where the closure was accessed and use the simpler replacement expression there:
- foreach (var identExpr in blockStatement.Descendants.OfType<IdentifierExpression>()) {
- if (identExpr.Identifier == variable.Name) {
- MemberReferenceExpression mre = (MemberReferenceExpression)identExpr.Parent;
- AstNode replacement;
- if (dict.TryGetValue(mre.Annotation<FieldReference>().ResolveWithinSameModule(), out replacement)) {
- mre.ReplaceWith(replacement.Clone());
- }
- }
- }
- // Now insert the variable declarations (we can do this after the replacements only so that the scope detection works):
- Statement insertionPoint = blockStatement.Statements.FirstOrDefault();
- foreach (var tuple in variablesToDeclare) {
- var newVarDecl = new VariableDeclarationStatement(tuple.Item1, tuple.Item2.Name);
- newVarDecl.Variables.Single().AddAnnotation(new CapturedVariableAnnotation());
- newVarDecl.Variables.Single().AddAnnotation(tuple.Item2);
- blockStatement.Statements.InsertBefore(insertionPoint, newVarDecl);
- }
- }
- currentlyUsedVariableNames.RemoveRange(numberOfVariablesOutsideBlock, currentlyUsedVariableNames.Count - numberOfVariablesOutsideBlock);
- return null;
- }
-
- void EnsureVariableNameIsAvailable(AstNode currentNode, string name)
- {
- int pos = currentlyUsedVariableNames.IndexOf(name);
- if (pos < 0) {
- // name is still available
- return;
- }
- // Naming conflict. Let's rename the existing variable so that the field keeps the name from metadata.
- NameVariables nv = new NameVariables();
- // Add currently used variable and parameter names
- foreach (string nameInUse in currentlyUsedVariableNames)
- nv.AddExistingName(nameInUse);
- // variables declared in child nodes of this block
- foreach (VariableInitializer vi in currentNode.Descendants.OfType<VariableInitializer>())
- nv.AddExistingName(vi.Name);
- // parameters in child lambdas
- foreach (ParameterDeclaration pd in currentNode.Descendants.OfType<ParameterDeclaration>())
- nv.AddExistingName(pd.Name);
-
- string newName = nv.GetAlternativeName(name);
- currentlyUsedVariableNames[pos] = newName;
-
- // find top-most block
- AstNode topMostBlock = currentNode.Ancestors.OfType<BlockStatement>().LastOrDefault() ?? currentNode;
-
- // rename identifiers
- foreach (IdentifierExpression ident in topMostBlock.Descendants.OfType<IdentifierExpression>()) {
- if (ident.Identifier == name) {
- ident.Identifier = newName;
- ILVariable v = ident.Annotation<ILVariable>();
- if (v != null)
- v.Name = newName;
- }
- }
- // rename variable declarations
- foreach (VariableInitializer vi in topMostBlock.Descendants.OfType<VariableInitializer>()) {
- if (vi.Name == name) {
- vi.Name = newName;
- ILVariable v = vi.Annotation<ILVariable>();
- if (v != null)
- v.Name = newName;
- }
- }
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/ExpressionTreeConverter.cs b/ICSharpCode.Decompiler/Ast/Transforms/ExpressionTreeConverter.cs
deleted file mode 100644
index 2327200d..00000000
--- a/ICSharpCode.Decompiler/Ast/Transforms/ExpressionTreeConverter.cs
+++ /dev/null
@@ -1,875 +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.Diagnostics;
-using System.Linq;
-using System.Reflection;
-using ICSharpCode.Decompiler.ILAst;
-using ICSharpCode.NRefactory.CSharp;
-using ICSharpCode.NRefactory.PatternMatching;
-using Mono.Cecil;
-
-namespace ICSharpCode.Decompiler.Ast.Transforms
-{
- public class ExpressionTreeConverter
- {
- #region static TryConvert method
- public static bool CouldBeExpressionTree(InvocationExpression expr)
- {
- if (expr != null && expr.Arguments.Count == 2) {
- MethodReference mr = expr.Annotation<MethodReference>();
- return mr != null && mr.Name == "Lambda" && mr.DeclaringType.FullName == "System.Linq.Expressions.Expression";
- }
- return false;
- }
-
- public static Expression TryConvert(DecompilerContext context, Expression expr)
- {
- Expression converted = new ExpressionTreeConverter(context).Convert(expr);
- if (converted != null) {
- converted.AddAnnotation(new ExpressionTreeLambdaAnnotation());
- }
- return converted;
- }
- #endregion
-
- readonly DecompilerContext context;
- Stack<LambdaExpression> activeLambdas = new Stack<LambdaExpression>();
-
- ExpressionTreeConverter(DecompilerContext context)
- {
- this.context = context;
- }
-
- #region Main Convert method
- Expression Convert(Expression expr)
- {
- InvocationExpression invocation = expr as InvocationExpression;
- if (invocation != null) {
- MethodReference mr = invocation.Annotation<MethodReference>();
- if (mr != null && mr.DeclaringType.FullName == "System.Linq.Expressions.Expression") {
- switch (mr.Name) {
- case "Add":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.Add, false);
- case "AddChecked":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.Add, true);
- case "AddAssign":
- return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Add, false);
- case "AddAssignChecked":
- return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Add, true);
- case "And":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.BitwiseAnd);
- case "AndAlso":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.ConditionalAnd);
- case "AndAssign":
- return ConvertAssignmentOperator(invocation, AssignmentOperatorType.BitwiseAnd);
- case "ArrayAccess":
- case "ArrayIndex":
- return ConvertArrayIndex(invocation);
- case "ArrayLength":
- return ConvertArrayLength(invocation);
- case "Assign":
- return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Assign);
- case "Call":
- return ConvertCall(invocation);
- case "Coalesce":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.NullCoalescing);
- case "Condition":
- return ConvertCondition(invocation);
- case "Constant":
- if (invocation.Arguments.Count >= 1)
- return invocation.Arguments.First().Clone();
- else
- return NotSupported(expr);
- case "Convert":
- return ConvertCast(invocation, false);
- case "ConvertChecked":
- return ConvertCast(invocation, true);
- case "Divide":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.Divide);
- case "DivideAssign":
- return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Divide);
- case "Equal":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.Equality);
- case "ExclusiveOr":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.ExclusiveOr);
- case "ExclusiveOrAssign":
- return ConvertAssignmentOperator(invocation, AssignmentOperatorType.ExclusiveOr);
- case "Field":
- return ConvertField(invocation);
- case "GreaterThan":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.GreaterThan);
- case "GreaterThanOrEqual":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.GreaterThanOrEqual);
- case "Invoke":
- return ConvertInvoke(invocation);
- case "Lambda":
- return ConvertLambda(invocation);
- case "LeftShift":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.ShiftLeft);
- case "LeftShiftAssign":
- return ConvertAssignmentOperator(invocation, AssignmentOperatorType.ShiftLeft);
- case "LessThan":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.LessThan);
- case "LessThanOrEqual":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.LessThanOrEqual);
- case "ListInit":
- return ConvertListInit(invocation);
- case "MemberInit":
- return ConvertMemberInit(invocation);
- case "Modulo":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.Modulus);
- case "ModuloAssign":
- return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Modulus);
- case "Multiply":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.Multiply, false);
- case "MultiplyChecked":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.Multiply, true);
- case "MultiplyAssign":
- return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Multiply, false);
- case "MultiplyAssignChecked":
- return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Multiply, true);
- case "Negate":
- return ConvertUnaryOperator(invocation, UnaryOperatorType.Minus, false);
- case "NegateChecked":
- return ConvertUnaryOperator(invocation, UnaryOperatorType.Minus, true);
- case "New":
- return ConvertNewObject(invocation);
- case "NewArrayBounds":
- return ConvertNewArrayBounds(invocation);
- case "NewArrayInit":
- return ConvertNewArrayInit(invocation);
- case "Not":
- return ConvertUnaryOperator(invocation, UnaryOperatorType.Not);
- case "NotEqual":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.InEquality);
- case "OnesComplement":
- return ConvertUnaryOperator(invocation, UnaryOperatorType.BitNot);
- case "Or":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.BitwiseOr);
- case "OrAssign":
- return ConvertAssignmentOperator(invocation, AssignmentOperatorType.BitwiseOr);
- case "OrElse":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.ConditionalOr);
- case "Property":
- return ConvertProperty(invocation);
- case "Quote":
- if (invocation.Arguments.Count == 1)
- return Convert(invocation.Arguments.Single());
- else
- return NotSupported(invocation);
- case "RightShift":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.ShiftRight);
- case "RightShiftAssign":
- return ConvertAssignmentOperator(invocation, AssignmentOperatorType.ShiftRight);
- case "Subtract":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.Subtract, false);
- case "SubtractChecked":
- return ConvertBinaryOperator(invocation, BinaryOperatorType.Subtract, true);
- case "SubtractAssign":
- return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Subtract, false);
- case "SubtractAssignChecked":
- return ConvertAssignmentOperator(invocation, AssignmentOperatorType.Subtract, true);
- case "TypeAs":
- return ConvertTypeAs(invocation);
- case "TypeIs":
- return ConvertTypeIs(invocation);
- }
- }
- }
- IdentifierExpression ident = expr as IdentifierExpression;
- if (ident != null) {
- ILVariable v = ident.Annotation<ILVariable>();
- if (v != null) {
- foreach (LambdaExpression lambda in activeLambdas) {
- foreach (ParameterDeclaration p in lambda.Parameters) {
- if (p.Annotation<ILVariable>() == v)
- return new IdentifierExpression(p.Name).WithAnnotation(v);
- }
- }
- }
- }
- return NotSupported(expr);
- }
-
- Expression NotSupported(Expression expr)
- {
- Debug.WriteLine("Expression Tree Conversion Failed: '" + expr + "' is not supported");
- return null;
- }
- #endregion
-
- #region Convert Lambda
- static readonly Expression emptyArrayPattern = new ArrayCreateExpression {
- Type = new AnyNode(),
- Arguments = { new PrimitiveExpression(0) }
- };
-
- Expression ConvertLambda(InvocationExpression invocation)
- {
- if (invocation.Arguments.Count != 2)
- return NotSupported(invocation);
- LambdaExpression lambda = new LambdaExpression();
- Expression body = invocation.Arguments.First();
- ArrayCreateExpression parameterArray = invocation.Arguments.Last() as ArrayCreateExpression;
- if (parameterArray == null)
- return NotSupported(invocation);
-
- var annotation = body.Annotation<ParameterDeclarationAnnotation>();
- if (annotation != null) {
- lambda.Parameters.AddRange(annotation.Parameters);
- } else {
- // No parameter declaration annotation found.
- if (!emptyArrayPattern.IsMatch(parameterArray))
- return null;
- }
-
- activeLambdas.Push(lambda);
- Expression convertedBody = Convert(body);
- activeLambdas.Pop();
- if (convertedBody == null)
- return null;
- lambda.Body = convertedBody;
- return lambda;
- }
- #endregion
-
- #region Convert Field
- static readonly Expression getFieldFromHandlePattern =
- new TypePattern(typeof(FieldInfo)).ToType().Invoke(
- "GetFieldFromHandle",
- new LdTokenPattern("field").ToExpression().Member("FieldHandle"),
- new OptionalNode(new TypeOfExpression(new AnyNode("declaringType")).Member("TypeHandle"))
- );
-
- Expression ConvertField(InvocationExpression invocation)
- {
- if (invocation.Arguments.Count != 2)
- return NotSupported(invocation);
-
- Expression fieldInfoExpr = invocation.Arguments.ElementAt(1);
- Match m = getFieldFromHandlePattern.Match(fieldInfoExpr);
- if (!m.Success)
- return NotSupported(invocation);
-
- FieldReference fr = m.Get<AstNode>("field").Single().Annotation<FieldReference>();
- if (fr == null)
- return null;
-
- Expression target = invocation.Arguments.ElementAt(0);
- Expression convertedTarget;
- if (target is NullReferenceExpression) {
- if (m.Has("declaringType"))
- convertedTarget = new TypeReferenceExpression(m.Get<AstType>("declaringType").Single().Clone());
- else
- convertedTarget = new TypeReferenceExpression(AstBuilder.ConvertType(fr.DeclaringType));
- } else {
- convertedTarget = Convert(target);
- if (convertedTarget == null)
- return null;
- }
-
- return convertedTarget.Member(fr.Name).WithAnnotation(fr);
- }
- #endregion
-
- #region Convert Property
- static readonly Expression getMethodFromHandlePattern =
- new TypePattern(typeof(MethodBase)).ToType().Invoke(
- "GetMethodFromHandle",
- new LdTokenPattern("method").ToExpression().Member("MethodHandle"),
- new OptionalNode(new TypeOfExpression(new AnyNode("declaringType")).Member("TypeHandle"))
- ).CastTo(new TypePattern(typeof(MethodInfo)));
-
- Expression ConvertProperty(InvocationExpression invocation)
- {
- if (invocation.Arguments.Count != 2)
- return NotSupported(invocation);
-
- Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(1));
- if (!m.Success)
- return NotSupported(invocation);
-
- MethodReference mr = m.Get<AstNode>("method").Single().Annotation<MethodReference>();
- if (mr == null)
- return null;
-
- Expression target = invocation.Arguments.ElementAt(0);
- Expression convertedTarget;
- if (target is NullReferenceExpression) {
- if (m.Has("declaringType"))
- convertedTarget = new TypeReferenceExpression(m.Get<AstType>("declaringType").Single().Clone());
- else
- convertedTarget = new TypeReferenceExpression(AstBuilder.ConvertType(mr.DeclaringType));
- } else {
- convertedTarget = Convert(target);
- if (convertedTarget == null)
- return null;
- }
-
- return convertedTarget.Member(GetPropertyName(mr)).WithAnnotation(mr);
- }
-
- string GetPropertyName(MethodReference accessor)
- {
- string name = accessor.Name;
- if (name.StartsWith("get_", StringComparison.Ordinal) || name.StartsWith("set_", StringComparison.Ordinal))
- name = name.Substring(4);
- return name;
- }
- #endregion
-
- #region Convert Call
- Expression ConvertCall(InvocationExpression invocation)
- {
- if (invocation.Arguments.Count < 2)
- return NotSupported(invocation);
-
- Expression target;
- int firstArgumentPosition;
-
- Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(0));
- if (m.Success) {
- target = null;
- firstArgumentPosition = 1;
- } else {
- m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(1));
- if (!m.Success)
- return NotSupported(invocation);
- target = invocation.Arguments.ElementAt(0);
- firstArgumentPosition = 2;
- }
-
- MethodReference mr = m.Get<AstNode>("method").Single().Annotation<MethodReference>();
- if (mr == null)
- return null;
-
- Expression convertedTarget;
- if (target == null || target is NullReferenceExpression) {
- // static method
- if (m.Has("declaringType"))
- convertedTarget = new TypeReferenceExpression(m.Get<AstType>("declaringType").Single().Clone());
- else
- convertedTarget = new TypeReferenceExpression(AstBuilder.ConvertType(mr.DeclaringType));
- } else {
- convertedTarget = Convert(target);
- if (convertedTarget == null)
- return null;
- }
-
- MemberReferenceExpression mre = convertedTarget.Member(mr.Name);
- GenericInstanceMethod gim = mr as GenericInstanceMethod;
- if (gim != null) {
- foreach (TypeReference tr in gim.GenericArguments) {
- mre.TypeArguments.Add(AstBuilder.ConvertType(tr));
- }
- }
- IList<Expression> arguments = null;
- if (invocation.Arguments.Count == firstArgumentPosition + 1) {
- Expression argumentArray = invocation.Arguments.ElementAt(firstArgumentPosition);
- arguments = ConvertExpressionsArray(argumentArray);
- }
- if (arguments == null) {
- arguments = new List<Expression>();
- foreach (Expression argument in invocation.Arguments.Skip(firstArgumentPosition)) {
- Expression convertedArgument = Convert(argument);
- if (convertedArgument == null)
- return null;
- arguments.Add(convertedArgument);
- }
- }
- MethodDefinition methodDef = mr.Resolve();
- if (methodDef != null && methodDef.IsGetter) {
- PropertyDefinition indexer = AstMethodBodyBuilder.GetIndexer(methodDef);
- if (indexer != null)
- return new IndexerExpression(mre.Target.Detach(), arguments).WithAnnotation(indexer);
- }
- return new InvocationExpression(mre, arguments).WithAnnotation(mr);
- }
-
- Expression ConvertInvoke(InvocationExpression invocation)
- {
- if (invocation.Arguments.Count != 2)
- return NotSupported(invocation);
-
- Expression convertedTarget = Convert(invocation.Arguments.ElementAt(0));
- IList<Expression> convertedArguments = ConvertExpressionsArray(invocation.Arguments.ElementAt(1));
- if (convertedTarget != null && convertedArguments != null)
- return new InvocationExpression(convertedTarget, convertedArguments);
- else
- return null;
- }
- #endregion
-
- #region Convert Binary Operator
- static readonly Pattern trueOrFalse = new Choice {
- new PrimitiveExpression(true),
- new PrimitiveExpression(false)
- };
-
- Expression ConvertBinaryOperator(InvocationExpression invocation, BinaryOperatorType op, bool? isChecked = null)
- {
- if (invocation.Arguments.Count < 2)
- return NotSupported(invocation);
-
- Expression left = Convert(invocation.Arguments.ElementAt(0));
- if (left == null)
- return null;
- Expression right = Convert(invocation.Arguments.ElementAt(1));
- if (right == null)
- return null;
-
- BinaryOperatorExpression boe = new BinaryOperatorExpression(left, op, right);
- if (isChecked != null)
- boe.AddAnnotation(isChecked.Value ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation);
-
- switch (invocation.Arguments.Count) {
- case 2:
- return boe;
- case 3:
- Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(2));
- if (m.Success)
- return boe.WithAnnotation(m.Get<AstNode>("method").Single().Annotation<MethodReference>());
- else
- return null;
- case 4:
- if (!trueOrFalse.IsMatch(invocation.Arguments.ElementAt(2)))
- return null;
- m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(3));
- if (m.Success)
- return boe.WithAnnotation(m.Get<AstNode>("method").Single().Annotation<MethodReference>());
- else
- return null;
- default:
- return NotSupported(invocation);
- }
- }
- #endregion
-
- #region Convert Assignment Operator
- Expression ConvertAssignmentOperator(InvocationExpression invocation, AssignmentOperatorType op, bool? isChecked = null)
- {
- return NotSupported(invocation);
- }
- #endregion
-
- #region Convert Unary Operator
- Expression ConvertUnaryOperator(InvocationExpression invocation, UnaryOperatorType op, bool? isChecked = null)
- {
- if (invocation.Arguments.Count < 1)
- return NotSupported(invocation);
-
- Expression expr = Convert(invocation.Arguments.ElementAt(0));
- if (expr == null)
- return null;
-
- UnaryOperatorExpression uoe = new UnaryOperatorExpression(op, expr);
- if (isChecked != null)
- uoe.AddAnnotation(isChecked.Value ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation);
-
- switch (invocation.Arguments.Count) {
- case 1:
- return uoe;
- case 2:
- Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(1));
- if (m.Success)
- return uoe.WithAnnotation(m.Get<AstNode>("method").Single().Annotation<MethodReference>());
- else
- return null;
- default:
- return NotSupported(invocation);
- }
- }
- #endregion
-
- #region Convert Condition Operator
- Expression ConvertCondition(InvocationExpression invocation)
- {
- if (invocation.Arguments.Count != 3)
- return NotSupported(invocation);
-
- Expression condition = Convert(invocation.Arguments.ElementAt(0));
- Expression trueExpr = Convert(invocation.Arguments.ElementAt(1));
- Expression falseExpr = Convert(invocation.Arguments.ElementAt(2));
- if (condition != null && trueExpr != null && falseExpr != null)
- return new ConditionalExpression(condition, trueExpr, falseExpr);
- else
- return null;
- }
- #endregion
-
- #region Convert New Object
- static readonly Expression newObjectCtorPattern = new TypePattern(typeof(MethodBase)).ToType().Invoke
- (
- "GetMethodFromHandle",
- new LdTokenPattern("ctor").ToExpression().Member("MethodHandle"),
- new OptionalNode(new TypeOfExpression(new AnyNode("declaringType")).Member("TypeHandle"))
- ).CastTo(new TypePattern(typeof(ConstructorInfo)));
-
- Expression ConvertNewObject(InvocationExpression invocation)
- {
- if (invocation.Arguments.Count < 1 || invocation.Arguments.Count > 3)
- return NotSupported(invocation);
-
- Match m = newObjectCtorPattern.Match(invocation.Arguments.First());
- if (!m.Success)
- return NotSupported(invocation);
-
- MethodReference ctor = m.Get<AstNode>("ctor").Single().Annotation<MethodReference>();
- if (ctor == null)
- return null;
-
- AstType declaringTypeNode;
- TypeReference declaringType;
- if (m.Has("declaringType")) {
- declaringTypeNode = m.Get<AstType>("declaringType").Single().Clone();
- declaringType = declaringTypeNode.Annotation<TypeReference>();
- } else {
- declaringTypeNode = AstBuilder.ConvertType(ctor.DeclaringType);
- declaringType = ctor.DeclaringType;
- }
- if (declaringTypeNode == null)
- return null;
-
- ObjectCreateExpression oce = new ObjectCreateExpression(declaringTypeNode);
- if (invocation.Arguments.Count >= 2) {
- IList<Expression> arguments = ConvertExpressionsArray(invocation.Arguments.ElementAtOrDefault(1));
- if (arguments == null)
- return null;
- oce.Arguments.AddRange(arguments);
- }
- if (invocation.Arguments.Count >= 3 && declaringType.IsAnonymousType()) {
- MethodDefinition resolvedCtor = ctor.Resolve();
- if (resolvedCtor == null || resolvedCtor.Parameters.Count != oce.Arguments.Count)
- return null;
- AnonymousTypeCreateExpression atce = new AnonymousTypeCreateExpression();
- var arguments = oce.Arguments.ToArray();
- if (AstMethodBodyBuilder.CanInferAnonymousTypePropertyNamesFromArguments(arguments, resolvedCtor.Parameters)) {
- oce.Arguments.MoveTo(atce.Initializers);
- } else {
- for (int i = 0; i < resolvedCtor.Parameters.Count; i++) {
- atce.Initializers.Add(
- new NamedExpression {
- Name = resolvedCtor.Parameters[i].Name,
- Expression = arguments[i].Detach()
- });
- }
- }
- return atce;
- }
-
- return oce;
- }
- #endregion
-
- #region Convert ListInit
- static readonly Pattern elementInitArrayPattern = ArrayInitializationPattern(
- typeof(System.Linq.Expressions.ElementInit),
- new TypePattern(typeof(System.Linq.Expressions.Expression)).ToType().Invoke("ElementInit", new AnyNode("methodInfos"), new AnyNode("addArgumentsArrays"))
- );
-
- Expression ConvertListInit(InvocationExpression invocation)
- {
- if (invocation.Arguments.Count != 2)
- return NotSupported(invocation);
- ObjectCreateExpression oce = Convert(invocation.Arguments.ElementAt(0)) as ObjectCreateExpression;
- if (oce == null)
- return null;
- Expression elementsArray = invocation.Arguments.ElementAt(1);
- ArrayInitializerExpression initializer = ConvertElementInit(elementsArray);
- if (initializer != null) {
- oce.Initializer = initializer;
- return oce;
- } else {
- return null;
- }
- }
-
- ArrayInitializerExpression ConvertElementInit(Expression elementsArray)
- {
- IList<Expression> elements = ConvertExpressionsArray(elementsArray);
- if (elements != null) {
- return new ArrayInitializerExpression(elements);
- }
- Match m = elementInitArrayPattern.Match(elementsArray);
- if (!m.Success)
- return null;
- ArrayInitializerExpression result = new ArrayInitializerExpression();
- foreach (var elementInit in m.Get<Expression>("addArgumentsArrays")) {
- IList<Expression> arguments = ConvertExpressionsArray(elementInit);
- if (arguments == null)
- return null;
- result.Elements.Add(new ArrayInitializerExpression(arguments));
- }
- return result;
- }
- #endregion
-
- #region Convert MemberInit
- Expression ConvertMemberInit(InvocationExpression invocation)
- {
- if (invocation.Arguments.Count != 2)
- return NotSupported(invocation);
- ObjectCreateExpression oce = Convert(invocation.Arguments.ElementAt(0)) as ObjectCreateExpression;
- if (oce == null)
- return null;
- Expression elementsArray = invocation.Arguments.ElementAt(1);
- ArrayInitializerExpression bindings = ConvertMemberBindings(elementsArray);
- if (bindings == null)
- return null;
- oce.Initializer = bindings;
- return oce;
- }
-
- static readonly Pattern memberBindingArrayPattern = ArrayInitializationPattern(typeof(System.Linq.Expressions.MemberBinding), new AnyNode("binding"));
- static readonly INode expressionTypeReference = new TypeReferenceExpression(new TypePattern(typeof(System.Linq.Expressions.Expression)));
-
- ArrayInitializerExpression ConvertMemberBindings(Expression elementsArray)
- {
- Match m = memberBindingArrayPattern.Match(elementsArray);
- if (!m.Success)
- return null;
- ArrayInitializerExpression result = new ArrayInitializerExpression();
- foreach (var binding in m.Get<Expression>("binding")) {
- InvocationExpression bindingInvocation = binding as InvocationExpression;
- if (bindingInvocation == null || bindingInvocation.Arguments.Count != 2)
- return null;
- MemberReferenceExpression bindingMRE = bindingInvocation.Target as MemberReferenceExpression;
- if (bindingMRE == null || !expressionTypeReference.IsMatch(bindingMRE.Target))
- return null;
-
- Expression bindingTarget = bindingInvocation.Arguments.ElementAt(0);
- Expression bindingValue = bindingInvocation.Arguments.ElementAt(1);
-
- string memberName;
- Match m2 = getMethodFromHandlePattern.Match(bindingTarget);
- if (m2.Success) {
- MethodReference setter = m2.Get<AstNode>("method").Single().Annotation<MethodReference>();
- if (setter == null)
- return null;
- memberName = GetPropertyName(setter);
- } else {
- return null;
- }
-
- Expression convertedValue;
- switch (bindingMRE.MemberName) {
- case "Bind":
- convertedValue = Convert(bindingValue);
- break;
- case "MemberBind":
- convertedValue = ConvertMemberBindings(bindingValue);
- break;
- case "ListBind":
- convertedValue = ConvertElementInit(bindingValue);
- break;
- default:
- return null;
- }
- if (convertedValue == null)
- return null;
- result.Elements.Add(new NamedExpression(memberName, convertedValue));
- }
- return result;
- }
- #endregion
-
- #region Convert Cast
- Expression ConvertCast(InvocationExpression invocation, bool isChecked)
- {
- if (invocation.Arguments.Count < 2)
- return null;
- Expression converted = Convert(invocation.Arguments.ElementAt(0));
- AstType type = ConvertTypeReference(invocation.Arguments.ElementAt(1));
- if (converted != null && type != null) {
- CastExpression cast = converted.CastTo(type);
- cast.AddAnnotation(isChecked ? AddCheckedBlocks.CheckedAnnotation : AddCheckedBlocks.UncheckedAnnotation);
- switch (invocation.Arguments.Count) {
- case 2:
- return cast;
- case 3:
- Match m = getMethodFromHandlePattern.Match(invocation.Arguments.ElementAt(2));
- if (m.Success)
- return cast.WithAnnotation(m.Get<AstNode>("method").Single().Annotation<MethodReference>());
- else
- return null;
- }
- }
- return null;
- }
- #endregion
-
- #region ConvertExpressionsArray
- static Pattern ArrayInitializationPattern(Type arrayElementType, INode elementPattern)
- {
- return new Choice {
- new ArrayCreateExpression {
- Type = new TypePattern(arrayElementType),
- Arguments = { new PrimitiveExpression(0) }
- },
- new ArrayCreateExpression {
- Type = new TypePattern(arrayElementType),
- AdditionalArraySpecifiers = { new ArraySpecifier() },
- Initializer = new ArrayInitializerExpression {
- Elements = { new Repeat(elementPattern) }
- }
- }
- };
- }
-
- static readonly Pattern expressionArrayPattern = ArrayInitializationPattern(typeof(System.Linq.Expressions.Expression), new AnyNode("elements"));
-
- IList<Expression> ConvertExpressionsArray(Expression arrayExpression)
- {
- Match m = expressionArrayPattern.Match(arrayExpression);
- if (m.Success) {
- List<Expression> result = new List<Expression>();
- foreach (Expression expr in m.Get<Expression>("elements")) {
- Expression converted = Convert(expr);
- if (converted == null)
- return null;
- result.Add(converted);
- }
- return result;
- }
- return null;
- }
- #endregion
-
- #region Convert TypeAs/TypeIs
- static readonly TypeOfPattern typeOfPattern = new TypeOfPattern("type");
-
- AstType ConvertTypeReference(Expression typeOfExpression)
- {
- Match m = typeOfPattern.Match(typeOfExpression);
- if (m.Success)
- return m.Get<AstType>("type").Single().Clone();
- else
- return null;
- }
-
- Expression ConvertTypeAs(InvocationExpression invocation)
- {
- if (invocation.Arguments.Count != 2)
- return null;
- Expression converted = Convert(invocation.Arguments.ElementAt(0));
- AstType type = ConvertTypeReference(invocation.Arguments.ElementAt(1));
- if (converted != null && type != null)
- return new AsExpression(converted, type);
- return null;
- }
-
- Expression ConvertTypeIs(InvocationExpression invocation)
- {
- if (invocation.Arguments.Count != 2)
- return null;
- Expression converted = Convert(invocation.Arguments.ElementAt(0));
- AstType type = ConvertTypeReference(invocation.Arguments.ElementAt(1));
- if (converted != null && type != null)
- return new IsExpression { Expression = converted, Type = type };
- return null;
- }
- #endregion
-
- #region Convert Array
- Expression ConvertArrayIndex(InvocationExpression invocation)
- {
- if (invocation.Arguments.Count != 2)
- return NotSupported(invocation);
-
- Expression targetConverted = Convert(invocation.Arguments.First());
- if (targetConverted == null)
- return null;
-
- Expression index = invocation.Arguments.ElementAt(1);
- Expression indexConverted = Convert(index);
- if (indexConverted != null) {
- return new IndexerExpression(targetConverted, indexConverted);
- }
- IList<Expression> indexesConverted = ConvertExpressionsArray(index);
- if (indexesConverted != null) {
- return new IndexerExpression(targetConverted, indexesConverted);
- }
- return null;
- }
-
- Expression ConvertArrayLength(InvocationExpression invocation)
- {
- if (invocation.Arguments.Count != 1)
- return NotSupported(invocation);
-
- Expression targetConverted = Convert(invocation.Arguments.Single());
- if (targetConverted != null)
- return targetConverted.Member("Length");
- else
- return null;
- }
-
- Expression ConvertNewArrayInit(InvocationExpression invocation)
- {
- if (invocation.Arguments.Count != 2)
- return NotSupported(invocation);
-
- AstType elementType = ConvertTypeReference(invocation.Arguments.ElementAt(0));
- IList<Expression> elements = ConvertExpressionsArray(invocation.Arguments.ElementAt(1));
- if (elementType != null && elements != null) {
- if (ContainsAnonymousType(elementType)) {
- elementType = null;
- }
- return new ArrayCreateExpression {
- Type = elementType,
- AdditionalArraySpecifiers = { new ArraySpecifier() },
- Initializer = new ArrayInitializerExpression(elements)
- };
- }
- return null;
- }
-
- Expression ConvertNewArrayBounds(InvocationExpression invocation)
- {
- if (invocation.Arguments.Count != 2)
- return NotSupported(invocation);
-
- AstType elementType = ConvertTypeReference(invocation.Arguments.ElementAt(0));
- IList<Expression> arguments = ConvertExpressionsArray(invocation.Arguments.ElementAt(1));
- if (elementType != null && arguments != null) {
- if (ContainsAnonymousType(elementType)) {
- elementType = null;
- }
- ArrayCreateExpression ace = new ArrayCreateExpression();
- ace.Type = elementType;
- ace.Arguments.AddRange(arguments);
- return ace;
- }
- return null;
- }
-
- bool ContainsAnonymousType(AstType type)
- {
- foreach (AstType t in type.DescendantsAndSelf.OfType<AstType>()) {
- TypeReference tr = t.Annotation<TypeReference>();
- if (tr != null && tr.IsAnonymousType())
- return true;
- }
- return false;
- }
- #endregion
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/FlattenSwitchBlocks.cs b/ICSharpCode.Decompiler/Ast/Transforms/FlattenSwitchBlocks.cs
deleted file mode 100644
index 9595e81b..00000000
--- a/ICSharpCode.Decompiler/Ast/Transforms/FlattenSwitchBlocks.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using ICSharpCode.NRefactory.CSharp;
-
-namespace ICSharpCode.Decompiler.Ast.Transforms
-{
- internal class FlattenSwitchBlocks : IAstTransform
- {
- public void Run(AstNode compilationUnit)
- {
- foreach (var switchSection in compilationUnit.Descendants.OfType<SwitchSection>())
- {
- if (switchSection.Statements.Count != 1)
- continue;
-
- var blockStatement = switchSection.Statements.First() as BlockStatement;
- if (blockStatement == null || blockStatement.Statements.Any(st => st is VariableDeclarationStatement))
- continue;
-
- blockStatement.Remove();
- blockStatement.Statements.MoveTo(switchSection.Statements);
- }
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/IntroduceExtensionMethods.cs b/ICSharpCode.Decompiler/Ast/Transforms/IntroduceExtensionMethods.cs
deleted file mode 100644
index 9f05285e..00000000
--- a/ICSharpCode.Decompiler/Ast/Transforms/IntroduceExtensionMethods.cs
+++ /dev/null
@@ -1,66 +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 Mono.Cecil;
-
-namespace ICSharpCode.Decompiler.Ast.Transforms
-{
- /// <summary>
- /// Converts extension method calls into infix syntax.
- /// </summary>
- public class IntroduceExtensionMethods : IAstTransform
- {
- readonly DecompilerContext context;
-
- public IntroduceExtensionMethods(DecompilerContext context)
- {
- this.context = context;
- }
-
- public void Run(AstNode compilationUnit)
- {
- foreach (InvocationExpression invocation in compilationUnit.Descendants.OfType<InvocationExpression>()) {
- MemberReferenceExpression mre = invocation.Target as MemberReferenceExpression;
- MethodReference methodReference = invocation.Annotation<MethodReference>();
- if (mre != null && mre.Target is TypeReferenceExpression && methodReference != null && invocation.Arguments.Any()) {
- MethodDefinition d = methodReference.Resolve();
- if (d != null) {
- foreach (var ca in d.CustomAttributes) {
- if (ca.AttributeType.Name == "ExtensionAttribute" && ca.AttributeType.Namespace == "System.Runtime.CompilerServices") {
- var firstArgument = invocation.Arguments.First();
- if (firstArgument is NullReferenceExpression)
- firstArgument = firstArgument.ReplaceWith(expr => expr.CastTo(AstBuilder.ConvertType(d.Parameters.First().ParameterType)));
- else
- mre.Target = firstArgument.Detach();
- if (invocation.Arguments.Any()) {
- // HACK: removing type arguments should be done indepently from whether a method is an extension method,
- // just by testing whether the arguments can be inferred
- mre.TypeArguments.Clear();
- }
- break;
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/IntroduceQueryExpressions.cs b/ICSharpCode.Decompiler/Ast/Transforms/IntroduceQueryExpressions.cs
deleted file mode 100644
index 0da56fe9..00000000
--- a/ICSharpCode.Decompiler/Ast/Transforms/IntroduceQueryExpressions.cs
+++ /dev/null
@@ -1,295 +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.Diagnostics;
-using System.Linq;
-using ICSharpCode.NRefactory.CSharp;
-
-namespace ICSharpCode.Decompiler.Ast.Transforms
-{
- /// <summary>
- /// Decompiles query expressions.
- /// Based on C# 4.0 spec, §7.16.2 Query expression translation
- /// </summary>
- public class IntroduceQueryExpressions : IAstTransform
- {
- readonly DecompilerContext context;
-
- public IntroduceQueryExpressions(DecompilerContext context)
- {
- this.context = context;
- }
-
- public void Run(AstNode compilationUnit)
- {
- if (!context.Settings.QueryExpressions)
- return;
- DecompileQueries(compilationUnit);
- // After all queries were decompiled, detect degenerate queries (queries not property terminated with 'select' or 'group')
- // and fix them, either by adding a degenerate select, or by combining them with another query.
- foreach (QueryExpression query in compilationUnit.Descendants.OfType<QueryExpression>()) {
- QueryFromClause fromClause = (QueryFromClause)query.Clauses.First();
- if (IsDegenerateQuery(query)) {
- // introduce select for degenerate query
- query.Clauses.Add(new QuerySelectClause { Expression = new IdentifierExpression(fromClause.Identifier) });
- }
- // See if the data source of this query is a degenerate query,
- // and combine the queries if possible.
- QueryExpression innerQuery = fromClause.Expression as QueryExpression;
- while (IsDegenerateQuery(innerQuery)) {
- QueryFromClause innerFromClause = (QueryFromClause)innerQuery.Clauses.First();
- if (fromClause.Identifier != innerFromClause.Identifier)
- break;
- // Replace the fromClause with all clauses from the inner query
- fromClause.Remove();
- QueryClause insertionPos = null;
- foreach (var clause in innerQuery.Clauses) {
- query.Clauses.InsertAfter(insertionPos, insertionPos = clause.Detach());
- }
- fromClause = innerFromClause;
- innerQuery = fromClause.Expression as QueryExpression;
- }
- }
- }
-
- bool IsDegenerateQuery(QueryExpression query)
- {
- if (query == null)
- return false;
- var lastClause = query.Clauses.LastOrDefault();
- return !(lastClause is QuerySelectClause || lastClause is QueryGroupClause);
- }
-
- void DecompileQueries(AstNode node)
- {
- QueryExpression query = DecompileQuery(node as InvocationExpression);
- if (query != null)
- node.ReplaceWith(query);
- for (AstNode child = (query ?? node).FirstChild; child != null; child = child.NextSibling) {
- DecompileQueries(child);
- }
- }
-
- QueryExpression DecompileQuery(InvocationExpression invocation)
- {
- if (invocation == null)
- return null;
- MemberReferenceExpression mre = invocation.Target as MemberReferenceExpression;
- if (mre == null)
- return null;
- switch (mre.MemberName) {
- case "Select":
- {
- if (invocation.Arguments.Count != 1)
- return null;
- string parameterName;
- Expression body;
- if (MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out body)) {
- QueryExpression query = new QueryExpression();
- query.Clauses.Add(new QueryFromClause { Identifier = parameterName, Expression = mre.Target.Detach() });
- query.Clauses.Add(new QuerySelectClause { Expression = body.Detach() });
- return query;
- }
- return null;
- }
- case "GroupBy":
- {
- if (invocation.Arguments.Count == 2) {
- string parameterName1, parameterName2;
- Expression keySelector, elementSelector;
- if (MatchSimpleLambda(invocation.Arguments.ElementAt(0), out parameterName1, out keySelector)
- && MatchSimpleLambda(invocation.Arguments.ElementAt(1), out parameterName2, out elementSelector)
- && parameterName1 == parameterName2)
- {
- QueryExpression query = new QueryExpression();
- query.Clauses.Add(new QueryFromClause { Identifier = parameterName1, Expression = mre.Target.Detach() });
- query.Clauses.Add(new QueryGroupClause { Projection = elementSelector.Detach(), Key = keySelector.Detach() });
- return query;
- }
- } else if (invocation.Arguments.Count == 1) {
- string parameterName;
- Expression keySelector;
- if (MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out keySelector)) {
- QueryExpression query = new QueryExpression();
- query.Clauses.Add(new QueryFromClause { Identifier = parameterName, Expression = mre.Target.Detach() });
- query.Clauses.Add(new QueryGroupClause { Projection = new IdentifierExpression(parameterName), Key = keySelector.Detach() });
- return query;
- }
- }
- return null;
- }
- case "SelectMany":
- {
- if (invocation.Arguments.Count != 2)
- return null;
- string parameterName;
- Expression collectionSelector;
- if (!MatchSimpleLambda(invocation.Arguments.ElementAt(0), out parameterName, out collectionSelector))
- return null;
- LambdaExpression lambda = invocation.Arguments.ElementAt(1) as LambdaExpression;
- if (lambda != null && lambda.Parameters.Count == 2 && lambda.Body is Expression) {
- ParameterDeclaration p1 = lambda.Parameters.ElementAt(0);
- ParameterDeclaration p2 = lambda.Parameters.ElementAt(1);
- if (p1.Name == parameterName) {
- QueryExpression query = new QueryExpression();
- query.Clauses.Add(new QueryFromClause { Identifier = p1.Name, Expression = mre.Target.Detach() });
- query.Clauses.Add(new QueryFromClause { Identifier = p2.Name, Expression = collectionSelector.Detach() });
- query.Clauses.Add(new QuerySelectClause { Expression = ((Expression)lambda.Body).Detach() });
- return query;
- }
- }
- return null;
- }
- case "Where":
- {
- if (invocation.Arguments.Count != 1)
- return null;
- string parameterName;
- Expression body;
- if (MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out body)) {
- QueryExpression query = new QueryExpression();
- query.Clauses.Add(new QueryFromClause { Identifier = parameterName, Expression = mre.Target.Detach() });
- query.Clauses.Add(new QueryWhereClause { Condition = body.Detach() });
- return query;
- }
- return null;
- }
- case "OrderBy":
- case "OrderByDescending":
- case "ThenBy":
- case "ThenByDescending":
- {
- if (invocation.Arguments.Count != 1)
- return null;
- string parameterName;
- Expression orderExpression;
- if (MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out orderExpression)) {
- if (ValidateThenByChain(invocation, parameterName)) {
- QueryOrderClause orderClause = new QueryOrderClause();
- InvocationExpression tmp = invocation;
- while (mre.MemberName == "ThenBy" || mre.MemberName == "ThenByDescending") {
- // insert new ordering at beginning
- orderClause.Orderings.InsertAfter(
- null, new QueryOrdering {
- Expression = orderExpression.Detach(),
- Direction = (mre.MemberName == "ThenBy" ? QueryOrderingDirection.None : QueryOrderingDirection.Descending)
- });
-
- tmp = (InvocationExpression)mre.Target;
- mre = (MemberReferenceExpression)tmp.Target;
- MatchSimpleLambda(tmp.Arguments.Single(), out parameterName, out orderExpression);
- }
- // insert new ordering at beginning
- orderClause.Orderings.InsertAfter(
- null, new QueryOrdering {
- Expression = orderExpression.Detach(),
- Direction = (mre.MemberName == "OrderBy" ? QueryOrderingDirection.None : QueryOrderingDirection.Descending)
- });
-
- QueryExpression query = new QueryExpression();
- query.Clauses.Add(new QueryFromClause { Identifier = parameterName, Expression = mre.Target.Detach() });
- query.Clauses.Add(orderClause);
- return query;
- }
- }
- return null;
- }
- case "Join":
- case "GroupJoin":
- {
- if (invocation.Arguments.Count != 4)
- return null;
- Expression source1 = mre.Target;
- Expression source2 = invocation.Arguments.ElementAt(0);
- string elementName1, elementName2;
- Expression key1, key2;
- if (!MatchSimpleLambda(invocation.Arguments.ElementAt(1), out elementName1, out key1))
- return null;
- if (!MatchSimpleLambda(invocation.Arguments.ElementAt(2), out elementName2, out key2))
- return null;
- LambdaExpression lambda = invocation.Arguments.ElementAt(3) as LambdaExpression;
- if (lambda != null && lambda.Parameters.Count == 2 && lambda.Body is Expression) {
- ParameterDeclaration p1 = lambda.Parameters.ElementAt(0);
- ParameterDeclaration p2 = lambda.Parameters.ElementAt(1);
- if (p1.Name == elementName1 && (p2.Name == elementName2 || mre.MemberName == "GroupJoin")) {
- QueryExpression query = new QueryExpression();
- query.Clauses.Add(new QueryFromClause { Identifier = elementName1, Expression = source1.Detach() });
- QueryJoinClause joinClause = new QueryJoinClause();
- joinClause.JoinIdentifier = elementName2; // join elementName2
- joinClause.InExpression = source2.Detach(); // in source2
- joinClause.OnExpression = key1.Detach(); // on key1
- joinClause.EqualsExpression = key2.Detach(); // equals key2
- if (mre.MemberName == "GroupJoin") {
- joinClause.IntoIdentifier = p2.Name; // into p2.Name
- }
- query.Clauses.Add(joinClause);
- query.Clauses.Add(new QuerySelectClause { Expression = ((Expression)lambda.Body).Detach() });
- return query;
- }
- }
- return null;
- }
- default:
- return null;
- }
- }
-
- /// <summary>
- /// Ensure that all ThenBy's are correct, and that the list of ThenBy's is terminated by an 'OrderBy' invocation.
- /// </summary>
- bool ValidateThenByChain(InvocationExpression invocation, string expectedParameterName)
- {
- if (invocation == null || invocation.Arguments.Count != 1)
- return false;
- MemberReferenceExpression mre = invocation.Target as MemberReferenceExpression;
- if (mre == null)
- return false;
- string parameterName;
- Expression body;
- if (!MatchSimpleLambda(invocation.Arguments.Single(), out parameterName, out body))
- return false;
- if (parameterName != expectedParameterName)
- return false;
-
- if (mre.MemberName == "OrderBy" || mre.MemberName == "OrderByDescending")
- return true;
- else if (mre.MemberName == "ThenBy" || mre.MemberName == "ThenByDescending")
- return ValidateThenByChain(mre.Target as InvocationExpression, expectedParameterName);
- else
- return false;
- }
-
- /// <summary>Matches simple lambdas of the form "a => b"</summary>
- bool MatchSimpleLambda(Expression expr, out string parameterName, out Expression body)
- {
- LambdaExpression lambda = expr as LambdaExpression;
- if (lambda != null && lambda.Parameters.Count == 1 && lambda.Body is Expression) {
- ParameterDeclaration p = lambda.Parameters.Single();
- if (p.ParameterModifier == ParameterModifier.None) {
- parameterName = p.Name;
- body = (Expression)lambda.Body;
- return true;
- }
- }
- parameterName = null;
- body = null;
- return false;
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs b/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs
deleted file mode 100644
index 43548e38..00000000
--- a/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUnsafeModifier.cs
+++ /dev/null
@@ -1,106 +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 ICSharpCode.NRefactory.CSharp;
-
-namespace ICSharpCode.Decompiler.Ast.Transforms
-{
- public class IntroduceUnsafeModifier : DepthFirstAstVisitor<object, bool>, IAstTransform
- {
- public static readonly object PointerArithmeticAnnotation = new PointerArithmetic();
-
- sealed class PointerArithmetic {}
-
- public void Run(AstNode compilationUnit)
- {
- compilationUnit.AcceptVisitor(this, null);
- }
-
- protected override bool VisitChildren(AstNode node, object data)
- {
- bool result = false;
- for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
- result |= child.AcceptVisitor(this, data);
- }
- if (result && node is EntityDeclaration && !(node is Accessor)) {
- ((EntityDeclaration)node).Modifiers |= Modifiers.Unsafe;
- return false;
- }
- return result;
- }
-
- public override bool VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression, object data)
- {
- base.VisitPointerReferenceExpression(pointerReferenceExpression, data);
- return true;
- }
-
- public override bool VisitComposedType(ComposedType composedType, object data)
- {
- if (composedType.PointerRank > 0)
- return true;
- else
- return base.VisitComposedType(composedType, data);
- }
-
- public override bool VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data)
- {
- bool result = base.VisitUnaryOperatorExpression(unaryOperatorExpression, data);
- if (unaryOperatorExpression.Operator == UnaryOperatorType.Dereference) {
- BinaryOperatorExpression bop = unaryOperatorExpression.Expression as BinaryOperatorExpression;
- if (bop != null && bop.Operator == BinaryOperatorType.Add && bop.Annotation<PointerArithmetic>() != null) {
- // transform "*(ptr + int)" to "ptr[int]"
- IndexerExpression indexer = new IndexerExpression();
- indexer.Target = bop.Left.Detach();
- indexer.Arguments.Add(bop.Right.Detach());
- indexer.CopyAnnotationsFrom(unaryOperatorExpression);
- indexer.CopyAnnotationsFrom(bop);
- unaryOperatorExpression.ReplaceWith(indexer);
- }
- return true;
- } else if (unaryOperatorExpression.Operator == UnaryOperatorType.AddressOf) {
- return true;
- } else {
- return result;
- }
- }
-
- public override bool VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data)
- {
- bool result = base.VisitMemberReferenceExpression(memberReferenceExpression, data);
- UnaryOperatorExpression uoe = memberReferenceExpression.Target as UnaryOperatorExpression;
- if (uoe != null && uoe.Operator == UnaryOperatorType.Dereference) {
- PointerReferenceExpression pre = new PointerReferenceExpression();
- pre.Target = uoe.Expression.Detach();
- pre.MemberName = memberReferenceExpression.MemberName;
- memberReferenceExpression.TypeArguments.MoveTo(pre.TypeArguments);
- pre.CopyAnnotationsFrom(uoe);
- pre.CopyAnnotationsFrom(memberReferenceExpression);
- memberReferenceExpression.ReplaceWith(pre);
- }
- return result;
- }
-
- public override bool VisitStackAllocExpression(StackAllocExpression stackAllocExpression, object data)
- {
- base.VisitStackAllocExpression(stackAllocExpression, data);
- return true;
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs b/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs
deleted file mode 100644
index 6e9cc4f5..00000000
--- a/ICSharpCode.Decompiler/Ast/Transforms/IntroduceUsingDeclarations.cs
+++ /dev/null
@@ -1,359 +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.NRefactory.CSharp;
-using Mono.Cecil;
-
-namespace ICSharpCode.Decompiler.Ast.Transforms
-{
- /// <summary>
- /// Introduces using declarations.
- /// </summary>
- public class IntroduceUsingDeclarations : IAstTransform
- {
- DecompilerContext context;
-
- public IntroduceUsingDeclarations(DecompilerContext context)
- {
- this.context = context;
- }
-
- public void Run(AstNode compilationUnit)
- {
- // First determine all the namespaces that need to be imported:
- compilationUnit.AcceptVisitor(new FindRequiredImports(this), null);
-
- importedNamespaces.Add("System"); // always import System, even when not necessary
-
- if (context.Settings.UsingDeclarations) {
- // Now add using declarations for those namespaces:
- foreach (string ns in importedNamespaces.OrderByDescending(n => n)) {
- // we go backwards (OrderByDescending) through the list of namespaces because we insert them backwards
- // (always inserting at the start of the list)
- 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] };
- }
- compilationUnit.InsertChildAfter(null, new UsingDeclaration { Import = nsType }, SyntaxTree.MemberRole);
- }
- }
-
- if (!context.Settings.FullyQualifyAmbiguousTypeNames)
- return;
-
- FindAmbiguousTypeNames(context.CurrentModule, internalsVisible: true);
- foreach (AssemblyNameReference r in context.CurrentModule.AssemblyReferences) {
- AssemblyDefinition d = context.CurrentModule.AssemblyResolver.Resolve(r);
- if (d != null)
- FindAmbiguousTypeNames(d.MainModule, internalsVisible: false);
- }
-
- // verify that the SimpleTypes refer to the correct type (no ambiguities)
- compilationUnit.AcceptVisitor(new FullyQualifyAmbiguousTypeNamesVisitor(this), null);
- }
-
- readonly HashSet<string> declaredNamespaces = new HashSet<string>() { string.Empty };
- readonly HashSet<string> importedNamespaces = new HashSet<string>();
-
- // Note that we store type names with `n suffix, so we automatically disambiguate based on number of type parameters.
- readonly HashSet<string> availableTypeNames = new HashSet<string>();
- readonly HashSet<string> ambiguousTypeNames = new HashSet<string>();
-
- sealed class FindRequiredImports : DepthFirstAstVisitor<object, object>
- {
- readonly IntroduceUsingDeclarations transform;
- string currentNamespace;
-
- public FindRequiredImports(IntroduceUsingDeclarations transform)
- {
- this.transform = transform;
- currentNamespace = transform.context.CurrentType != null ? transform.context.CurrentType.Namespace : string.Empty;
- }
-
- bool IsParentOfCurrentNamespace(string ns)
- {
- if (ns.Length == 0)
- return true;
- if (currentNamespace.StartsWith(ns, StringComparison.Ordinal)) {
- if (currentNamespace.Length == ns.Length)
- return true;
- if (currentNamespace[ns.Length] == '.')
- return true;
- }
- return false;
- }
-
- public override object VisitSimpleType(SimpleType simpleType, object data)
- {
- TypeReference tr = simpleType.Annotation<TypeReference>();
- if (tr != null && !IsParentOfCurrentNamespace(tr.Namespace)) {
- transform.importedNamespaces.Add(tr.Namespace);
- }
- return base.VisitSimpleType(simpleType, data); // also visit type arguments
- }
-
- public override object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data)
- {
- string oldNamespace = currentNamespace;
- foreach (string ident in namespaceDeclaration.Identifiers) {
- currentNamespace = NamespaceDeclaration.BuildQualifiedName(currentNamespace, ident);
- transform.declaredNamespaces.Add(currentNamespace);
- }
- base.VisitNamespaceDeclaration(namespaceDeclaration, data);
- currentNamespace = oldNamespace;
- return null;
- }
- }
-
- void FindAmbiguousTypeNames(ModuleDefinition module, bool internalsVisible)
- {
- foreach (TypeDefinition type in module.Types) {
- if (internalsVisible || type.IsPublic) {
- if (importedNamespaces.Contains(type.Namespace) || declaredNamespaces.Contains(type.Namespace)) {
- if (!availableTypeNames.Add(type.Name))
- ambiguousTypeNames.Add(type.Name);
- }
- }
- }
- }
-
- sealed class FullyQualifyAmbiguousTypeNamesVisitor : DepthFirstAstVisitor<object, object>
- {
- readonly IntroduceUsingDeclarations transform;
- string currentNamespace;
- HashSet<string> currentMemberTypes;
- Dictionary<string, MemberReference> currentMembers;
- bool isWithinTypeReferenceExpression;
-
- public FullyQualifyAmbiguousTypeNamesVisitor(IntroduceUsingDeclarations transform)
- {
- this.transform = transform;
- currentNamespace = transform.context.CurrentType != null ? transform.context.CurrentType.Namespace : string.Empty;
- }
-
- public override object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data)
- {
- string oldNamespace = currentNamespace;
- foreach (string ident in namespaceDeclaration.Identifiers) {
- currentNamespace = NamespaceDeclaration.BuildQualifiedName(currentNamespace, ident);
- }
- base.VisitNamespaceDeclaration(namespaceDeclaration, data);
- currentNamespace = oldNamespace;
- return null;
- }
-
- public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data)
- {
- HashSet<string> oldMemberTypes = currentMemberTypes;
- currentMemberTypes = currentMemberTypes != null ? new HashSet<string>(currentMemberTypes) : new HashSet<string>();
-
- Dictionary<string, MemberReference> oldMembers = currentMembers;
- currentMembers = new Dictionary<string, MemberReference>();
-
- TypeDefinition typeDef = typeDeclaration.Annotation<TypeDefinition>();
- bool privateMembersVisible = true;
- ModuleDefinition internalMembersVisibleInModule = typeDef.Module;
- while (typeDef != null) {
- foreach (GenericParameter gp in typeDef.GenericParameters) {
- currentMemberTypes.Add(gp.Name);
- }
- foreach (TypeDefinition t in typeDef.NestedTypes) {
- if (privateMembersVisible || IsVisible(t, internalMembersVisibleInModule))
- currentMemberTypes.Add(t.Name.Substring(t.Name.LastIndexOf('+') + 1));
- }
-
- foreach (MethodDefinition method in typeDef.Methods) {
- if (privateMembersVisible || IsVisible(method, internalMembersVisibleInModule))
- AddCurrentMember(method);
- }
- foreach (PropertyDefinition property in typeDef.Properties) {
- if (privateMembersVisible || IsVisible(property.GetMethod, internalMembersVisibleInModule) || IsVisible(property.SetMethod, internalMembersVisibleInModule))
- AddCurrentMember(property);
- }
- foreach (EventDefinition ev in typeDef.Events) {
- if (privateMembersVisible || IsVisible(ev.AddMethod, internalMembersVisibleInModule) || IsVisible(ev.RemoveMethod, internalMembersVisibleInModule))
- AddCurrentMember(ev);
- }
- foreach (FieldDefinition f in typeDef.Fields) {
- if (privateMembersVisible || IsVisible(f, internalMembersVisibleInModule))
- AddCurrentMember(f);
- }
- // repeat with base class:
- if (typeDef.BaseType != null)
- typeDef = typeDef.BaseType.Resolve();
- else
- typeDef = null;
- privateMembersVisible = false;
- }
-
- // Now add current members from outer classes:
- if (oldMembers != null) {
- foreach (var pair in oldMembers) {
- // add members from outer classes only if the inner class doesn't define the member
- if (!currentMembers.ContainsKey(pair.Key))
- currentMembers.Add(pair.Key, pair.Value);
- }
- }
-
- base.VisitTypeDeclaration(typeDeclaration, data);
- currentMembers = oldMembers;
- return null;
- }
-
- void AddCurrentMember(MemberReference m)
- {
- MemberReference existingMember;
- if (currentMembers.TryGetValue(m.Name, out existingMember)) {
- // We keep the existing member assignment if it was from another class (=from a derived class),
- // because members in derived classes have precedence over members in base classes.
- if (existingMember != null && existingMember.DeclaringType == m.DeclaringType) {
- // Use null as value to signalize multiple members with the same name
- currentMembers[m.Name] = null;
- }
- } else {
- currentMembers.Add(m.Name, m);
- }
- }
-
- bool IsVisible(MethodDefinition m, ModuleDefinition internalMembersVisibleInModule)
- {
- if (m == null)
- return false;
- switch (m.Attributes & MethodAttributes.MemberAccessMask) {
- case MethodAttributes.FamANDAssem:
- case MethodAttributes.Assembly:
- return m.Module == internalMembersVisibleInModule;
- case MethodAttributes.Family:
- case MethodAttributes.FamORAssem:
- case MethodAttributes.Public:
- return true;
- default:
- return false;
- }
- }
-
- bool IsVisible(FieldDefinition f, ModuleDefinition internalMembersVisibleInModule)
- {
- if (f == null)
- return false;
- switch (f.Attributes & FieldAttributes.FieldAccessMask) {
- case FieldAttributes.FamANDAssem:
- case FieldAttributes.Assembly:
- return f.Module == internalMembersVisibleInModule;
- case FieldAttributes.Family:
- case FieldAttributes.FamORAssem:
- case FieldAttributes.Public:
- return true;
- default:
- return false;
- }
- }
-
- bool IsVisible(TypeDefinition t, ModuleDefinition internalMembersVisibleInModule)
- {
- if (t == null)
- return false;
- switch (t.Attributes & TypeAttributes.VisibilityMask) {
- case TypeAttributes.NotPublic:
- case TypeAttributes.NestedAssembly:
- case TypeAttributes.NestedFamANDAssem:
- return t.Module == internalMembersVisibleInModule;
- case TypeAttributes.NestedFamily:
- case TypeAttributes.NestedFamORAssem:
- case TypeAttributes.NestedPublic:
- case TypeAttributes.Public:
- return true;
- default:
- return false;
- }
- }
-
- public override object VisitSimpleType(SimpleType simpleType, object data)
- {
- // Handle type arguments first, so that the fixed-up type arguments get moved over to the MemberType,
- // if we're also creating one here.
- base.VisitSimpleType(simpleType, data);
- TypeReference tr = simpleType.Annotation<TypeReference>();
- // Fully qualify any ambiguous type names.
- if (tr != null && IsAmbiguous(tr.Namespace, tr.Name)) {
- AstType ns;
- if (string.IsNullOrEmpty(tr.Namespace)) {
- ns = new SimpleType("global");
- } else {
- string[] parts = tr.Namespace.Split('.');
- if (IsAmbiguous(string.Empty, parts[0])) {
- // conflict between namespace and type name/member name
- ns = new MemberType { Target = new SimpleType("global"), IsDoubleColon = true, MemberName = parts[0] };
- } else {
- ns = new SimpleType(parts[0]);
- }
- for (int i = 1; i < parts.Length; i++) {
- ns = new MemberType { Target = ns, MemberName = parts[i] };
- }
- }
- MemberType mt = new MemberType();
- mt.Target = ns;
- mt.IsDoubleColon = string.IsNullOrEmpty(tr.Namespace);
- mt.MemberName = simpleType.Identifier;
- mt.CopyAnnotationsFrom(simpleType);
- simpleType.TypeArguments.MoveTo(mt.TypeArguments);
- simpleType.ReplaceWith(mt);
- }
- return null;
- }
-
- public override object VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, object data)
- {
- isWithinTypeReferenceExpression = true;
- base.VisitTypeReferenceExpression(typeReferenceExpression, data);
- isWithinTypeReferenceExpression = false;
- return null;
- }
-
- bool IsAmbiguous(string ns, string name)
- {
- // If the type name conflicts with an inner class/type parameter, we need to fully-qualify it:
- if (currentMemberTypes != null && currentMemberTypes.Contains(name))
- return true;
- // If the type name conflicts with a field/property etc. on the current class, we need to fully-qualify it,
- // if we're inside an expression.
- if (isWithinTypeReferenceExpression && currentMembers != null) {
- MemberReference mr;
- if (currentMembers.TryGetValue(name, out mr)) {
- // However, in the special case where the member is a field or property with the same type
- // as is requested, then we can use the short name (if it's not otherwise ambiguous)
- PropertyDefinition prop = mr as PropertyDefinition;
- FieldDefinition field = mr as FieldDefinition;
- if (!(prop != null && prop.PropertyType.Namespace == ns && prop.PropertyType.Name == name)
- && !(field != null && field.FieldType.Namespace == ns && field.FieldType.Name == name))
- return true;
- }
- }
- // If the type is defined in the current namespace,
- // then we can use the short name even if we imported type with same name from another namespace.
- if (ns == currentNamespace && !string.IsNullOrEmpty(ns))
- return false;
- return transform.ambiguousTypeNames.Contains(name);
- }
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs b/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs
deleted file mode 100644
index d3ae46c1..00000000
--- a/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs
+++ /dev/null
@@ -1,1123 +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.Diagnostics;
-using System.Linq;
-
-using ICSharpCode.Decompiler.ILAst;
-using ICSharpCode.NRefactory.CSharp;
-using ICSharpCode.NRefactory.CSharp.Analysis;
-using ICSharpCode.NRefactory.PatternMatching;
-using Mono.Cecil;
-
-namespace ICSharpCode.Decompiler.Ast.Transforms
-{
- /// <summary>
- /// Finds the expanded form of using statements using pattern matching and replaces it with a UsingStatement.
- /// </summary>
- public sealed class PatternStatementTransform : ContextTrackingVisitor<AstNode>, IAstTransform
- {
- public PatternStatementTransform(DecompilerContext context) : base(context)
- {
- }
-
- #region Visitor Overrides
- protected override AstNode VisitChildren(AstNode node, object data)
- {
- // Go through the children, and keep visiting a node as long as it changes.
- // Because some transforms delete/replace nodes before and after the node being transformed, we rely
- // on the transform's return value to know where we need to keep iterating.
- for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
- AstNode oldChild;
- do {
- oldChild = child;
- child = child.AcceptVisitor(this, data);
- Debug.Assert(child != null && child.Parent == node);
- } while (child != oldChild);
- }
- return node;
- }
-
- public override AstNode VisitExpressionStatement(ExpressionStatement expressionStatement, object data)
- {
- AstNode result;
- if (context.Settings.UsingStatement) {
- result = TransformUsings(expressionStatement);
- if (result != null)
- return result;
- result = TransformNonGenericForEach(expressionStatement);
- if (result != null)
- return result;
- }
- result = TransformFor(expressionStatement);
- if (result != null)
- return result;
- if (context.Settings.LockStatement) {
- result = TransformLock(expressionStatement);
- if (result != null)
- return result;
- }
- return base.VisitExpressionStatement(expressionStatement, data);
- }
-
- public override AstNode VisitUsingStatement(UsingStatement usingStatement, object data)
- {
- if (context.Settings.ForEachStatement) {
- AstNode result = TransformForeach(usingStatement);
- if (result != null)
- return result;
- }
- return base.VisitUsingStatement(usingStatement, data);
- }
-
- public override AstNode VisitWhileStatement(WhileStatement whileStatement, object data)
- {
- return TransformDoWhile(whileStatement) ?? base.VisitWhileStatement(whileStatement, data);
- }
-
- public override AstNode VisitIfElseStatement(IfElseStatement ifElseStatement, object data)
- {
- if (context.Settings.SwitchStatementOnString) {
- AstNode result = TransformSwitchOnString(ifElseStatement);
- if (result != null)
- return result;
- }
- AstNode simplifiedIfElse = SimplifyCascadingIfElseStatements(ifElseStatement);
- if (simplifiedIfElse != null)
- return simplifiedIfElse;
- return base.VisitIfElseStatement(ifElseStatement, data);
- }
-
- public override AstNode VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data)
- {
- if (context.Settings.AutomaticProperties) {
- AstNode result = TransformAutomaticProperties(propertyDeclaration);
- if (result != null)
- return result;
- }
- return base.VisitPropertyDeclaration(propertyDeclaration, data);
- }
-
- public override AstNode VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration, object data)
- {
- // first apply transforms to the accessor bodies
- base.VisitCustomEventDeclaration(eventDeclaration, data);
- if (context.Settings.AutomaticEvents) {
- AstNode result = TransformAutomaticEvents(eventDeclaration);
- if (result != null)
- return result;
- }
- return eventDeclaration;
- }
-
- public override AstNode VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data)
- {
- return TransformDestructor(methodDeclaration) ?? base.VisitMethodDeclaration(methodDeclaration, data);
- }
-
- public override AstNode VisitTryCatchStatement(TryCatchStatement tryCatchStatement, object data)
- {
- return TransformTryCatchFinally(tryCatchStatement) ?? base.VisitTryCatchStatement(tryCatchStatement, data);
- }
- #endregion
-
- /// <summary>
- /// $variable = $initializer;
- /// </summary>
- static readonly AstNode variableAssignPattern = new ExpressionStatement(
- new AssignmentExpression(
- new NamedNode("variable", new IdentifierExpression(Pattern.AnyString)),
- new AnyNode("initializer")
- ));
-
- #region using
- static Expression InvokeDispose(Expression identifier)
- {
- return new Choice {
- identifier.Invoke("Dispose"),
- identifier.Clone().CastTo(new TypePattern(typeof(IDisposable))).Invoke("Dispose")
- };
- }
-
- static readonly AstNode usingTryCatchPattern = new TryCatchStatement {
- TryBlock = new AnyNode(),
- FinallyBlock = new BlockStatement {
- new Choice {
- { "valueType",
- new ExpressionStatement(InvokeDispose(new NamedNode("ident", new IdentifierExpression(Pattern.AnyString))))
- },
- { "referenceType",
- new IfElseStatement {
- Condition = new BinaryOperatorExpression(
- new NamedNode("ident", new IdentifierExpression(Pattern.AnyString)),
- BinaryOperatorType.InEquality,
- new NullReferenceExpression()
- ),
- TrueStatement = new BlockStatement {
- new ExpressionStatement(InvokeDispose(new Backreference("ident")))
- }
- }
- }
- }.ToStatement()
- }
- };
-
- public UsingStatement TransformUsings(ExpressionStatement node)
- {
- Match m1 = variableAssignPattern.Match(node);
- if (!m1.Success) return null;
- TryCatchStatement tryCatch = node.NextSibling as TryCatchStatement;
- Match m2 = usingTryCatchPattern.Match(tryCatch);
- if (!m2.Success) return null;
- string variableName = m1.Get<IdentifierExpression>("variable").Single().Identifier;
- if (variableName != m2.Get<IdentifierExpression>("ident").Single().Identifier)
- return null;
- if (m2.Has("valueType")) {
- // if there's no if(x!=null), then it must be a value type
- ILVariable v = m1.Get<AstNode>("variable").Single().Annotation<ILVariable>();
- if (v == null || v.Type == null || !v.Type.IsValueType)
- return null;
- }
-
- // There are two variants of the using statement:
- // "using (var a = init)" and "using (expr)".
- // The former declares a read-only variable 'a', and the latter declares an unnamed read-only variable
- // to store the original value of 'expr'.
- // This means that in order to introduce a using statement, in both cases we need to detect a read-only
- // variable that is used only within that block.
-
- if (HasAssignment(tryCatch, variableName))
- return null;
-
- VariableDeclarationStatement varDecl = FindVariableDeclaration(node, variableName);
- if (varDecl == null || !(varDecl.Parent is BlockStatement))
- return null;
-
- // Validate that the variable is not used after the using statement:
- if (!IsVariableValueUnused(varDecl, tryCatch))
- return null;
-
- node.Remove();
-
- UsingStatement usingStatement = new UsingStatement();
- usingStatement.EmbeddedStatement = tryCatch.TryBlock.Detach();
- tryCatch.ReplaceWith(usingStatement);
-
- // If possible, we'll eliminate the variable completely:
- if (usingStatement.EmbeddedStatement.Descendants.OfType<IdentifierExpression>().Any(ident => ident.Identifier == variableName)) {
- // variable is used, so we'll create a variable declaration
- usingStatement.ResourceAcquisition = new VariableDeclarationStatement {
- Type = (AstType)varDecl.Type.Clone(),
- Variables = {
- new VariableInitializer {
- Name = variableName,
- Initializer = m1.Get<Expression>("initializer").Single().Detach()
- }.CopyAnnotationsFrom(node.Expression)
- .WithAnnotation(m1.Get<AstNode>("variable").Single().Annotation<ILVariable>())
- }
- }.CopyAnnotationsFrom(node);
- } else {
- // the variable is never used; eliminate it:
- usingStatement.ResourceAcquisition = m1.Get<Expression>("initializer").Single().Detach();
- }
- return usingStatement;
- }
-
- internal static VariableDeclarationStatement FindVariableDeclaration(AstNode node, string identifier)
- {
- while (node != null) {
- while (node.PrevSibling != null) {
- node = node.PrevSibling;
- VariableDeclarationStatement varDecl = node as VariableDeclarationStatement;
- if (varDecl != null && varDecl.Variables.Count == 1 && varDecl.Variables.Single().Name == identifier) {
- return varDecl;
- }
- }
- node = node.Parent;
- }
- return null;
- }
-
- /// <summary>
- /// Gets whether the old variable value (assigned inside 'targetStatement' or earlier)
- /// is read anywhere in the remaining scope of the variable declaration.
- /// </summary>
- bool IsVariableValueUnused(VariableDeclarationStatement varDecl, Statement targetStatement)
- {
- Debug.Assert(targetStatement.Ancestors.Contains(varDecl.Parent));
- BlockStatement block = (BlockStatement)varDecl.Parent;
- DefiniteAssignmentAnalysis daa = new DefiniteAssignmentAnalysis(block, context.CancellationToken);
- 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)
-
- // I'm not sure whether the other consumers of 'CanMoveVariableDeclarationIntoStatement' should be changed the same way.
- bool CanMoveVariableDeclarationIntoStatement(VariableDeclarationStatement varDecl, Statement targetStatement, out Statement declarationPoint)
- {
- Debug.Assert(targetStatement.Ancestors.Contains(varDecl.Parent));
- // Find all blocks between targetStatement and varDecl.Parent
- List<BlockStatement> blocks = targetStatement.Ancestors.TakeWhile(block => block != varDecl.Parent).OfType<BlockStatement>().ToList();
- blocks.Add((BlockStatement)varDecl.Parent); // also handle the varDecl.Parent block itself
- blocks.Reverse(); // go from parent blocks to child blocks
- DefiniteAssignmentAnalysis daa = new DefiniteAssignmentAnalysis(blocks[0], context.CancellationToken);
- declarationPoint = null;
- foreach (BlockStatement block in blocks) {
- if (!DeclareVariables.FindDeclarationPoint(daa, varDecl, block, out declarationPoint)) {
- return false;
- }
- }
- return true;
- }
-
- /// <summary>
- /// Gets whether there is an assignment to 'variableName' anywhere within the given node.
- /// </summary>
- bool HasAssignment(AstNode root, string variableName)
- {
- foreach (AstNode node in root.DescendantsAndSelf) {
- IdentifierExpression ident = node as IdentifierExpression;
- if (ident != null && ident.Identifier == variableName) {
- if (ident.Parent is AssignmentExpression && ident.Role == AssignmentExpression.LeftRole
- || ident.Parent is DirectionExpression)
- {
- return true;
- }
- }
- }
- return false;
- }
- #endregion
-
- #region foreach (generic)
- static readonly UsingStatement genericForeachPattern = new UsingStatement {
- ResourceAcquisition = new VariableDeclarationStatement {
- Type = new AnyNode("enumeratorType"),
- Variables = {
- new NamedNode(
- "enumeratorVariable",
- new VariableInitializer {
- Name = Pattern.AnyString,
- Initializer = new AnyNode("collection").ToExpression().Invoke("GetEnumerator")
- }
- )
- }
- },
- EmbeddedStatement = new BlockStatement {
- new Repeat(
- new VariableDeclarationStatement { Type = new AnyNode(), Variables = { new VariableInitializer(Pattern.AnyString) } }.WithName("variablesOutsideLoop")
- ).ToStatement(),
- new WhileStatement {
- Condition = new IdentifierExpressionBackreference("enumeratorVariable").ToExpression().Invoke("MoveNext"),
- EmbeddedStatement = new BlockStatement {
- new Repeat(
- new VariableDeclarationStatement {
- Type = new AnyNode(),
- Variables = { new VariableInitializer(Pattern.AnyString) }
- }.WithName("variablesInsideLoop")
- ).ToStatement(),
- new AssignmentExpression {
- Left = new IdentifierExpression(Pattern.AnyString).WithName("itemVariable"),
- Operator = AssignmentOperatorType.Assign,
- Right = new IdentifierExpressionBackreference("enumeratorVariable").ToExpression().Member("Current")
- },
- new Repeat(new AnyNode("statement")).ToStatement()
- }
- }.WithName("loop")
- }};
-
- public ForeachStatement TransformForeach(UsingStatement node)
- {
- Match m = genericForeachPattern.Match(node);
- if (!m.Success)
- return null;
- if (!(node.Parent is BlockStatement) && m.Has("variablesOutsideLoop")) {
- // if there are variables outside the loop, we need to put those into the parent block, and that won't work if the direct parent isn't a block
- return null;
- }
- VariableInitializer enumeratorVar = m.Get<VariableInitializer>("enumeratorVariable").Single();
- IdentifierExpression itemVar = m.Get<IdentifierExpression>("itemVariable").Single();
- WhileStatement loop = m.Get<WhileStatement>("loop").Single();
-
- // Find the declaration of the item variable:
- // Because we look only outside the loop, we won't make the mistake of moving a captured variable across the loop boundary
- VariableDeclarationStatement itemVarDecl = FindVariableDeclaration(loop, itemVar.Identifier);
- if (itemVarDecl == null || !(itemVarDecl.Parent is BlockStatement))
- return null;
-
- // Now verify that we can move the variable declaration in front of the loop:
- Statement declarationPoint;
- CanMoveVariableDeclarationIntoStatement(itemVarDecl, loop, out declarationPoint);
- // We ignore the return value because we don't care whether we can move the variable into the loop
- // (that is possible only with non-captured variables).
- // We just care that we can move it in front of the loop:
- if (declarationPoint != loop)
- return null;
-
- BlockStatement newBody = new BlockStatement();
- foreach (Statement stmt in m.Get<Statement>("variablesInsideLoop"))
- newBody.Add(stmt.Detach());
- foreach (Statement stmt in m.Get<Statement>("statement"))
- newBody.Add(stmt.Detach());
-
- ForeachStatement foreachStatement = new ForeachStatement {
- VariableType = (AstType)itemVarDecl.Type.Clone(),
- VariableName = itemVar.Identifier,
- InExpression = m.Get<Expression>("collection").Single().Detach(),
- EmbeddedStatement = newBody
- }.WithAnnotation(itemVarDecl.Variables.Single().Annotation<ILVariable>());
- if (foreachStatement.InExpression is BaseReferenceExpression) {
- foreachStatement.InExpression = new ThisReferenceExpression().CopyAnnotationsFrom(foreachStatement.InExpression);
- }
- node.ReplaceWith(foreachStatement);
- foreach (Statement stmt in m.Get<Statement>("variablesOutsideLoop")) {
- ((BlockStatement)foreachStatement.Parent).Statements.InsertAfter(null, stmt.Detach());
- }
- return foreachStatement;
- }
- #endregion
-
- #region foreach (non-generic)
- ExpressionStatement getEnumeratorPattern = new ExpressionStatement(
- new AssignmentExpression(
- new NamedNode("left", new IdentifierExpression(Pattern.AnyString)),
- new AnyNode("collection").ToExpression().Invoke("GetEnumerator")
- ));
-
- TryCatchStatement nonGenericForeachPattern = new TryCatchStatement {
- TryBlock = new BlockStatement {
- new WhileStatement {
- Condition = new IdentifierExpression(Pattern.AnyString).WithName("enumerator").Invoke("MoveNext"),
- EmbeddedStatement = new BlockStatement {
- new AssignmentExpression(
- new IdentifierExpression(Pattern.AnyString).WithName("itemVar"),
- new Choice {
- new Backreference("enumerator").ToExpression().Member("Current"),
- new CastExpression {
- Type = new AnyNode("castType"),
- Expression = new Backreference("enumerator").ToExpression().Member("Current")
- }
- }
- ),
- new Repeat(new AnyNode("stmt")).ToStatement()
- }
- }.WithName("loop")
- },
- FinallyBlock = new BlockStatement {
- new AssignmentExpression(
- new IdentifierExpression(Pattern.AnyString).WithName("disposable"),
- new Backreference("enumerator").ToExpression().CastAs(new TypePattern(typeof(IDisposable)))
- ),
- new IfElseStatement {
- Condition = new BinaryOperatorExpression {
- Left = new Backreference("disposable"),
- Operator = BinaryOperatorType.InEquality,
- Right = new NullReferenceExpression()
- },
- TrueStatement = new BlockStatement {
- new Backreference("disposable").ToExpression().Invoke("Dispose")
- }
- }
- }};
-
- public ForeachStatement TransformNonGenericForEach(ExpressionStatement node)
- {
- Match m1 = getEnumeratorPattern.Match(node);
- if (!m1.Success) return null;
- AstNode tryCatch = node.NextSibling;
- Match m2 = nonGenericForeachPattern.Match(tryCatch);
- if (!m2.Success) return null;
-
- IdentifierExpression enumeratorVar = m2.Get<IdentifierExpression>("enumerator").Single();
- IdentifierExpression itemVar = m2.Get<IdentifierExpression>("itemVar").Single();
- WhileStatement loop = m2.Get<WhileStatement>("loop").Single();
-
- // verify that the getEnumeratorPattern assigns to the same variable as the nonGenericForeachPattern is reading from
- if (!enumeratorVar.IsMatch(m1.Get("left").Single()))
- return null;
-
- VariableDeclarationStatement enumeratorVarDecl = FindVariableDeclaration(loop, enumeratorVar.Identifier);
- if (enumeratorVarDecl == null || !(enumeratorVarDecl.Parent is BlockStatement))
- return null;
-
- // Find the declaration of the item variable:
- // Because we look only outside the loop, we won't make the mistake of moving a captured variable across the loop boundary
- VariableDeclarationStatement itemVarDecl = FindVariableDeclaration(loop, itemVar.Identifier);
- if (itemVarDecl == null || !(itemVarDecl.Parent is BlockStatement))
- return null;
-
- // Now verify that we can move the variable declaration in front of the loop:
- Statement declarationPoint;
- CanMoveVariableDeclarationIntoStatement(itemVarDecl, loop, out declarationPoint);
- // We ignore the return value because we don't care whether we can move the variable into the loop
- // (that is possible only with non-captured variables).
- // We just care that we can move it in front of the loop:
- if (declarationPoint != loop)
- return null;
-
- ForeachStatement foreachStatement = new ForeachStatement
- {
- VariableType = itemVarDecl.Type.Clone(),
- VariableName = itemVar.Identifier,
- }.WithAnnotation(itemVarDecl.Variables.Single().Annotation<ILVariable>());
- BlockStatement body = new BlockStatement();
- foreachStatement.EmbeddedStatement = body;
- ((BlockStatement)node.Parent).Statements.InsertBefore(node, foreachStatement);
-
- body.Add(node.Detach());
- body.Add((Statement)tryCatch.Detach());
-
- // Now that we moved the whole try-catch into the foreach loop; verify that we can
- // move the enumerator into the foreach loop:
- CanMoveVariableDeclarationIntoStatement(enumeratorVarDecl, foreachStatement, out declarationPoint);
- if (declarationPoint != foreachStatement) {
- // oops, the enumerator variable can't be moved into the foreach loop
- // Undo our AST changes:
- ((BlockStatement)foreachStatement.Parent).Statements.InsertBefore(foreachStatement, node.Detach());
- foreachStatement.ReplaceWith(tryCatch);
- return null;
- }
-
- // Now create the correct body for the foreach statement:
- foreachStatement.InExpression = m1.Get<Expression>("collection").Single().Detach();
- if (foreachStatement.InExpression is BaseReferenceExpression) {
- foreachStatement.InExpression = new ThisReferenceExpression().CopyAnnotationsFrom(foreachStatement.InExpression);
- }
- body.Statements.Clear();
- body.Statements.AddRange(m2.Get<Statement>("stmt").Select(stmt => stmt.Detach()));
-
- return foreachStatement;
- }
- #endregion
-
- #region for
- static readonly WhileStatement forPattern = new WhileStatement {
- Condition = new BinaryOperatorExpression {
- Left = new NamedNode("ident", new IdentifierExpression(Pattern.AnyString)),
- Operator = BinaryOperatorType.Any,
- Right = new AnyNode("endExpr")
- },
- EmbeddedStatement = new BlockStatement {
- Statements = {
- new Repeat(new AnyNode("statement")),
- new NamedNode(
- "increment",
- new ExpressionStatement(
- new AssignmentExpression {
- Left = new Backreference("ident"),
- Operator = AssignmentOperatorType.Any,
- Right = new AnyNode()
- }))
- }
- }};
-
- public ForStatement TransformFor(ExpressionStatement node)
- {
- Match m1 = variableAssignPattern.Match(node);
- if (!m1.Success) return null;
- AstNode next = node.NextSibling;
- Match m2 = forPattern.Match(next);
- if (!m2.Success) return null;
- // ensure the variable in the for pattern is the same as in the declaration
- if (m1.Get<IdentifierExpression>("variable").Single().Identifier != m2.Get<IdentifierExpression>("ident").Single().Identifier)
- return null;
- WhileStatement loop = (WhileStatement)next;
- node.Remove();
- BlockStatement newBody = new BlockStatement();
- foreach (Statement stmt in m2.Get<Statement>("statement"))
- newBody.Add(stmt.Detach());
- ForStatement forStatement = new ForStatement();
- forStatement.Initializers.Add(node);
- forStatement.Condition = loop.Condition.Detach();
- forStatement.Iterators.Add(m2.Get<Statement>("increment").Single().Detach());
- forStatement.EmbeddedStatement = newBody;
- loop.ReplaceWith(forStatement);
- return forStatement;
- }
- #endregion
-
- #region doWhile
- static readonly WhileStatement doWhilePattern = new WhileStatement {
- Condition = new PrimitiveExpression(true),
- EmbeddedStatement = new BlockStatement {
- Statements = {
- new Repeat(new AnyNode("statement")),
- new IfElseStatement {
- Condition = new AnyNode("condition"),
- TrueStatement = new BlockStatement { new BreakStatement() }
- }
- }
- }};
-
- public DoWhileStatement TransformDoWhile(WhileStatement whileLoop)
- {
- Match m = doWhilePattern.Match(whileLoop);
- if (m.Success) {
- DoWhileStatement doLoop = new DoWhileStatement();
- doLoop.Condition = new UnaryOperatorExpression(UnaryOperatorType.Not, m.Get<Expression>("condition").Single().Detach());
- doLoop.Condition.AcceptVisitor(new PushNegation(), null);
- BlockStatement block = (BlockStatement)whileLoop.EmbeddedStatement;
- block.Statements.Last().Remove(); // remove if statement
- doLoop.EmbeddedStatement = block.Detach();
- whileLoop.ReplaceWith(doLoop);
-
- // we may have to extract variable definitions out of the loop if they were used in the condition:
- foreach (var varDecl in block.Statements.OfType<VariableDeclarationStatement>()) {
- VariableInitializer v = varDecl.Variables.Single();
- if (doLoop.Condition.DescendantsAndSelf.OfType<IdentifierExpression>().Any(i => i.Identifier == v.Name)) {
- AssignmentExpression assign = new AssignmentExpression(new IdentifierExpression(v.Name), v.Initializer.Detach());
- // move annotations from v to assign:
- assign.CopyAnnotationsFrom(v);
- v.RemoveAnnotations<object>();
- // remove varDecl with assignment; and move annotations from varDecl to the ExpressionStatement:
- varDecl.ReplaceWith(new ExpressionStatement(assign).CopyAnnotationsFrom(varDecl));
- varDecl.RemoveAnnotations<object>();
-
- // insert the varDecl above the do-while loop:
- doLoop.Parent.InsertChildBefore(doLoop, varDecl, BlockStatement.StatementRole);
- }
- }
- return doLoop;
- }
- return null;
- }
- #endregion
-
- #region lock
- static readonly AstNode lockFlagInitPattern = new ExpressionStatement(
- new AssignmentExpression(
- new NamedNode("variable", new IdentifierExpression(Pattern.AnyString)),
- new PrimitiveExpression(false)
- ));
-
- static readonly AstNode lockTryCatchPattern = new TryCatchStatement {
- TryBlock = new BlockStatement {
- new OptionalNode(new VariableDeclarationStatement()).ToStatement(),
- new TypePattern(typeof(System.Threading.Monitor)).ToType().Invoke(
- "Enter", new AnyNode("enter"),
- new DirectionExpression {
- FieldDirection = FieldDirection.Ref,
- Expression = new NamedNode("flag", new IdentifierExpression(Pattern.AnyString))
- }),
- new Repeat(new AnyNode()).ToStatement()
- },
- FinallyBlock = new BlockStatement {
- new IfElseStatement {
- Condition = new Backreference("flag"),
- TrueStatement = new BlockStatement {
- new TypePattern(typeof(System.Threading.Monitor)).ToType().Invoke("Exit", new AnyNode("exit"))
- }
- }
- }};
-
- static readonly AstNode oldMonitorCallPattern = new ExpressionStatement(
- new TypePattern(typeof(System.Threading.Monitor)).ToType().Invoke("Enter", new AnyNode("enter"))
- );
-
- static readonly AstNode oldLockTryCatchPattern = new TryCatchStatement
- {
- TryBlock = new BlockStatement {
- new Repeat(new AnyNode()).ToStatement()
- },
- FinallyBlock = new BlockStatement {
- new TypePattern(typeof(System.Threading.Monitor)).ToType().Invoke("Exit", new AnyNode("exit"))
- }
- };
-
- bool AnalyzeLockV2(ExpressionStatement node, out Expression enter, out Expression exit)
- {
- enter = null;
- exit = null;
- Match m1 = oldMonitorCallPattern.Match(node);
- if (!m1.Success) return false;
- Match m2 = oldLockTryCatchPattern.Match(node.NextSibling);
- if (!m2.Success) return false;
- enter = m1.Get<Expression>("enter").Single();
- exit = m2.Get<Expression>("exit").Single();
- return true;
- }
-
- bool AnalyzeLockV4(ExpressionStatement node, out Expression enter, out Expression exit)
- {
- enter = null;
- exit = null;
- Match m1 = lockFlagInitPattern.Match(node);
- if (!m1.Success) return false;
- Match m2 = lockTryCatchPattern.Match(node.NextSibling);
- if (!m2.Success) return false;
- enter = m2.Get<Expression>("enter").Single();
- exit = m2.Get<Expression>("exit").Single();
- return m1.Get<IdentifierExpression>("variable").Single().Identifier == m2.Get<IdentifierExpression>("flag").Single().Identifier;
- }
-
- public LockStatement TransformLock(ExpressionStatement node)
- {
- Expression enter, exit;
- bool isV2 = AnalyzeLockV2(node, out enter, out exit);
- if (isV2 || AnalyzeLockV4(node, out enter, out exit)) {
- AstNode tryCatch = node.NextSibling;
- if (!exit.IsMatch(enter)) {
- // If exit and enter are not the same, then enter must be "exit = ..."
- AssignmentExpression assign = enter as AssignmentExpression;
- if (assign == null)
- return null;
- if (!exit.IsMatch(assign.Left))
- return null;
- enter = assign.Right;
- // TODO: verify that 'obj' variable can be removed
- }
- // TODO: verify that 'flag' variable can be removed
- // transform the code into a lock statement:
- LockStatement l = new LockStatement();
- l.Expression = enter.Detach();
- l.EmbeddedStatement = ((TryCatchStatement)tryCatch).TryBlock.Detach();
- if (!isV2) // Remove 'Enter()' call
- ((BlockStatement)l.EmbeddedStatement).Statements.First().Remove();
- tryCatch.ReplaceWith(l);
- node.Remove(); // remove flag variable
- return l;
- }
- return null;
- }
- #endregion
-
- #region switch on strings
- static readonly IfElseStatement switchOnStringPattern = new IfElseStatement {
- Condition = new BinaryOperatorExpression {
- Left = new AnyNode("switchExpr"),
- Operator = BinaryOperatorType.InEquality,
- Right = new NullReferenceExpression()
- },
- TrueStatement = new BlockStatement {
- new IfElseStatement {
- Condition = new BinaryOperatorExpression {
- Left = new AnyNode("cachedDict"),
- Operator = BinaryOperatorType.Equality,
- Right = new NullReferenceExpression()
- },
- TrueStatement = new AnyNode("dictCreation")
- },
- new IfElseStatement {
- Condition = new Backreference("cachedDict").ToExpression().Invoke(
- "TryGetValue",
- new NamedNode("switchVar", new IdentifierExpression(Pattern.AnyString)),
- new DirectionExpression {
- FieldDirection = FieldDirection.Out,
- Expression = new IdentifierExpression(Pattern.AnyString).WithName("intVar")
- }),
- TrueStatement = new BlockStatement {
- Statements = {
- new NamedNode(
- "switch", new SwitchStatement {
- Expression = new IdentifierExpressionBackreference("intVar"),
- SwitchSections = { new Repeat(new AnyNode()) }
- })
- }
- }
- },
- new Repeat(new AnyNode("nonNullDefaultStmt")).ToStatement()
- },
- FalseStatement = new OptionalNode("nullStmt", new BlockStatement { Statements = { new Repeat(new AnyNode()) } })
- };
-
- public SwitchStatement TransformSwitchOnString(IfElseStatement node)
- {
- Match m = switchOnStringPattern.Match(node);
- if (!m.Success)
- return null;
- // switchVar must be the same as switchExpr; or switchExpr must be an assignment and switchVar the left side of that assignment
- if (!m.Get("switchVar").Single().IsMatch(m.Get("switchExpr").Single())) {
- AssignmentExpression assign = m.Get("switchExpr").Single() as AssignmentExpression;
- if (!(assign != null && m.Get("switchVar").Single().IsMatch(assign.Left)))
- return null;
- }
- FieldReference cachedDictField = m.Get<AstNode>("cachedDict").Single().Annotation<FieldReference>();
- if (cachedDictField == null)
- return null;
- List<Statement> dictCreation = m.Get<BlockStatement>("dictCreation").Single().Statements.ToList();
- List<KeyValuePair<string, int>> dict = BuildDictionary(dictCreation);
- SwitchStatement sw = m.Get<SwitchStatement>("switch").Single();
- sw.Expression = m.Get<Expression>("switchExpr").Single().Detach();
- foreach (SwitchSection section in sw.SwitchSections) {
- List<CaseLabel> labels = section.CaseLabels.ToList();
- section.CaseLabels.Clear();
- foreach (CaseLabel label in labels) {
- PrimitiveExpression expr = label.Expression as PrimitiveExpression;
- if (expr == null || !(expr.Value is int))
- continue;
- int val = (int)expr.Value;
- foreach (var pair in dict) {
- if (pair.Value == val)
- section.CaseLabels.Add(new CaseLabel { Expression = new PrimitiveExpression(pair.Key) });
- }
- }
- }
- if (m.Has("nullStmt")) {
- SwitchSection section = new SwitchSection();
- section.CaseLabels.Add(new CaseLabel { Expression = new NullReferenceExpression() });
- BlockStatement block = m.Get<BlockStatement>("nullStmt").Single();
- block.Statements.Add(new BreakStatement());
- section.Statements.Add(block.Detach());
- sw.SwitchSections.Add(section);
- } else if (m.Has("nonNullDefaultStmt")) {
- sw.SwitchSections.Add(
- new SwitchSection {
- CaseLabels = { new CaseLabel { Expression = new NullReferenceExpression() } },
- Statements = { new BlockStatement { new BreakStatement() } }
- });
- }
- if (m.Has("nonNullDefaultStmt")) {
- SwitchSection section = new SwitchSection();
- section.CaseLabels.Add(new CaseLabel());
- BlockStatement block = new BlockStatement();
- block.Statements.AddRange(m.Get<Statement>("nonNullDefaultStmt").Select(s => s.Detach()));
- block.Add(new BreakStatement());
- section.Statements.Add(block);
- sw.SwitchSections.Add(section);
- }
- node.ReplaceWith(sw);
- return sw;
- }
-
- List<KeyValuePair<string, int>> BuildDictionary(List<Statement> dictCreation)
- {
- if (context.Settings.ObjectOrCollectionInitializers && dictCreation.Count == 1)
- return BuildDictionaryFromInitializer(dictCreation[0]);
-
- return BuildDictionaryFromAddMethodCalls(dictCreation);
- }
-
- static readonly Statement assignInitializedDictionary = new ExpressionStatement {
- Expression = new AssignmentExpression {
- Left = new AnyNode().ToExpression(),
- Right = new ObjectCreateExpression {
- Type = new AnyNode(),
- Arguments = { new Repeat(new AnyNode()) },
- Initializer = new ArrayInitializerExpression {
- Elements = { new Repeat(new AnyNode("dictJumpTable")) }
- }
- },
- },
- };
-
- List<KeyValuePair<string, int>> BuildDictionaryFromInitializer(Statement statement)
- {
- List<KeyValuePair<string, int>> dict = new List<KeyValuePair<string, int>>();
- Match m = assignInitializedDictionary.Match(statement);
- if (!m.Success)
- return dict;
-
- foreach (ArrayInitializerExpression initializer in m.Get<ArrayInitializerExpression>("dictJumpTable")) {
- KeyValuePair<string, int> pair;
- if (TryGetPairFrom(initializer.Elements, out pair))
- dict.Add(pair);
- }
-
- return dict;
- }
-
- static List<KeyValuePair<string, int>> BuildDictionaryFromAddMethodCalls(List<Statement> dictCreation)
- {
- List<KeyValuePair<string, int>> dict = new List<KeyValuePair<string, int>>();
- for (int i = 0; i < dictCreation.Count; i++) {
- ExpressionStatement es = dictCreation[i] as ExpressionStatement;
- if (es == null)
- continue;
- InvocationExpression ie = es.Expression as InvocationExpression;
- if (ie == null)
- continue;
-
- KeyValuePair<string, int> pair;
- if (TryGetPairFrom(ie.Arguments, out pair))
- dict.Add(pair);
- }
- return dict;
- }
-
- static bool TryGetPairFrom(AstNodeCollection<Expression> expressions, out KeyValuePair<string, int> pair)
- {
- PrimitiveExpression arg1 = expressions.ElementAtOrDefault(0) as PrimitiveExpression;
- PrimitiveExpression arg2 = expressions.ElementAtOrDefault(1) as PrimitiveExpression;
- if (arg1 != null && arg2 != null && arg1.Value is string && arg2.Value is int) {
- pair = new KeyValuePair<string, int>((string)arg1.Value, (int)arg2.Value);
- return true;
- }
-
- pair = default(KeyValuePair<string, int>);
- return false;
- }
-
- #endregion
-
- #region Automatic Properties
- static readonly PropertyDeclaration automaticPropertyPattern = new PropertyDeclaration {
- Attributes = { new Repeat(new AnyNode()) },
- Modifiers = Modifiers.Any,
- ReturnType = new AnyNode(),
- PrivateImplementationType = new OptionalNode(new AnyNode()),
- Name = Pattern.AnyString,
- Getter = new Accessor {
- Attributes = { new Repeat(new AnyNode()) },
- Modifiers = Modifiers.Any,
- Body = new BlockStatement {
- new ReturnStatement {
- Expression = new AnyNode("fieldReference")
- }
- }
- },
- Setter = new Accessor {
- Attributes = { new Repeat(new AnyNode()) },
- Modifiers = Modifiers.Any,
- Body = new BlockStatement {
- new AssignmentExpression {
- Left = new Backreference("fieldReference"),
- Right = new IdentifierExpression("value")
- }
- }}};
-
- PropertyDeclaration TransformAutomaticProperties(PropertyDeclaration property)
- {
- PropertyDefinition cecilProperty = property.Annotation<PropertyDefinition>();
- if (cecilProperty == null || cecilProperty.GetMethod == null || cecilProperty.SetMethod == null)
- return null;
- if (!(cecilProperty.GetMethod.IsCompilerGenerated() && cecilProperty.SetMethod.IsCompilerGenerated()))
- return null;
- Match m = automaticPropertyPattern.Match(property);
- if (m.Success) {
- FieldDefinition field = m.Get<AstNode>("fieldReference").Single().Annotation<FieldReference>().ResolveWithinSameModule();
- if (field.IsCompilerGenerated() && field.DeclaringType == cecilProperty.DeclaringType) {
- RemoveCompilerGeneratedAttribute(property.Getter.Attributes);
- RemoveCompilerGeneratedAttribute(property.Setter.Attributes);
- property.Getter.Body = null;
- property.Setter.Body = null;
- }
- }
- // Since the event instance is not changed, we can continue in the visitor as usual, so return null
- return null;
- }
-
- void RemoveCompilerGeneratedAttribute(AstNodeCollection<AttributeSection> attributeSections)
- {
- foreach (AttributeSection section in attributeSections) {
- foreach (var attr in section.Attributes) {
- TypeReference tr = attr.Type.Annotation<TypeReference>();
- if (tr != null && tr.Namespace == "System.Runtime.CompilerServices" && tr.Name == "CompilerGeneratedAttribute") {
- attr.Remove();
- }
- }
- if (section.Attributes.Count == 0)
- section.Remove();
- }
- }
- #endregion
-
- #region Automatic Events
- static readonly Accessor automaticEventPatternV4 = new Accessor {
- Attributes = { new Repeat(new AnyNode()) },
- Body = new BlockStatement {
- new VariableDeclarationStatement { Type = new AnyNode("type"), Variables = { new AnyNode() } },
- new VariableDeclarationStatement { Type = new Backreference("type"), Variables = { new AnyNode() } },
- new VariableDeclarationStatement { Type = new Backreference("type"), Variables = { new AnyNode() } },
- new AssignmentExpression {
- Left = new NamedNode("var1", new IdentifierExpression(Pattern.AnyString)),
- Operator = AssignmentOperatorType.Assign,
- Right = new NamedNode(
- "field",
- new MemberReferenceExpression {
- Target = new Choice { new ThisReferenceExpression(), new TypeReferenceExpression { Type = new AnyNode() } },
- MemberName = Pattern.AnyString
- })
- },
- new DoWhileStatement {
- EmbeddedStatement = new BlockStatement {
- new AssignmentExpression(new NamedNode("var2", new IdentifierExpression(Pattern.AnyString)), new IdentifierExpressionBackreference("var1")),
- new AssignmentExpression {
- Left = new NamedNode("var3", new IdentifierExpression(Pattern.AnyString)),
- Operator = AssignmentOperatorType.Assign,
- Right = new AnyNode("delegateCombine").ToExpression().Invoke(
- new IdentifierExpressionBackreference("var2"),
- new IdentifierExpression("value")
- ).CastTo(new Backreference("type"))
- },
- new AssignmentExpression {
- Left = new IdentifierExpressionBackreference("var1"),
- Right = new TypePattern(typeof(System.Threading.Interlocked)).ToType().Invoke(
- "CompareExchange",
- new AstType[] { new Backreference("type") }, // type argument
- new Expression[] { // arguments
- new DirectionExpression { FieldDirection = FieldDirection.Ref, Expression = new Backreference("field") },
- new IdentifierExpressionBackreference("var3"),
- new IdentifierExpressionBackreference("var2")
- }
- )}
- },
- Condition = new BinaryOperatorExpression {
- Left = new IdentifierExpressionBackreference("var1"),
- Operator = BinaryOperatorType.InEquality,
- Right = new IdentifierExpressionBackreference("var2")
- }}
- }};
-
- bool CheckAutomaticEventV4Match(Match m, CustomEventDeclaration ev, bool isAddAccessor)
- {
- if (!m.Success)
- return false;
- if (m.Get<MemberReferenceExpression>("field").Single().MemberName != ev.Name)
- return false; // field name must match event name
- if (!ev.ReturnType.IsMatch(m.Get("type").Single()))
- return false; // variable types must match event type
- var combineMethod = m.Get<AstNode>("delegateCombine").Single().Parent.Annotation<MethodReference>();
- if (combineMethod == null || combineMethod.Name != (isAddAccessor ? "Combine" : "Remove"))
- return false;
- return combineMethod.DeclaringType.FullName == "System.Delegate";
- }
-
- EventDeclaration TransformAutomaticEvents(CustomEventDeclaration ev)
- {
- Match m1 = automaticEventPatternV4.Match(ev.AddAccessor);
- if (!CheckAutomaticEventV4Match(m1, ev, true))
- return null;
- Match m2 = automaticEventPatternV4.Match(ev.RemoveAccessor);
- if (!CheckAutomaticEventV4Match(m2, ev, false))
- return null;
- EventDeclaration ed = new EventDeclaration();
- ev.Attributes.MoveTo(ed.Attributes);
- foreach (var attr in ev.AddAccessor.Attributes) {
- attr.AttributeTarget = "method";
- ed.Attributes.Add(attr.Detach());
- }
- ed.ReturnType = ev.ReturnType.Detach();
- ed.Modifiers = ev.Modifiers;
- ed.Variables.Add(new VariableInitializer(ev.Name));
- ed.CopyAnnotationsFrom(ev);
-
- EventDefinition eventDef = ev.Annotation<EventDefinition>();
- if (eventDef != null) {
- FieldDefinition field = eventDef.DeclaringType.Fields.FirstOrDefault(f => f.Name == ev.Name);
- if (field != null) {
- ed.AddAnnotation(field);
- AstBuilder.ConvertAttributes(ed, field, "field");
- }
- }
-
- ev.ReplaceWith(ed);
- return ed;
- }
- #endregion
-
- #region Destructor
- static readonly MethodDeclaration destructorPattern = new MethodDeclaration {
- Attributes = { new Repeat(new AnyNode()) },
- Modifiers = Modifiers.Any,
- ReturnType = new PrimitiveType("void"),
- Name = "Finalize",
- Body = new BlockStatement {
- new TryCatchStatement {
- TryBlock = new AnyNode("body"),
- FinallyBlock = new BlockStatement {
- new BaseReferenceExpression().Invoke("Finalize")
- }
- }
- }
- };
-
- DestructorDeclaration TransformDestructor(MethodDeclaration methodDef)
- {
- Match m = destructorPattern.Match(methodDef);
- if (m.Success) {
- DestructorDeclaration dd = new DestructorDeclaration();
- methodDef.Attributes.MoveTo(dd.Attributes);
- dd.Modifiers = methodDef.Modifiers & ~(Modifiers.Protected | Modifiers.Override);
- dd.Body = m.Get<BlockStatement>("body").Single().Detach();
- dd.Name = AstBuilder.CleanName(context.CurrentType.Name);
- methodDef.ReplaceWith(dd);
- return dd;
- }
- return null;
- }
- #endregion
-
- #region Try-Catch-Finally
- static readonly TryCatchStatement tryCatchFinallyPattern = new TryCatchStatement {
- TryBlock = new BlockStatement {
- new TryCatchStatement {
- TryBlock = new AnyNode(),
- CatchClauses = { new Repeat(new AnyNode()) }
- }
- },
- FinallyBlock = new AnyNode()
- };
-
- /// <summary>
- /// Simplify nested 'try { try {} catch {} } finally {}'.
- /// This transformation must run after the using/lock tranformations.
- /// </summary>
- TryCatchStatement TransformTryCatchFinally(TryCatchStatement tryFinally)
- {
- if (tryCatchFinallyPattern.IsMatch(tryFinally)) {
- TryCatchStatement tryCatch = (TryCatchStatement)tryFinally.TryBlock.Statements.Single();
- tryFinally.TryBlock = tryCatch.TryBlock.Detach();
- tryCatch.CatchClauses.MoveTo(tryFinally.CatchClauses);
- }
- // Since the tryFinally instance is not changed, we can continue in the visitor as usual, so return null
- return null;
- }
- #endregion
-
- #region Simplify cascading if-else-if statements
- static readonly IfElseStatement cascadingIfElsePattern = new IfElseStatement
- {
- Condition = new AnyNode(),
- TrueStatement = new AnyNode(),
- FalseStatement = new BlockStatement {
- Statements = {
- new NamedNode(
- "nestedIfStatement",
- new IfElseStatement {
- Condition = new AnyNode(),
- TrueStatement = new AnyNode(),
- FalseStatement = new OptionalNode(new AnyNode())
- }
- )
- }
- }
- };
-
- AstNode SimplifyCascadingIfElseStatements(IfElseStatement node)
- {
- Match m = cascadingIfElsePattern.Match(node);
- if (m.Success) {
- IfElseStatement elseIf = m.Get<IfElseStatement>("nestedIfStatement").Single();
- node.FalseStatement = elseIf.Detach();
- }
-
- return null;
- }
- #endregion
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs b/ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs
deleted file mode 100644
index 193c5e69..00000000
--- a/ICSharpCode.Decompiler/Ast/Transforms/PushNegation.cs
+++ /dev/null
@@ -1,164 +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.NRefactory.CSharp;
-using ICSharpCode.NRefactory.PatternMatching;
-
-namespace ICSharpCode.Decompiler.Ast.Transforms
-{
- public class PushNegation: DepthFirstAstVisitor<object, object>, IAstTransform
- {
- sealed class LiftedOperator { }
- /// <summary>
- /// Annotation for lifted operators that cannot be transformed by PushNegation
- /// </summary>
- public static readonly object LiftedOperatorAnnotation = new LiftedOperator();
-
- public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unary, object data)
- {
- // lifted operators can't be transformed
- if (unary.Annotation<LiftedOperator>() != null || unary.Expression.Annotation<LiftedOperator>() != null)
- return base.VisitUnaryOperatorExpression(unary, data);
-
- // Remove double negation
- // !!a
- if (unary.Operator == UnaryOperatorType.Not &&
- unary.Expression is UnaryOperatorExpression &&
- (unary.Expression as UnaryOperatorExpression).Operator == UnaryOperatorType.Not)
- {
- AstNode newNode = (unary.Expression as UnaryOperatorExpression).Expression;
- unary.ReplaceWith(newNode);
- return newNode.AcceptVisitor(this, data);
- }
-
- // Push through binary operation
- // !((a) op (b))
- BinaryOperatorExpression binaryOp = unary.Expression as BinaryOperatorExpression;
- if (unary.Operator == UnaryOperatorType.Not && binaryOp != null) {
- bool successful = true;
- switch (binaryOp.Operator) {
- case BinaryOperatorType.Equality:
- binaryOp.Operator = BinaryOperatorType.InEquality;
- break;
- case BinaryOperatorType.InEquality:
- binaryOp.Operator = BinaryOperatorType.Equality;
- break;
- case BinaryOperatorType.GreaterThan: // TODO: these are invalid for floats (stupid NaN)
- binaryOp.Operator = BinaryOperatorType.LessThanOrEqual;
- break;
- case BinaryOperatorType.GreaterThanOrEqual:
- binaryOp.Operator = BinaryOperatorType.LessThan;
- break;
- case BinaryOperatorType.LessThanOrEqual:
- binaryOp.Operator = BinaryOperatorType.GreaterThan;
- break;
- case BinaryOperatorType.LessThan:
- binaryOp.Operator = BinaryOperatorType.GreaterThanOrEqual;
- break;
- default:
- successful = false;
- break;
- }
- if (successful) {
- unary.ReplaceWith(binaryOp);
- return binaryOp.AcceptVisitor(this, data);
- }
-
- successful = true;
- switch (binaryOp.Operator) {
- case BinaryOperatorType.ConditionalAnd:
- binaryOp.Operator = BinaryOperatorType.ConditionalOr;
- break;
- case BinaryOperatorType.ConditionalOr:
- binaryOp.Operator = BinaryOperatorType.ConditionalAnd;
- break;
- default:
- successful = false;
- break;
- }
- if (successful) {
- binaryOp.Left.ReplaceWith(e => new UnaryOperatorExpression(UnaryOperatorType.Not, e));
- binaryOp.Right.ReplaceWith(e => new UnaryOperatorExpression(UnaryOperatorType.Not, e));
- unary.ReplaceWith(binaryOp);
- return binaryOp.AcceptVisitor(this, data);
- }
- }
- return base.VisitUnaryOperatorExpression(unary, data);
- }
-
- readonly static AstNode asCastIsNullPattern = new BinaryOperatorExpression(
- new AnyNode("expr").ToExpression().CastAs(new AnyNode("type")),
- BinaryOperatorType.Equality,
- new NullReferenceExpression()
- );
-
- readonly static AstNode asCastIsNotNullPattern = new BinaryOperatorExpression(
- new AnyNode("expr").ToExpression().CastAs(new AnyNode("type")),
- BinaryOperatorType.InEquality,
- new NullReferenceExpression()
- );
-
- public override object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data)
- {
- // lifted operators can't be transformed
- if (binaryOperatorExpression.Annotation<LiftedOperator>() != null)
- return base.VisitBinaryOperatorExpression(binaryOperatorExpression, data);
-
- BinaryOperatorType op = binaryOperatorExpression.Operator;
- bool? rightOperand = null;
- if (binaryOperatorExpression.Right is PrimitiveExpression)
- rightOperand = ((PrimitiveExpression)binaryOperatorExpression.Right).Value as bool?;
- if (op == BinaryOperatorType.Equality && rightOperand == true || op == BinaryOperatorType.InEquality && rightOperand == false) {
- // 'b == true' or 'b != false' is useless
- binaryOperatorExpression.Left.AcceptVisitor(this, data);
- binaryOperatorExpression.ReplaceWith(binaryOperatorExpression.Left);
- return null;
- } else if (op == BinaryOperatorType.Equality && rightOperand == false || op == BinaryOperatorType.InEquality && rightOperand == true) {
- // 'b == false' or 'b != true' is a negation:
- Expression left = binaryOperatorExpression.Left;
- left.Remove();
- UnaryOperatorExpression uoe = new UnaryOperatorExpression(UnaryOperatorType.Not, left);
- binaryOperatorExpression.ReplaceWith(uoe);
- return uoe.AcceptVisitor(this, data);
- } else {
- bool negate = false;
- Match m = asCastIsNotNullPattern.Match(binaryOperatorExpression);
- if (!m.Success) {
- m = asCastIsNullPattern.Match(binaryOperatorExpression);
- negate = true;
- }
- if (m.Success) {
- Expression expr = m.Get<Expression>("expr").Single().Detach().IsType(m.Get<AstType>("type").Single().Detach());
- if (negate)
- expr = new UnaryOperatorExpression(UnaryOperatorType.Not, expr);
- binaryOperatorExpression.ReplaceWith(expr);
- return expr.AcceptVisitor(this, data);
- } else {
- return base.VisitBinaryOperatorExpression(binaryOperatorExpression, data);
- }
- }
- }
- void IAstTransform.Run(AstNode node)
- {
- node.AcceptVisitor(this, null);
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs b/ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs
deleted file mode 100644
index 6a3f8f97..00000000
--- a/ICSharpCode.Decompiler/Ast/Transforms/ReplaceMethodCallsWithOperators.cs
+++ /dev/null
@@ -1,356 +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 System.Reflection;
-using ICSharpCode.NRefactory.PatternMatching;
-using Mono.Cecil;
-using Ast = ICSharpCode.NRefactory.CSharp;
-using ICSharpCode.NRefactory.CSharp;
-
-namespace ICSharpCode.Decompiler.Ast.Transforms
-{
- /// <summary>
- /// Replaces method calls with the appropriate operator expressions.
- /// Also simplifies "x = x op y" into "x op= y" where possible.
- /// </summary>
- public class ReplaceMethodCallsWithOperators : DepthFirstAstVisitor<object, object>, IAstTransform
- {
- static readonly MemberReferenceExpression typeHandleOnTypeOfPattern = new MemberReferenceExpression {
- Target = new Choice {
- new TypeOfExpression(new AnyNode()),
- new UndocumentedExpression { UndocumentedExpressionType = UndocumentedExpressionType.RefType, Arguments = { new AnyNode() } }
- },
- MemberName = "TypeHandle"
- };
-
- DecompilerContext context;
-
- public ReplaceMethodCallsWithOperators(DecompilerContext context)
- {
- this.context = context;
- }
-
- public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data)
- {
- base.VisitInvocationExpression(invocationExpression, data);
- ProcessInvocationExpression(invocationExpression);
- return null;
- }
-
- internal static void ProcessInvocationExpression(InvocationExpression invocationExpression)
- {
- MethodReference methodRef = invocationExpression.Annotation<MethodReference>();
- if (methodRef == null)
- return;
- var arguments = invocationExpression.Arguments.ToArray();
-
- // Reduce "String.Concat(a, b)" to "a + b"
- if (methodRef.Name == "Concat" && methodRef.DeclaringType.FullName == "System.String" && arguments.Length >= 2)
- {
- invocationExpression.Arguments.Clear(); // detach arguments from invocationExpression
- Expression expr = arguments[0];
- for (int i = 1; i < arguments.Length; i++) {
- expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Add, arguments[i]);
- }
- invocationExpression.ReplaceWith(expr);
- return;
- }
-
- switch (methodRef.FullName) {
- case "System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)":
- if (arguments.Length == 1) {
- if (typeHandleOnTypeOfPattern.IsMatch(arguments[0])) {
- invocationExpression.ReplaceWith(((MemberReferenceExpression)arguments[0]).Target);
- return;
- }
- }
- break;
- case "System.Reflection.FieldInfo System.Reflection.FieldInfo::GetFieldFromHandle(System.RuntimeFieldHandle)":
- if (arguments.Length == 1) {
- MemberReferenceExpression mre = arguments[0] as MemberReferenceExpression;
- if (mre != null && mre.MemberName == "FieldHandle" && mre.Target.Annotation<LdTokenAnnotation>() != null) {
- invocationExpression.ReplaceWith(mre.Target);
- return;
- }
- }
- break;
- case "System.Reflection.FieldInfo System.Reflection.FieldInfo::GetFieldFromHandle(System.RuntimeFieldHandle,System.RuntimeTypeHandle)":
- if (arguments.Length == 2) {
- MemberReferenceExpression mre1 = arguments[0] as MemberReferenceExpression;
- MemberReferenceExpression mre2 = arguments[1] as MemberReferenceExpression;
- if (mre1 != null && mre1.MemberName == "FieldHandle" && mre1.Target.Annotation<LdTokenAnnotation>() != null) {
- if (mre2 != null && mre2.MemberName == "TypeHandle" && mre2.Target is TypeOfExpression) {
- Expression oldArg = ((InvocationExpression)mre1.Target).Arguments.Single();
- FieldReference field = oldArg.Annotation<FieldReference>();
- if (field != null) {
- AstType declaringType = ((TypeOfExpression)mre2.Target).Type.Detach();
- oldArg.ReplaceWith(declaringType.Member(field.Name).WithAnnotation(field));
- invocationExpression.ReplaceWith(mre1.Target);
- return;
- }
- }
- }
- }
- break;
- }
-
- BinaryOperatorType? bop = GetBinaryOperatorTypeFromMetadataName(methodRef.Name);
- if (bop != null && arguments.Length == 2) {
- invocationExpression.Arguments.Clear(); // detach arguments from invocationExpression
- invocationExpression.ReplaceWith(
- new BinaryOperatorExpression(arguments[0], bop.Value, arguments[1]).WithAnnotation(methodRef)
- );
- return;
- }
- UnaryOperatorType? uop = GetUnaryOperatorTypeFromMetadataName(methodRef.Name);
- if (uop != null && arguments.Length == 1) {
- arguments[0].Remove(); // detach argument
- invocationExpression.ReplaceWith(
- new UnaryOperatorExpression(uop.Value, arguments[0]).WithAnnotation(methodRef)
- );
- return;
- }
- if (methodRef.Name == "op_Explicit" && arguments.Length == 1) {
- arguments[0].Remove(); // detach argument
- invocationExpression.ReplaceWith(
- arguments[0].CastTo(AstBuilder.ConvertType(methodRef.ReturnType, methodRef.MethodReturnType))
- .WithAnnotation(methodRef)
- );
- return;
- }
- if (methodRef.Name == "op_Implicit" && arguments.Length == 1) {
- invocationExpression.ReplaceWith(arguments[0]);
- return;
- }
- if (methodRef.Name == "op_True" && arguments.Length == 1 && invocationExpression.Role == Roles.Condition) {
- invocationExpression.ReplaceWith(arguments[0]);
- return;
- }
-
- return;
- }
-
- static BinaryOperatorType? GetBinaryOperatorTypeFromMetadataName(string name)
- {
- switch (name) {
- case "op_Addition":
- return BinaryOperatorType.Add;
- case "op_Subtraction":
- return BinaryOperatorType.Subtract;
- case "op_Multiply":
- return BinaryOperatorType.Multiply;
- case "op_Division":
- return BinaryOperatorType.Divide;
- case "op_Modulus":
- return BinaryOperatorType.Modulus;
- case "op_BitwiseAnd":
- return BinaryOperatorType.BitwiseAnd;
- case "op_BitwiseOr":
- return BinaryOperatorType.BitwiseOr;
- case "op_ExclusiveOr":
- return BinaryOperatorType.ExclusiveOr;
- case "op_LeftShift":
- return BinaryOperatorType.ShiftLeft;
- case "op_RightShift":
- return BinaryOperatorType.ShiftRight;
- case "op_Equality":
- return BinaryOperatorType.Equality;
- case "op_Inequality":
- return BinaryOperatorType.InEquality;
- case "op_LessThan":
- return BinaryOperatorType.LessThan;
- case "op_LessThanOrEqual":
- return BinaryOperatorType.LessThanOrEqual;
- case "op_GreaterThan":
- return BinaryOperatorType.GreaterThan;
- case "op_GreaterThanOrEqual":
- return BinaryOperatorType.GreaterThanOrEqual;
- default:
- return null;
- }
- }
-
- static UnaryOperatorType? GetUnaryOperatorTypeFromMetadataName(string name)
- {
- switch (name) {
- case "op_LogicalNot":
- return UnaryOperatorType.Not;
- case "op_OnesComplement":
- return UnaryOperatorType.BitNot;
- case "op_UnaryNegation":
- return UnaryOperatorType.Minus;
- case "op_UnaryPlus":
- return UnaryOperatorType.Plus;
- case "op_Increment":
- return UnaryOperatorType.Increment;
- case "op_Decrement":
- return UnaryOperatorType.Decrement;
- default:
- return null;
- }
- }
-
- /// <summary>
- /// This annotation is used to convert a compound assignment "a += 2;" or increment operator "a++;"
- /// back to the original "a = a + 2;". This is sometimes necessary when the checked/unchecked semantics
- /// cannot be guaranteed otherwise (see CheckedUnchecked.ForWithCheckedInitializerAndUncheckedIterator test)
- /// </summary>
- public class RestoreOriginalAssignOperatorAnnotation
- {
- readonly BinaryOperatorExpression binaryOperatorExpression;
-
- public RestoreOriginalAssignOperatorAnnotation(BinaryOperatorExpression binaryOperatorExpression)
- {
- this.binaryOperatorExpression = binaryOperatorExpression;
- }
-
- public AssignmentExpression Restore(Expression expression)
- {
- expression.RemoveAnnotations<RestoreOriginalAssignOperatorAnnotation>();
- AssignmentExpression assign = expression as AssignmentExpression;
- if (assign == null) {
- UnaryOperatorExpression uoe = (UnaryOperatorExpression)expression;
- assign = new AssignmentExpression(uoe.Expression.Detach(), new PrimitiveExpression(1));
- } else {
- assign.Operator = AssignmentOperatorType.Assign;
- }
- binaryOperatorExpression.Right = assign.Right.Detach();
- assign.Right = binaryOperatorExpression;
- return assign;
- }
- }
-
- public override object VisitAssignmentExpression(AssignmentExpression assignment, object data)
- {
- base.VisitAssignmentExpression(assignment, data);
- // Combine "x = x op y" into "x op= y"
- BinaryOperatorExpression binary = assignment.Right as BinaryOperatorExpression;
- if (binary != null && assignment.Operator == AssignmentOperatorType.Assign) {
- if (CanConvertToCompoundAssignment(assignment.Left) && assignment.Left.IsMatch(binary.Left)) {
- assignment.Operator = GetAssignmentOperatorForBinaryOperator(binary.Operator);
- if (assignment.Operator != AssignmentOperatorType.Assign) {
- // If we found a shorter operator, get rid of the BinaryOperatorExpression:
- assignment.CopyAnnotationsFrom(binary);
- assignment.Right = binary.Right;
- assignment.AddAnnotation(new RestoreOriginalAssignOperatorAnnotation(binary));
- }
- }
- }
- if (context.Settings.IntroduceIncrementAndDecrement && (assignment.Operator == AssignmentOperatorType.Add || assignment.Operator == AssignmentOperatorType.Subtract)) {
- // detect increment/decrement
- if (assignment.Right.IsMatch(new PrimitiveExpression(1))) {
- // only if it's not a custom operator
- if (assignment.Annotation<MethodReference>() == null) {
- UnaryOperatorType type;
- // When the parent is an expression statement, pre- or post-increment doesn't matter;
- // so we can pick post-increment which is more commonly used (for (int i = 0; i < x; i++))
- if (assignment.Parent is ExpressionStatement)
- type = (assignment.Operator == AssignmentOperatorType.Add) ? UnaryOperatorType.PostIncrement : UnaryOperatorType.PostDecrement;
- else
- type = (assignment.Operator == AssignmentOperatorType.Add) ? UnaryOperatorType.Increment : UnaryOperatorType.Decrement;
- assignment.ReplaceWith(new UnaryOperatorExpression(type, assignment.Left.Detach()).CopyAnnotationsFrom(assignment));
- }
- }
- }
- return null;
- }
-
- public static AssignmentOperatorType GetAssignmentOperatorForBinaryOperator(BinaryOperatorType bop)
- {
- switch (bop) {
- case BinaryOperatorType.Add:
- return AssignmentOperatorType.Add;
- case BinaryOperatorType.Subtract:
- return AssignmentOperatorType.Subtract;
- case BinaryOperatorType.Multiply:
- return AssignmentOperatorType.Multiply;
- case BinaryOperatorType.Divide:
- return AssignmentOperatorType.Divide;
- case BinaryOperatorType.Modulus:
- return AssignmentOperatorType.Modulus;
- case BinaryOperatorType.ShiftLeft:
- return AssignmentOperatorType.ShiftLeft;
- case BinaryOperatorType.ShiftRight:
- return AssignmentOperatorType.ShiftRight;
- case BinaryOperatorType.BitwiseAnd:
- return AssignmentOperatorType.BitwiseAnd;
- case BinaryOperatorType.BitwiseOr:
- return AssignmentOperatorType.BitwiseOr;
- case BinaryOperatorType.ExclusiveOr:
- return AssignmentOperatorType.ExclusiveOr;
- default:
- return AssignmentOperatorType.Assign;
- }
- }
-
- static bool CanConvertToCompoundAssignment(Expression left)
- {
- MemberReferenceExpression mre = left as MemberReferenceExpression;
- if (mre != null)
- return IsWithoutSideEffects(mre.Target);
- IndexerExpression ie = left as IndexerExpression;
- if (ie != null)
- return IsWithoutSideEffects(ie.Target) && ie.Arguments.All(IsWithoutSideEffects);
- UnaryOperatorExpression uoe = left as UnaryOperatorExpression;
- if (uoe != null && uoe.Operator == UnaryOperatorType.Dereference)
- return IsWithoutSideEffects(uoe.Expression);
- return IsWithoutSideEffects(left);
- }
-
- static bool IsWithoutSideEffects(Expression left)
- {
- return left is ThisReferenceExpression || left is IdentifierExpression || left is TypeReferenceExpression || left is BaseReferenceExpression;
- }
-
- static readonly Expression getMethodOrConstructorFromHandlePattern =
- new TypePattern(typeof(MethodBase)).ToType().Invoke(
- "GetMethodFromHandle",
- new NamedNode("ldtokenNode", new LdTokenPattern("method")).ToExpression().Member("MethodHandle"),
- new OptionalNode(new TypeOfExpression(new AnyNode("declaringType")).Member("TypeHandle"))
- ).CastTo(new Choice {
- new TypePattern(typeof(MethodInfo)),
- new TypePattern(typeof(ConstructorInfo))
- });
-
- public override object VisitCastExpression(CastExpression castExpression, object data)
- {
- base.VisitCastExpression(castExpression, data);
- // Handle methodof
- Match m = getMethodOrConstructorFromHandlePattern.Match(castExpression);
- if (m.Success) {
- MethodReference method = m.Get<AstNode>("method").Single().Annotation<MethodReference>();
- if (m.Has("declaringType")) {
- Expression newNode = m.Get<AstType>("declaringType").Single().Detach().Member(method.Name);
- newNode = newNode.Invoke(method.Parameters.Select(p => new TypeReferenceExpression(AstBuilder.ConvertType(p.ParameterType, p))));
- newNode.AddAnnotation(method);
- m.Get<AstNode>("method").Single().ReplaceWith(newNode);
- }
- castExpression.ReplaceWith(m.Get<AstNode>("ldtokenNode").Single());
- }
- return null;
- }
-
- void IAstTransform.Run(AstNode node)
- {
- node.AcceptVisitor(this, null);
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs b/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs
deleted file mode 100644
index 3091a109..00000000
--- a/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs
+++ /dev/null
@@ -1,65 +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.Threading;
-using ICSharpCode.NRefactory.CSharp;
-
-namespace ICSharpCode.Decompiler.Ast.Transforms
-{
- public interface IAstTransform
- {
- void Run(AstNode compilationUnit);
- }
-
- public static class TransformationPipeline
- {
- public static IAstTransform[] CreatePipeline(DecompilerContext context)
- {
- return new IAstTransform[] {
- new PushNegation(),
- new DelegateConstruction(context),
- new PatternStatementTransform(context),
- new ReplaceMethodCallsWithOperators(context),
- new IntroduceUnsafeModifier(),
- new AddCheckedBlocks(),
- new DeclareVariables(context), // should run after most transforms that modify statements
- new ConvertConstructorCallIntoInitializer(), // must run after DeclareVariables
- new DecimalConstantTransform(),
- new IntroduceUsingDeclarations(context),
- new IntroduceExtensionMethods(context), // must run after IntroduceUsingDeclarations
- new IntroduceQueryExpressions(context), // must run after IntroduceExtensionMethods
- new CombineQueryExpressions(context),
- new FlattenSwitchBlocks(),
- };
- }
-
- public static void RunTransformationsUntil(AstNode node, Predicate<IAstTransform> abortCondition, DecompilerContext context)
- {
- if (node == null)
- return;
-
- foreach (var transform in CreatePipeline(context)) {
- context.CancellationToken.ThrowIfCancellationRequested();
- if (abortCondition != null && abortCondition(transform))
- return;
- transform.Run(node);
- }
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs b/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs
deleted file mode 100644
index 19e7ff24..00000000
--- a/ICSharpCode.Decompiler/Ast/TypesHierarchyHelpers.cs
+++ /dev/null
@@ -1,536 +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.Collections.ObjectModel;
-using System.Linq;
-using System.Text;
-using Mono.Cecil;
-
-namespace ICSharpCode.Decompiler.Ast
-{
- public static class TypesHierarchyHelpers
- {
- public static bool IsBaseType(TypeDefinition baseType, TypeDefinition derivedType, bool resolveTypeArguments)
- {
- if (resolveTypeArguments)
- return BaseTypes(derivedType).Any(t => t.Item == baseType);
- else {
- var comparableBaseType = baseType.Resolve();
- if (comparableBaseType == null)
- return false;
- while (derivedType.BaseType != null) {
- var resolvedBaseType = derivedType.BaseType.Resolve();
- if (resolvedBaseType == null)
- return false;
- if (comparableBaseType == resolvedBaseType)
- return true;
- derivedType = resolvedBaseType;
- }
- return false;
- }
- }
-
- /// <summary>
- /// Determines whether one method overrides or hides another method.
- /// </summary>
- /// <param name="parentMethod">The method declared in a base type.</param>
- /// <param name="childMethod">The method declared in a derived type.</param>
- /// <returns>true if <paramref name="childMethod"/> hides or overrides <paramref name="parentMethod"/>,
- /// otherwise false.</returns>
- public static bool IsBaseMethod(MethodDefinition parentMethod, MethodDefinition childMethod)
- {
- if (parentMethod == null)
- throw new ArgumentNullException("parentMethod");
- if (childMethod == null)
- throw new ArgumentNullException("childMethod");
-
- if (parentMethod.Name != childMethod.Name)
- return false;
-
- if (parentMethod.HasParameters || childMethod.HasParameters)
- if (!parentMethod.HasParameters || !childMethod.HasParameters || parentMethod.Parameters.Count != childMethod.Parameters.Count)
- return false;
-
- return FindBaseMethods(childMethod).Any(m => m == parentMethod);// || (parentMethod.HasGenericParameters && m.);
- }
-
- /// <summary>
- /// Determines whether a property overrides or hides another property.
- /// </summary>
- /// <param name="parentProperty">The property declared in a base type.</param>
- /// <param name="childProperty">The property declared in a derived type.</param>
- /// <returns>true if the <paramref name="childProperty"/> hides or overrides <paramref name="parentProperty"/>,
- /// otherwise false.</returns>
- public static bool IsBaseProperty(PropertyDefinition parentProperty, PropertyDefinition childProperty)
- {
- if (parentProperty == null)
- throw new ArgumentNullException("parentProperty");
- if (childProperty == null)
- throw new ArgumentNullException("childProperty");
-
- if (parentProperty.Name != childProperty.Name)
- return false;
-
- if (parentProperty.HasParameters || childProperty.HasParameters)
- if (!parentProperty.HasParameters || !childProperty.HasParameters || parentProperty.Parameters.Count != childProperty.Parameters.Count)
- return false;
-
- return FindBaseProperties(childProperty).Any(m => m == parentProperty);
- }
-
- public static bool IsBaseEvent(EventDefinition parentEvent, EventDefinition childEvent)
- {
- if (parentEvent.Name != childEvent.Name)
- return false;
-
- return FindBaseEvents(childEvent).Any(m => m == parentEvent);
- }
-
- /// <summary>
- /// Finds all methods from base types overridden or hidden by the specified method.
- /// </summary>
- /// <param name="method">The method which overrides or hides methods from base types.</param>
- /// <returns>Methods overriden or hidden by the specified method.</returns>
- public static IEnumerable<MethodDefinition> FindBaseMethods(MethodDefinition method)
- {
- if (method == null)
- throw new ArgumentNullException("method");
-
- var typeContext = CreateGenericContext(method.DeclaringType);
- var gMethod = typeContext.ApplyTo(method);
-
- foreach (var baseType in BaseTypes(method.DeclaringType))
- foreach (var baseMethod in baseType.Item.Methods)
- if (MatchMethod(baseType.ApplyTo(baseMethod), gMethod) && IsVisibleFromDerived(baseMethod, method.DeclaringType)) {
- yield return baseMethod;
- if (baseMethod.IsNewSlot == baseMethod.IsVirtual)
- yield break;
- }
- }
-
- /// <summary>
- /// Finds all properties from base types overridden or hidden by the specified property.
- /// </summary>
- /// <param name="property">The property which overrides or hides properties from base types.</param>
- /// <returns>Properties overriden or hidden by the specified property.</returns>
- public static IEnumerable<PropertyDefinition> FindBaseProperties(PropertyDefinition property)
- {
- if (property == null)
- throw new ArgumentNullException("property");
-
- if ((property.GetMethod ?? property.SetMethod).HasOverrides)
- yield break;
-
- var typeContext = CreateGenericContext(property.DeclaringType);
- var gProperty = typeContext.ApplyTo(property);
- bool isIndexer = property.IsIndexer();
-
- foreach (var baseType in BaseTypes(property.DeclaringType))
- foreach (var baseProperty in baseType.Item.Properties)
- if (MatchProperty(baseType.ApplyTo(baseProperty), gProperty)
- && IsVisibleFromDerived(baseProperty, property.DeclaringType)) {
- if (isIndexer != baseProperty.IsIndexer())
- continue;
- yield return baseProperty;
- var anyPropertyAccessor = baseProperty.GetMethod ?? baseProperty.SetMethod;
- if (anyPropertyAccessor.IsNewSlot == anyPropertyAccessor.IsVirtual)
- yield break;
- }
- }
-
- public static IEnumerable<EventDefinition> FindBaseEvents(EventDefinition eventDef)
- {
- if (eventDef == null)
- throw new ArgumentNullException("eventDef");
-
- var typeContext = CreateGenericContext(eventDef.DeclaringType);
- var gEvent = typeContext.ApplyTo(eventDef);
-
- foreach (var baseType in BaseTypes(eventDef.DeclaringType))
- foreach (var baseEvent in baseType.Item.Events)
- if (MatchEvent(baseType.ApplyTo(baseEvent), gEvent) && IsVisibleFromDerived(baseEvent, eventDef.DeclaringType)) {
- yield return baseEvent;
- var anyEventAccessor = baseEvent.AddMethod ?? baseEvent.RemoveMethod;
- if (anyEventAccessor.IsNewSlot == anyEventAccessor.IsVirtual)
- yield break;
- }
-
- }
-
- /// <summary>
- /// Determinates whether member of the base type is visible from a derived type.
- /// </summary>
- /// <param name="baseMember">The member which visibility is checked.</param>
- /// <param name="derivedType">The derived type.</param>
- /// <returns>true if the member is visible from derived type, othewise false.</returns>
- public static bool IsVisibleFromDerived(IMemberDefinition baseMember, TypeDefinition derivedType)
- {
- if (baseMember == null)
- throw new ArgumentNullException("baseMember");
- if (derivedType == null)
- throw new ArgumentNullException("derivedType");
-
- MethodAttributes attrs = GetAccessAttributes(baseMember) & MethodAttributes.MemberAccessMask;
- if (attrs == MethodAttributes.Private)
- return false;
-
- if (baseMember.DeclaringType.Module == derivedType.Module)
- return true;
-
- if (attrs == MethodAttributes.Assembly || attrs == MethodAttributes.FamANDAssem) {
- var derivedTypeAsm = derivedType.Module.Assembly;
- var asm = baseMember.DeclaringType.Module.Assembly;
-
- if (asm.HasCustomAttributes) {
- var attributes = asm.CustomAttributes
- .Where(attr => attr.AttributeType.FullName == "System.Runtime.CompilerServices.InternalsVisibleToAttribute");
- foreach (var attribute in attributes) {
- string assemblyName = attribute.ConstructorArguments[0].Value as string;
- assemblyName = assemblyName.Split(',')[0]; // strip off any public key info
- if (assemblyName == derivedTypeAsm.Name.Name)
- return true;
- }
- }
-
- return false;
- }
-
- return true;
- }
-
- static MethodAttributes GetAccessAttributes(IMemberDefinition member)
- {
- var fld = member as FieldDefinition;
- if (fld != null)
- return (MethodAttributes)fld.Attributes;
-
- var method = member as MethodDefinition;
- if (method != null)
- return method.Attributes;
-
- var prop = member as PropertyDefinition;
- if (prop != null) {
- return (prop.GetMethod ?? prop.SetMethod).Attributes;
- }
-
- var evnt = member as EventDefinition;
- if (evnt != null) {
- return (evnt.AddMethod ?? evnt.RemoveMethod).Attributes;
- }
-
- var nestedType = member as TypeDefinition;
- if (nestedType != null) {
- if (nestedType.IsNestedPrivate)
- return MethodAttributes.Private;
- if (nestedType.IsNestedAssembly || nestedType.IsNestedFamilyAndAssembly)
- return MethodAttributes.Assembly;
- return MethodAttributes.Public;
- }
-
- throw new NotSupportedException();
- }
-
- static bool MatchMethod(GenericContext<MethodDefinition> candidate, GenericContext<MethodDefinition> method)
- {
- var mCandidate = candidate.Item;
- var mMethod = method.Item;
- if (mCandidate.Name != mMethod.Name)
- return false;
-
- if (mCandidate.HasOverrides)
- return false;
-
- if (mCandidate.IsSpecialName != method.Item.IsSpecialName)
- return false;
-
- if (mCandidate.HasGenericParameters || mMethod.HasGenericParameters) {
- if (!mCandidate.HasGenericParameters || !mMethod.HasGenericParameters || mCandidate.GenericParameters.Count != mMethod.GenericParameters.Count)
- return false;
- }
-
- if (mCandidate.HasParameters || mMethod.HasParameters) {
- if (!mCandidate.HasParameters || !mMethod.HasParameters || mCandidate.Parameters.Count != mMethod.Parameters.Count)
- return false;
-
- for (int index = 0; index < mCandidate.Parameters.Count; index++) {
- if (!MatchParameters(candidate.ApplyTo(mCandidate.Parameters[index]), method.ApplyTo(mMethod.Parameters[index])))
- return false;
- }
- }
-
- return true;
- }
-
- public static bool MatchInterfaceMethod(MethodDefinition candidate, MethodDefinition method, TypeReference interfaceContextType)
- {
- var candidateContext = CreateGenericContext(candidate.DeclaringType);
- var gCandidate = candidateContext.ApplyTo(candidate);
-
- if (interfaceContextType is GenericInstanceType) {
- var methodContext = new GenericContext<TypeDefinition>(interfaceContextType.Resolve(), ((GenericInstanceType)interfaceContextType).GenericArguments);
- var gMethod = methodContext.ApplyTo(method);
- return MatchMethod(gCandidate, gMethod);
- } else {
- var methodContext = CreateGenericContext(interfaceContextType.Resolve());
- var gMethod = candidateContext.ApplyTo(method);
- return MatchMethod(gCandidate, gMethod);
- }
- }
-
- static bool MatchProperty(GenericContext<PropertyDefinition> candidate, GenericContext<PropertyDefinition> property)
- {
- var mCandidate = candidate.Item;
- var mProperty = property.Item;
- if (mCandidate.Name != mProperty.Name)
- return false;
-
- if ((mCandidate.GetMethod ?? mCandidate.SetMethod).HasOverrides)
- return false;
-
- if (mCandidate.HasParameters || mProperty.HasParameters) {
- if (!mCandidate.HasParameters || !mProperty.HasParameters || mCandidate.Parameters.Count != mProperty.Parameters.Count)
- return false;
-
- for (int index = 0; index < mCandidate.Parameters.Count; index++) {
- if (!MatchParameters(candidate.ApplyTo(mCandidate.Parameters[index]), property.ApplyTo(mProperty.Parameters[index])))
- return false;
- }
- }
-
- return true;
- }
-
- static bool MatchEvent(GenericContext<EventDefinition> candidate, GenericContext<EventDefinition> ev)
- {
- var mCandidate = candidate.Item;
- var mEvent = ev.Item;
- if (mCandidate.Name != mEvent.Name)
- return false;
-
- if ((mCandidate.AddMethod ?? mCandidate.RemoveMethod).HasOverrides)
- return false;
-
- if (!IsSameType(candidate.ResolveWithContext(mCandidate.EventType), ev.ResolveWithContext(mEvent.EventType)))
- return false;
-
- return true;
- }
-
- static bool MatchParameters(GenericContext<ParameterDefinition> baseParameterType, GenericContext<ParameterDefinition> parameterType)
- {
- if (baseParameterType.Item.IsIn != parameterType.Item.IsIn ||
- baseParameterType.Item.IsOut != parameterType.Item.IsOut)
- return false;
- var baseParam = baseParameterType.ResolveWithContext(baseParameterType.Item.ParameterType);
- var param = parameterType.ResolveWithContext(parameterType.Item.ParameterType);
- return IsSameType(baseParam, param);
- }
-
- static bool IsSameType(TypeReference tr1, TypeReference tr2)
- {
- if (tr1 == tr2)
- return true;
- if (tr1 == null || tr2 == null)
- return false;
-
- if (tr1.GetType() != tr2.GetType())
- return false;
-
- if (tr1.Name == tr2.Name && tr1.FullName == tr2.FullName)
- return true;
-
- return false;
- }
-
- static IEnumerable<GenericContext<TypeDefinition>> BaseTypes(TypeDefinition type)
- {
- return BaseTypes(CreateGenericContext(type));
- }
-
- static IEnumerable<GenericContext<TypeDefinition>> BaseTypes(GenericContext<TypeDefinition> type)
- {
- while (type.Item.BaseType != null) {
- var baseType = type.Item.BaseType;
- var genericBaseType = baseType as GenericInstanceType;
- if (genericBaseType != null) {
-#pragma warning disable 618
- type = new GenericContext<TypeDefinition>(genericBaseType.ResolveOrThrow(),
-#pragma warning restore 618
- genericBaseType.GenericArguments.Select(t => type.ResolveWithContext(t)));
- } else
-#pragma warning disable 618
- type = new GenericContext<TypeDefinition>(baseType.ResolveOrThrow());
-#pragma warning restore 618
- yield return type;
- }
- }
-
- static GenericContext<TypeDefinition> CreateGenericContext(TypeDefinition type)
- {
- return type.HasGenericParameters
- ? new GenericContext<TypeDefinition>(type, type.GenericParameters)
- : new GenericContext<TypeDefinition>(type);
- }
-
- struct GenericContext<T> where T : class
- {
- static readonly ReadOnlyCollection<TypeReference> Empty = new ReadOnlyCollection<TypeReference>(new List<TypeReference>());
-
- static readonly GenericParameter UnresolvedGenericTypeParameter =
- new DummyGenericParameterProvider(false).DummyParameter;
-
- static readonly GenericParameter UnresolvedGenericMethodParameter =
- new DummyGenericParameterProvider(true).DummyParameter;
-
- public readonly T Item;
- public readonly ReadOnlyCollection<TypeReference> TypeArguments;
-
- public GenericContext(T item)
- {
- if (item == null)
- throw new ArgumentNullException("item");
-
- Item = item;
- TypeArguments = Empty;
- }
-
- public GenericContext(T item, IEnumerable<TypeReference> typeArguments)
- {
- if (item == null)
- throw new ArgumentNullException("item");
-
- Item = item;
- var list = new List<TypeReference>();
- foreach (var arg in typeArguments) {
- var resolved = arg != null ? arg.Resolve() : arg;
- list.Add(resolved != null ? resolved : arg);
- }
- TypeArguments = new ReadOnlyCollection<TypeReference>(list);
- }
-
- GenericContext(T item, ReadOnlyCollection<TypeReference> typeArguments)
- {
- Item = item;
- TypeArguments = typeArguments;
- }
-
- public TypeReference ResolveWithContext(TypeReference type)
- {
- var genericParameter = type as GenericParameter;
- if (genericParameter != null)
- if (genericParameter.Owner.GenericParameterType == GenericParameterType.Type)
- return TypeArguments[genericParameter.Position];
- else
- return genericParameter.Owner.GenericParameterType == GenericParameterType.Type
- ? UnresolvedGenericTypeParameter : UnresolvedGenericMethodParameter;
- var typeSpecification = type as TypeSpecification;
- if (typeSpecification != null) {
- var resolvedElementType = ResolveWithContext(typeSpecification.ElementType);
- return ReplaceElementType(typeSpecification, resolvedElementType);
- }
-#pragma warning disable 618
- return type.ResolveOrThrow();
-#pragma warning restore 618
- }
-
- TypeReference ReplaceElementType(TypeSpecification ts, TypeReference newElementType)
- {
- var arrayType = ts as ArrayType;
- if (arrayType != null) {
- if (newElementType == arrayType.ElementType)
- return arrayType;
- var newArrayType = new ArrayType(newElementType, arrayType.Rank);
- for (int dimension = 0; dimension < arrayType.Rank; dimension++)
- newArrayType.Dimensions[dimension] = arrayType.Dimensions[dimension];
- return newArrayType;
- }
- var byReferenceType = ts as ByReferenceType;
- if (byReferenceType != null) {
- return new ByReferenceType(newElementType);
- }
- // TODO: should we throw an exception instead calling Resolve method?
-#pragma warning disable 618
- return ts.ResolveOrThrow();
-#pragma warning restore 618
- }
-
- public GenericContext<T2> ApplyTo<T2>(T2 item) where T2 : class
- {
- return new GenericContext<T2>(item, TypeArguments);
- }
-
- class DummyGenericParameterProvider : IGenericParameterProvider
- {
- readonly GenericParameterType type;
- readonly Mono.Collections.Generic.Collection<GenericParameter> parameters;
-
- public DummyGenericParameterProvider(bool methodTypeParameter)
- {
- type = methodTypeParameter ? GenericParameterType.Method :
- GenericParameterType.Type;
- parameters = new Mono.Collections.Generic.Collection<GenericParameter>(1);
- parameters.Add(new GenericParameter(this));
- }
-
- public GenericParameter DummyParameter
- {
- get { return parameters[0]; }
- }
-
- bool IGenericParameterProvider.HasGenericParameters
- {
- get { throw new NotImplementedException(); }
- }
-
- bool IGenericParameterProvider.IsDefinition
- {
- get { throw new NotImplementedException(); }
- }
-
- ModuleDefinition IGenericParameterProvider.Module
- {
- get { throw new NotImplementedException(); }
- }
-
- Mono.Collections.Generic.Collection<GenericParameter> IGenericParameterProvider.GenericParameters
- {
- get { return parameters; }
- }
-
- GenericParameterType IGenericParameterProvider.GenericParameterType
- {
- get { return type; }
- }
-
- MetadataToken IMetadataTokenProvider.MetadataToken
- {
- get
- {
- throw new NotImplementedException();
- }
- set
- {
- throw new NotImplementedException();
- }
- }
- }
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/CecilExtensions.cs b/ICSharpCode.Decompiler/CecilExtensions.cs
deleted file mode 100644
index 0c7cb1e4..00000000
--- a/ICSharpCode.Decompiler/CecilExtensions.cs
+++ /dev/null
@@ -1,374 +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 Mono.Cecil;
-using Mono.Cecil.Cil;
-
-namespace ICSharpCode.Decompiler
-{
- /// <summary>
- /// Cecil helper methods.
- /// </summary>
- public static class CecilExtensions
- {
- #region GetPushDelta / GetPopDelta
- public static int GetPushDelta(this Instruction instruction)
- {
- OpCode code = instruction.OpCode;
- switch (code.StackBehaviourPush) {
- case StackBehaviour.Push0:
- return 0;
-
- case StackBehaviour.Push1:
- case StackBehaviour.Pushi:
- case StackBehaviour.Pushi8:
- case StackBehaviour.Pushr4:
- case StackBehaviour.Pushr8:
- case StackBehaviour.Pushref:
- return 1;
-
- case StackBehaviour.Push1_push1:
- return 2;
-
- case StackBehaviour.Varpush:
- if (code.FlowControl != FlowControl.Call)
- break;
-
- IMethodSignature method = (IMethodSignature) instruction.Operand;
- return IsVoid (method.ReturnType) ? 0 : 1;
- }
-
- throw new NotSupportedException ();
- }
-
- public static int? GetPopDelta(this Instruction instruction, MethodDefinition methodDef)
- {
- OpCode code = instruction.OpCode;
- switch (code.StackBehaviourPop) {
- case StackBehaviour.Pop0:
- return 0;
- case StackBehaviour.Popi:
- case StackBehaviour.Popref:
- case StackBehaviour.Pop1:
- return 1;
-
- case StackBehaviour.Pop1_pop1:
- case StackBehaviour.Popi_pop1:
- case StackBehaviour.Popi_popi:
- case StackBehaviour.Popi_popi8:
- case StackBehaviour.Popi_popr4:
- case StackBehaviour.Popi_popr8:
- case StackBehaviour.Popref_pop1:
- case StackBehaviour.Popref_popi:
- return 2;
-
- case StackBehaviour.Popi_popi_popi:
- case StackBehaviour.Popref_popi_popi:
- case StackBehaviour.Popref_popi_popi8:
- case StackBehaviour.Popref_popi_popr4:
- case StackBehaviour.Popref_popi_popr8:
- case StackBehaviour.Popref_popi_popref:
- return 3;
-
- case StackBehaviour.PopAll:
- return null;
-
- case StackBehaviour.Varpop:
- if (code == OpCodes.Ret)
- return methodDef.ReturnType.IsVoid() ? 0 : 1;
-
- if (code.FlowControl != FlowControl.Call)
- break;
-
- IMethodSignature method = (IMethodSignature) instruction.Operand;
- int count = method.HasParameters ? method.Parameters.Count : 0;
- if (method.HasThis && code != OpCodes.Newobj)
- ++count;
- if (code == OpCodes.Calli)
- ++count; // calli takes a function pointer in additional to the normal args
-
- return count;
- }
-
- throw new NotSupportedException ();
- }
-
- public static bool IsVoid(this TypeReference type)
- {
- while (type is OptionalModifierType || type is RequiredModifierType)
- type = ((TypeSpecification)type).ElementType;
- return type.MetadataType == MetadataType.Void;
- }
-
- public static bool IsValueTypeOrVoid(this TypeReference type)
- {
- while (type is OptionalModifierType || type is RequiredModifierType)
- type = ((TypeSpecification)type).ElementType;
- if (type is ArrayType)
- return false;
- return type.IsValueType || type.IsVoid();
- }
-
- /// <summary>
- /// checks if the given TypeReference is one of the following types:
- /// [sbyte, short, int, long, IntPtr]
- /// </summary>
- public static bool IsSignedIntegralType(this TypeReference type)
- {
- return type.MetadataType == MetadataType.SByte ||
- type.MetadataType == MetadataType.Int16 ||
- type.MetadataType == MetadataType.Int32 ||
- type.MetadataType == MetadataType.Int64 ||
- type.MetadataType == MetadataType.IntPtr;
- }
-
- /// <summary>
- /// checks if the given value is a numeric zero-value.
- /// NOTE that this only works for types: [sbyte, short, int, long, IntPtr, byte, ushort, uint, ulong, float, double and decimal]
- /// </summary>
- public static bool IsZero(this object value)
- {
- return value.Equals((sbyte)0) ||
- value.Equals((short)0) ||
- value.Equals(0) ||
- value.Equals(0L) ||
- value.Equals(IntPtr.Zero) ||
- value.Equals((byte)0) ||
- value.Equals((ushort)0) ||
- value.Equals(0u) ||
- value.Equals(0UL) ||
- value.Equals(0.0f) ||
- value.Equals(0.0) ||
- value.Equals((decimal)0);
-
- }
-
- #endregion
-
- /// <summary>
- /// Gets the (exclusive) end offset of this instruction.
- /// </summary>
- public static int GetEndOffset(this Instruction inst)
- {
- if (inst == null)
- throw new ArgumentNullException("inst");
- return inst.Offset + inst.GetSize();
- }
-
- public static string OffsetToString(int offset)
- {
- return string.Format("IL_{0:x4}", offset);
- }
-
- public static HashSet<MethodDefinition> GetAccessorMethods(this TypeDefinition type)
- {
- HashSet<MethodDefinition> accessorMethods = new HashSet<MethodDefinition>();
- foreach (var property in type.Properties) {
- accessorMethods.Add(property.GetMethod);
- accessorMethods.Add(property.SetMethod);
- if (property.HasOtherMethods) {
- foreach (var m in property.OtherMethods)
- accessorMethods.Add(m);
- }
- }
- foreach (EventDefinition ev in type.Events) {
- accessorMethods.Add(ev.AddMethod);
- accessorMethods.Add(ev.RemoveMethod);
- accessorMethods.Add(ev.InvokeMethod);
- if (ev.HasOtherMethods) {
- foreach (var m in ev.OtherMethods)
- accessorMethods.Add(m);
- }
- }
- return accessorMethods;
- }
-
- public static TypeDefinition ResolveWithinSameModule(this TypeReference type)
- {
- if (type != null && type.GetElementType().Module == type.Module)
- return type.Resolve();
- else
- return null;
- }
-
- public static FieldDefinition ResolveWithinSameModule(this FieldReference field)
- {
- if (field != null && field.DeclaringType.GetElementType().Module == field.Module)
- return field.Resolve();
- else
- return null;
- }
-
- public static MethodDefinition ResolveWithinSameModule(this MethodReference method)
- {
- if (method != null && method.DeclaringType.GetElementType().Module == method.Module)
- return method.Resolve();
- else
- return null;
- }
-
- [Obsolete("throwing exceptions is considered a bug")]
- public static TypeDefinition ResolveOrThrow(this TypeReference typeReference)
- {
- var resolved = typeReference.Resolve();
- if (resolved == null)
- throw new ReferenceResolvingException();
- return resolved;
- }
-
- public static bool IsCompilerGenerated(this ICustomAttributeProvider provider)
- {
- if (provider != null && provider.HasCustomAttributes) {
- foreach (CustomAttribute a in provider.CustomAttributes) {
- if (a.AttributeType.FullName == "System.Runtime.CompilerServices.CompilerGeneratedAttribute")
- return true;
- }
- }
- return false;
- }
-
- public static bool IsCompilerGeneratedOrIsInCompilerGeneratedClass(this IMemberDefinition member)
- {
- if (member == null)
- return false;
- if (member.IsCompilerGenerated())
- return true;
- return IsCompilerGeneratedOrIsInCompilerGeneratedClass(member.DeclaringType);
- }
-
- public static TypeReference GetEnumUnderlyingType(this TypeDefinition type)
- {
- if (!type.IsEnum)
- throw new ArgumentException("Type must be an enum", "type");
-
- var fields = type.Fields;
-
- for (int i = 0; i < fields.Count; i++)
- {
- var field = fields[i];
- if (!field.IsStatic)
- return field.FieldType;
- }
-
- throw new NotSupportedException();
- }
-
- public static bool IsAnonymousType(this TypeReference type)
- {
- if (type == null)
- return false;
- if (string.IsNullOrEmpty(type.Namespace) && type.HasGeneratedName() && (type.Name.Contains("AnonType") || type.Name.Contains("AnonymousType"))) {
- TypeDefinition td = type.Resolve();
- return td != null && td.IsCompilerGenerated();
- }
- return false;
- }
-
- public static bool HasGeneratedName(this MemberReference member)
- {
- return member.Name.StartsWith("<", StringComparison.Ordinal);
- }
-
- public static bool ContainsAnonymousType(this TypeReference type)
- {
- GenericInstanceType git = type as GenericInstanceType;
- if (git != null) {
- if (IsAnonymousType(git))
- return true;
- for (int i = 0; i < git.GenericArguments.Count; i++) {
- if (git.GenericArguments[i].ContainsAnonymousType())
- return true;
- }
- return false;
- }
- TypeSpecification typeSpec = type as TypeSpecification;
- if (typeSpec != null)
- return typeSpec.ElementType.ContainsAnonymousType();
- else
- return false;
- }
-
- public static string GetDefaultMemberName(this TypeDefinition type)
- {
- CustomAttribute attr;
- return type.GetDefaultMemberName(out attr);
- }
-
- public static string GetDefaultMemberName(this TypeDefinition type, out CustomAttribute defaultMemberAttribute)
- {
- if (type.HasCustomAttributes)
- foreach (CustomAttribute ca in type.CustomAttributes)
- if (ca.Constructor.DeclaringType.Name == "DefaultMemberAttribute" && ca.Constructor.DeclaringType.Namespace == "System.Reflection"
- && ca.Constructor.FullName == @"System.Void System.Reflection.DefaultMemberAttribute::.ctor(System.String)") {
- defaultMemberAttribute = ca;
- return ca.ConstructorArguments[0].Value as string;
- }
- defaultMemberAttribute = null;
- return null;
- }
-
- public static bool IsIndexer(this PropertyDefinition property)
- {
- CustomAttribute attr;
- return property.IsIndexer(out attr);
- }
-
- public static bool IsIndexer(this PropertyDefinition property, out CustomAttribute defaultMemberAttribute)
- {
- defaultMemberAttribute = null;
- if (property.HasParameters) {
- var accessor = property.GetMethod ?? property.SetMethod;
- PropertyDefinition basePropDef = property;
- if (accessor.HasOverrides) {
- // if the property is explicitly implementing an interface, look up the property in the interface:
- MethodDefinition baseAccessor = accessor.Overrides.First().Resolve();
- if (baseAccessor != null) {
- foreach (PropertyDefinition baseProp in baseAccessor.DeclaringType.Properties) {
- if (baseProp.GetMethod == baseAccessor || baseProp.SetMethod == baseAccessor) {
- basePropDef = baseProp;
- break;
- }
- }
- } else
- return false;
- }
- CustomAttribute attr;
- var defaultMemberName = basePropDef.DeclaringType.GetDefaultMemberName(out attr);
- if (defaultMemberName == basePropDef.Name) {
- defaultMemberAttribute = attr;
- return true;
- }
- }
- return false;
- }
-
- public static bool IsDelegate(this TypeDefinition type)
- {
- if (type.BaseType != null && type.BaseType.Namespace == "System") {
- if (type.BaseType.Name == "MulticastDelegate")
- return true;
- if (type.BaseType.Name == "Delegate" && type.Name != "MulticastDelegate")
- return true;
- }
- return false;
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/CodeMappings.cs b/ICSharpCode.Decompiler/CodeMappings.cs
deleted file mode 100644
index ee62f76c..00000000
--- a/ICSharpCode.Decompiler/CodeMappings.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.Linq;
-using ICSharpCode.Decompiler.ILAst;
-using ICSharpCode.NRefactory;
-using Mono.Cecil;
-
-namespace ICSharpCode.Decompiler
-{
- /// <summary> Maps method's source code to IL </summary>
- public class MethodDebugSymbols
- {
- public MethodDefinition CecilMethod { get; set; }
- public List<ILVariable> LocalVariables { get; set; }
- public List<SequencePoint> SequencePoints { get; set; }
- public TextLocation StartLocation { get; set; }
- public TextLocation EndLocation { get; set; }
-
- public MethodDebugSymbols(MethodDefinition methodDef)
- {
- CecilMethod = methodDef;
- LocalVariables = new List<ILVariable>();
- SequencePoints = new List<SequencePoint>();
- }
- }
-
- public class SequencePoint
- {
- public ILRange[] ILRanges { get; set; }
- public TextLocation StartLocation { get; set; }
- public TextLocation EndLocation { get; set; }
- public int ILOffset { get { return ILRanges[0].From; } }
-
- public override string ToString()
- {
- return string.Join(" ", ILRanges) + " " + StartLocation + "-" + EndLocation;
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/DecompilerException.cs b/ICSharpCode.Decompiler/DecompilerException.cs
deleted file mode 100644
index 5f5f022f..00000000
--- a/ICSharpCode.Decompiler/DecompilerException.cs
+++ /dev/null
@@ -1,42 +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.Runtime.Serialization;
-using Mono.Cecil;
-
-namespace ICSharpCode.Decompiler
-{
- /// <summary>
- /// Description of DecompilerException.
- /// </summary>
- public class DecompilerException : Exception, ISerializable
- {
- public MethodDefinition DecompiledMethod { get; set; }
-
- public DecompilerException(MethodDefinition decompiledMethod, Exception innerException)
- : base("Error decompiling " + decompiledMethod.FullName + Environment.NewLine, innerException)
- {
- }
-
- // This constructor is needed for serialization.
- protected DecompilerException(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
- }
-} \ No newline at end of file
diff --git a/ICSharpCode.Decompiler/DecompilerSettings.cs b/ICSharpCode.Decompiler/DecompilerSettings.cs
deleted file mode 100644
index 74bdc943..00000000
--- a/ICSharpCode.Decompiler/DecompilerSettings.cs
+++ /dev/null
@@ -1,356 +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.ComponentModel;
-using ICSharpCode.NRefactory.CSharp;
-
-namespace ICSharpCode.Decompiler
-{
- /// <summary>
- /// Settings for the decompiler.
- /// </summary>
- public class DecompilerSettings : INotifyPropertyChanged
- {
- bool anonymousMethods = true;
-
- /// <summary>
- /// Decompile anonymous methods/lambdas.
- /// </summary>
- public bool AnonymousMethods {
- get { return anonymousMethods; }
- set {
- if (anonymousMethods != value) {
- anonymousMethods = value;
- OnPropertyChanged("AnonymousMethods");
- }
- }
- }
-
- bool expressionTrees = true;
-
- /// <summary>
- /// Decompile expression trees.
- /// </summary>
- public bool ExpressionTrees {
- get { return expressionTrees; }
- set {
- if (expressionTrees != value) {
- expressionTrees = value;
- OnPropertyChanged("ExpressionTrees");
- }
- }
- }
-
- bool yieldReturn = true;
-
- /// <summary>
- /// Decompile enumerators.
- /// </summary>
- public bool YieldReturn {
- get { return yieldReturn; }
- set {
- if (yieldReturn != value) {
- yieldReturn = value;
- OnPropertyChanged("YieldReturn");
- }
- }
- }
-
- bool asyncAwait = true;
-
- /// <summary>
- /// Decompile async methods.
- /// </summary>
- public bool AsyncAwait {
- get { return asyncAwait; }
- set {
- if (asyncAwait != value) {
- asyncAwait = value;
- OnPropertyChanged("AsyncAwait");
- }
- }
- }
-
- bool automaticProperties = true;
-
- /// <summary>
- /// Decompile automatic properties
- /// </summary>
- public bool AutomaticProperties {
- get { return automaticProperties; }
- set {
- if (automaticProperties != value) {
- automaticProperties = value;
- OnPropertyChanged("AutomaticProperties");
- }
- }
- }
-
- bool automaticEvents = true;
-
- /// <summary>
- /// Decompile automatic events
- /// </summary>
- public bool AutomaticEvents {
- get { return automaticEvents; }
- set {
- if (automaticEvents != value) {
- automaticEvents = value;
- OnPropertyChanged("AutomaticEvents");
- }
- }
- }
-
- bool usingStatement = true;
-
- /// <summary>
- /// Decompile using statements.
- /// </summary>
- public bool UsingStatement {
- get { return usingStatement; }
- set {
- if (usingStatement != value) {
- usingStatement = value;
- OnPropertyChanged("UsingStatement");
- }
- }
- }
-
- bool forEachStatement = true;
-
- /// <summary>
- /// Decompile foreach statements.
- /// </summary>
- public bool ForEachStatement {
- get { return forEachStatement; }
- set {
- if (forEachStatement != value) {
- forEachStatement = value;
- OnPropertyChanged("ForEachStatement");
- }
- }
- }
-
- bool lockStatement = true;
-
- /// <summary>
- /// Decompile lock statements.
- /// </summary>
- public bool LockStatement {
- get { return lockStatement; }
- set {
- if (lockStatement != value) {
- lockStatement = value;
- OnPropertyChanged("LockStatement");
- }
- }
- }
-
- bool switchStatementOnString = true;
-
- public bool SwitchStatementOnString {
- get { return switchStatementOnString; }
- set {
- if (switchStatementOnString != value) {
- switchStatementOnString = value;
- OnPropertyChanged("SwitchStatementOnString");
- }
- }
- }
-
- bool usingDeclarations = true;
-
- public bool UsingDeclarations {
- get { return usingDeclarations; }
- set {
- if (usingDeclarations != value) {
- usingDeclarations = value;
- OnPropertyChanged("UsingDeclarations");
- }
- }
- }
-
- bool queryExpressions = true;
-
- public bool QueryExpressions {
- get { return queryExpressions; }
- set {
- if (queryExpressions != value) {
- queryExpressions = value;
- OnPropertyChanged("QueryExpressions");
- }
- }
- }
-
- bool fullyQualifyAmbiguousTypeNames = true;
-
- public bool FullyQualifyAmbiguousTypeNames {
- get { return fullyQualifyAmbiguousTypeNames; }
- set {
- if (fullyQualifyAmbiguousTypeNames != value) {
- fullyQualifyAmbiguousTypeNames = value;
- OnPropertyChanged("FullyQualifyAmbiguousTypeNames");
- }
- }
- }
-
- bool useDebugSymbols = true;
-
- /// <summary>
- /// Gets/Sets whether to use variable names from debug symbols, if available.
- /// </summary>
- public bool UseDebugSymbols {
- get { return useDebugSymbols; }
- set {
- if (useDebugSymbols != value) {
- useDebugSymbols = value;
- OnPropertyChanged("UseDebugSymbols");
- }
- }
- }
-
- bool objectCollectionInitializers = true;
-
- /// <summary>
- /// Gets/Sets whether to use C# 3.0 object/collection initializers
- /// </summary>
- public bool ObjectOrCollectionInitializers {
- get { return objectCollectionInitializers; }
- set {
- if (objectCollectionInitializers != value) {
- objectCollectionInitializers = value;
- OnPropertyChanged("ObjectCollectionInitializers");
- }
- }
- }
-
- bool showXmlDocumentation = true;
-
- /// <summary>
- /// Gets/Sets whether to include XML documentation comments in the decompiled code
- /// </summary>
- public bool ShowXmlDocumentation {
- get { return showXmlDocumentation; }
- set {
- if (showXmlDocumentation != value) {
- showXmlDocumentation = value;
- OnPropertyChanged("ShowXmlDocumentation");
- }
- }
- }
-
- bool foldBraces = false;
-
- public bool FoldBraces {
- get { return foldBraces; }
- set {
- if (foldBraces != value) {
- foldBraces = value;
- OnPropertyChanged("FoldBraces");
- }
- }
- }
-
- #region Options to aid VB decompilation
- bool introduceIncrementAndDecrement = true;
-
- /// <summary>
- /// Gets/Sets whether to use increment and decrement operators
- /// </summary>
- public bool IntroduceIncrementAndDecrement {
- get { return introduceIncrementAndDecrement; }
- set {
- if (introduceIncrementAndDecrement != value) {
- introduceIncrementAndDecrement = value;
- OnPropertyChanged("IntroduceIncrementAndDecrement");
- }
- }
- }
-
- bool makeAssignmentExpressions = true;
-
- /// <summary>
- /// Gets/Sets whether to use assignment expressions such as in while ((count = Do()) != 0) ;
- /// </summary>
- public bool MakeAssignmentExpressions {
- get { return makeAssignmentExpressions; }
- set {
- if (makeAssignmentExpressions != value) {
- makeAssignmentExpressions = value;
- OnPropertyChanged("MakeAssignmentExpressions");
- }
- }
- }
-
- bool alwaysGenerateExceptionVariableForCatchBlocks = false;
-
- /// <summary>
- /// Gets/Sets whether to always generate exception variables in catch blocks
- /// </summary>
- public bool AlwaysGenerateExceptionVariableForCatchBlocks {
- get { return alwaysGenerateExceptionVariableForCatchBlocks; }
- set {
- if (alwaysGenerateExceptionVariableForCatchBlocks != value) {
- alwaysGenerateExceptionVariableForCatchBlocks = value;
- OnPropertyChanged("AlwaysGenerateExceptionVariableForCatchBlocks");
- }
- }
- }
- #endregion
-
- CSharpFormattingOptions csharpFormattingOptions;
-
- public CSharpFormattingOptions CSharpFormattingOptions {
- get {
- if (csharpFormattingOptions == null) {
- csharpFormattingOptions = FormattingOptionsFactory.CreateAllman();
- csharpFormattingOptions.IndentSwitchBody = false;
- csharpFormattingOptions.ArrayInitializerWrapping = Wrapping.WrapAlways;
- }
- return csharpFormattingOptions;
- }
- set {
- if (value == null)
- throw new ArgumentNullException();
- if (csharpFormattingOptions != value) {
- csharpFormattingOptions = value;
- OnPropertyChanged("CSharpFormattingOptions");
- }
- }
- }
-
- public event PropertyChangedEventHandler PropertyChanged;
-
- protected virtual void OnPropertyChanged(string propertyName)
- {
- if (PropertyChanged != null) {
- PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
- }
- }
-
- public DecompilerSettings Clone()
- {
- DecompilerSettings settings = (DecompilerSettings)MemberwiseClone();
- if (csharpFormattingOptions != null)
- settings.csharpFormattingOptions = csharpFormattingOptions.Clone();
- settings.PropertyChanged = null;
- return settings;
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
deleted file mode 100644
index ea6e54db..00000000
--- a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
+++ /dev/null
@@ -1,447 +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 Mono.Cecil;
-using Mono.Cecil.Cil;
-
-namespace ICSharpCode.Decompiler.Disassembler
-{
- public enum ILNameSyntax
- {
- /// <summary>
- /// class/valuetype + TypeName (built-in types use keyword syntax)
- /// </summary>
- Signature,
- /// <summary>
- /// Like signature, but always refers to type parameters using their position
- /// </summary>
- SignatureNoNamedTypeParameters,
- /// <summary>
- /// [assembly]Full.Type.Name (even for built-in types)
- /// </summary>
- TypeName,
- /// <summary>
- /// Name (but built-in types use keyword syntax)
- /// </summary>
- ShortTypeName
- }
-
- public static class DisassemblerHelpers
- {
- public static void WriteOffsetReference(ITextOutput writer, Instruction instruction)
- {
- writer.WriteReference(CecilExtensions.OffsetToString(instruction.Offset), instruction);
- }
-
- public static void WriteTo(this ExceptionHandler exceptionHandler, ITextOutput writer)
- {
- writer.Write("Try ");
- WriteOffsetReference(writer, exceptionHandler.TryStart);
- writer.Write('-');
- WriteOffsetReference(writer, exceptionHandler.TryEnd);
- writer.Write(' ');
- writer.Write(exceptionHandler.HandlerType.ToString());
- if (exceptionHandler.FilterStart != null) {
- writer.Write(' ');
- WriteOffsetReference(writer, exceptionHandler.FilterStart);
- writer.Write(" handler ");
- }
- if (exceptionHandler.CatchType != null) {
- writer.Write(' ');
- exceptionHandler.CatchType.WriteTo(writer);
- }
- writer.Write(' ');
- WriteOffsetReference(writer, exceptionHandler.HandlerStart);
- writer.Write('-');
- WriteOffsetReference(writer, exceptionHandler.HandlerEnd);
- }
-
- public static void WriteTo(this Instruction instruction, ITextOutput writer)
- {
- writer.WriteDefinition(CecilExtensions.OffsetToString(instruction.Offset), instruction);
- writer.Write(": ");
- writer.WriteReference(instruction.OpCode.Name, instruction.OpCode);
- if (instruction.Operand != null) {
- writer.Write(' ');
- if (instruction.OpCode == OpCodes.Ldtoken) {
- if (instruction.Operand is MethodReference)
- writer.Write("method ");
- else if (instruction.Operand is FieldReference)
- writer.Write("field ");
- }
- WriteOperand(writer, instruction.Operand);
- }
- }
-
- static void WriteLabelList(ITextOutput writer, Instruction[] instructions)
- {
- writer.Write("(");
- for(int i = 0; i < instructions.Length; i++) {
- if(i != 0) writer.Write(", ");
- WriteOffsetReference(writer, instructions[i]);
- }
- writer.Write(")");
- }
-
- static string ToInvariantCultureString(object value)
- {
- IConvertible convertible = value as IConvertible;
- return(null != convertible)
- ? convertible.ToString(System.Globalization.CultureInfo.InvariantCulture)
- : value.ToString();
- }
-
- public static void WriteTo(this MethodReference method, ITextOutput writer)
- {
- if (method.ExplicitThis) {
- writer.Write("instance explicit ");
- }
- else if (method.HasThis) {
- writer.Write("instance ");
- }
- method.ReturnType.WriteTo(writer, ILNameSyntax.SignatureNoNamedTypeParameters);
- writer.Write(' ');
- if (method.DeclaringType != null) {
- method.DeclaringType.WriteTo(writer, ILNameSyntax.TypeName);
- writer.Write("::");
- }
- MethodDefinition md = method as MethodDefinition;
- if (md != null && md.IsCompilerControlled) {
- writer.WriteReference(Escape(method.Name + "$PST" + method.MetadataToken.ToInt32().ToString("X8")), method);
- } else {
- writer.WriteReference(Escape(method.Name), method);
- }
- GenericInstanceMethod gim = method as GenericInstanceMethod;
- if (gim != null) {
- writer.Write('<');
- for (int i = 0; i < gim.GenericArguments.Count; i++) {
- if (i > 0)
- writer.Write(", ");
- gim.GenericArguments[i].WriteTo(writer);
- }
- writer.Write('>');
- }
- writer.Write("(");
- var parameters = method.Parameters;
- for(int i = 0; i < parameters.Count; ++i) {
- if (i > 0) writer.Write(", ");
- parameters[i].ParameterType.WriteTo(writer, ILNameSyntax.SignatureNoNamedTypeParameters);
- }
- writer.Write(")");
- }
-
- static void WriteTo(this FieldReference field, ITextOutput writer)
- {
- field.FieldType.WriteTo(writer, ILNameSyntax.SignatureNoNamedTypeParameters);
- writer.Write(' ');
- field.DeclaringType.WriteTo(writer, ILNameSyntax.TypeName);
- writer.Write("::");
- writer.WriteReference(Escape(field.Name), field);
- }
-
- static bool IsValidIdentifierCharacter(char c)
- {
- return c == '_' || c == '$' || c == '@' || c == '?' || c == '`';
- }
-
- static bool IsValidIdentifier(string identifier)
- {
- if (string.IsNullOrEmpty(identifier))
- return false;
- if (!(char.IsLetter(identifier[0]) || IsValidIdentifierCharacter(identifier[0]))) {
- // As a special case, .ctor and .cctor are valid despite starting with a dot
- return identifier == ".ctor" || identifier == ".cctor";
- }
- for (int i = 1; i < identifier.Length; i++) {
- if (!(char.IsLetterOrDigit(identifier[i]) || IsValidIdentifierCharacter(identifier[i]) || identifier[i] == '.'))
- return false;
- }
- return true;
- }
-
- static readonly HashSet<string> ilKeywords = BuildKeywordList(
- "abstract", "algorithm", "alignment", "ansi", "any", "arglist",
- "array", "as", "assembly", "assert", "at", "auto", "autochar", "beforefieldinit",
- "blob", "blob_object", "bool", "brnull", "brnull.s", "brzero", "brzero.s", "bstr",
- "bytearray", "byvalstr", "callmostderived", "carray", "catch", "cdecl", "cf",
- "char", "cil", "class", "clsid", "const", "currency", "custom", "date", "decimal",
- "default", "demand", "deny", "endmac", "enum", "error", "explicit", "extends", "extern",
- "false", "famandassem", "family", "famorassem", "fastcall", "fault", "field", "filetime",
- "filter", "final", "finally", "fixed", "float", "float32", "float64", "forwardref",
- "fromunmanaged", "handler", "hidebysig", "hresult", "idispatch", "il", "illegal",
- "implements", "implicitcom", "implicitres", "import", "in", "inheritcheck", "init",
- "initonly", "instance", "int", "int16", "int32", "int64", "int8", "interface", "internalcall",
- "iunknown", "lasterr", "lcid", "linkcheck", "literal", "localloc", "lpstr", "lpstruct", "lptstr",
- "lpvoid", "lpwstr", "managed", "marshal", "method", "modopt", "modreq", "native", "nested",
- "newslot", "noappdomain", "noinlining", "nomachine", "nomangle", "nometadata", "noncasdemand",
- "noncasinheritance", "noncaslinkdemand", "noprocess", "not", "not_in_gc_heap", "notremotable",
- "notserialized", "null", "nullref", "object", "objectref", "opt", "optil", "out",
- "permitonly", "pinned", "pinvokeimpl", "prefix1", "prefix2", "prefix3", "prefix4", "prefix5", "prefix6",
- "prefix7", "prefixref", "prejitdeny", "prejitgrant", "preservesig", "private", "privatescope", "protected",
- "public", "record", "refany", "reqmin", "reqopt", "reqrefuse", "reqsecobj", "request", "retval",
- "rtspecialname", "runtime", "safearray", "sealed", "sequential", "serializable", "special", "specialname",
- "static", "stdcall", "storage", "stored_object", "stream", "streamed_object", "string", "struct",
- "synchronized", "syschar", "sysstring", "tbstr", "thiscall", "tls", "to", "true", "typedref",
- "unicode", "unmanaged", "unmanagedexp", "unsigned", "unused", "userdefined", "value", "valuetype",
- "vararg", "variant", "vector", "virtual", "void", "wchar", "winapi", "with", "wrapper",
-
- // These are not listed as keywords in spec, but ILAsm treats them as such
- "property", "type", "flags", "callconv", "strict"
- );
-
- static HashSet<string> BuildKeywordList(params string[] keywords)
- {
- HashSet<string> s = new HashSet<string>(keywords);
- foreach (var field in typeof(OpCodes).GetFields()) {
- s.Add(((OpCode)field.GetValue(null)).Name);
- }
- return s;
- }
-
- public static string Escape(string identifier)
- {
- if (IsValidIdentifier(identifier) && !ilKeywords.Contains(identifier)) {
- return identifier;
- } else {
- // The ECMA specification says that ' inside SQString should be ecaped using an octal escape sequence,
- // but we follow Microsoft's ILDasm and use \'.
- return "'" + NRefactory.CSharp.TextWriterTokenWriter.ConvertString(identifier).Replace("'", "\\'") + "'";
- }
- }
-
- public static void WriteTo(this TypeReference type, ITextOutput writer, ILNameSyntax syntax = ILNameSyntax.Signature)
- {
- ILNameSyntax syntaxForElementTypes = syntax == ILNameSyntax.SignatureNoNamedTypeParameters ? syntax : ILNameSyntax.Signature;
- if (type is PinnedType) {
- ((PinnedType)type).ElementType.WriteTo(writer, syntaxForElementTypes);
- writer.Write(" pinned");
- } else if (type is ArrayType) {
- ArrayType at = (ArrayType)type;
- at.ElementType.WriteTo(writer, syntaxForElementTypes);
- writer.Write('[');
- writer.Write(string.Join(", ", at.Dimensions));
- writer.Write(']');
- } else if (type is GenericParameter) {
- writer.Write('!');
- if (((GenericParameter)type).Owner.GenericParameterType == GenericParameterType.Method)
- writer.Write('!');
- if (string.IsNullOrEmpty(type.Name) || type.Name[0] == '!' || syntax == ILNameSyntax.SignatureNoNamedTypeParameters)
- writer.Write(((GenericParameter)type).Position.ToString());
- else
- writer.Write(Escape(type.Name));
- } else if (type is ByReferenceType) {
- ((ByReferenceType)type).ElementType.WriteTo(writer, syntaxForElementTypes);
- writer.Write('&');
- } else if (type is PointerType) {
- ((PointerType)type).ElementType.WriteTo(writer, syntaxForElementTypes);
- writer.Write('*');
- } else if (type is GenericInstanceType) {
- type.GetElementType().WriteTo(writer, syntaxForElementTypes);
- writer.Write('<');
- var arguments = ((GenericInstanceType)type).GenericArguments;
- for (int i = 0; i < arguments.Count; i++) {
- if (i > 0)
- writer.Write(", ");
- arguments[i].WriteTo(writer, syntaxForElementTypes);
- }
- writer.Write('>');
- } else if (type is OptionalModifierType) {
- ((OptionalModifierType)type).ElementType.WriteTo(writer, syntax);
- writer.Write(" modopt(");
- ((OptionalModifierType)type).ModifierType.WriteTo(writer, ILNameSyntax.TypeName);
- writer.Write(") ");
- } else if (type is RequiredModifierType) {
- ((RequiredModifierType)type).ElementType.WriteTo(writer, syntax);
- writer.Write(" modreq(");
- ((RequiredModifierType)type).ModifierType.WriteTo(writer, ILNameSyntax.TypeName);
- writer.Write(") ");
- } else {
- string name = PrimitiveTypeName(type.FullName);
- if (syntax == ILNameSyntax.ShortTypeName) {
- if (name != null)
- writer.Write(name);
- else
- writer.WriteReference(Escape(type.Name), type);
- } else if ((syntax == ILNameSyntax.Signature || syntax == ILNameSyntax.SignatureNoNamedTypeParameters) && name != null) {
- writer.Write(name);
- } else {
- if (syntax == ILNameSyntax.Signature || syntax == ILNameSyntax.SignatureNoNamedTypeParameters)
- writer.Write(type.IsValueType ? "valuetype " : "class ");
-
- if (type.DeclaringType != null) {
- type.DeclaringType.WriteTo(writer, ILNameSyntax.TypeName);
- writer.Write('/');
- writer.WriteReference(Escape(type.Name), type);
- } else {
- if (!type.IsDefinition && type.Scope != null && !(type is TypeSpecification))
- writer.Write("[{0}]", Escape(type.Scope.Name));
- writer.WriteReference(Escape(type.FullName), type);
- }
- }
- }
- }
-
- public static void WriteOperand(ITextOutput writer, object operand)
- {
- if (operand == null)
- throw new ArgumentNullException("operand");
-
- Instruction targetInstruction = operand as Instruction;
- if (targetInstruction != null) {
- WriteOffsetReference(writer, targetInstruction);
- return;
- }
-
- Instruction[] targetInstructions = operand as Instruction[];
- if (targetInstructions != null) {
- WriteLabelList(writer, targetInstructions);
- return;
- }
-
- VariableReference variableRef = operand as VariableReference;
- if (variableRef != null) {
- if (string.IsNullOrEmpty(variableRef.Name))
- writer.WriteReference(variableRef.Index.ToString(), variableRef);
- else
- writer.WriteReference(Escape(variableRef.Name), variableRef);
- return;
- }
-
- ParameterReference paramRef = operand as ParameterReference;
- if (paramRef != null) {
- if (string.IsNullOrEmpty(paramRef.Name))
- writer.WriteReference(paramRef.Index.ToString(), paramRef);
- else
- writer.WriteReference(Escape(paramRef.Name), paramRef);
- return;
- }
-
- MethodReference methodRef = operand as MethodReference;
- if (methodRef != null) {
- methodRef.WriteTo(writer);
- return;
- }
-
- TypeReference typeRef = operand as TypeReference;
- if (typeRef != null) {
- typeRef.WriteTo(writer, ILNameSyntax.TypeName);
- return;
- }
-
- FieldReference fieldRef = operand as FieldReference;
- if (fieldRef != null) {
- fieldRef.WriteTo(writer);
- return;
- }
-
- string s = operand as string;
- if (s != null) {
- writer.Write("\"" + NRefactory.CSharp.TextWriterTokenWriter.ConvertString(s) + "\"");
- } else if (operand is char) {
- writer.Write(((int)(char)operand).ToString());
- } else if (operand is float) {
- float val = (float)operand;
- if (val == 0) {
- if (1 / val == float.NegativeInfinity) {
- // negative zero is a special case
- writer.Write('-');
- }
- writer.Write("0.0");
- } else if (float.IsInfinity(val) || float.IsNaN(val)) {
- byte[] data = BitConverter.GetBytes(val);
- writer.Write('(');
- for (int i = 0; i < data.Length; i++) {
- if (i > 0)
- writer.Write(' ');
- writer.Write(data[i].ToString("X2"));
- }
- writer.Write(')');
- } else {
- writer.Write(val.ToString("R", System.Globalization.CultureInfo.InvariantCulture));
- }
- } else if (operand is double) {
- double val = (double)operand;
- if (val == 0) {
- if (1 / val == double.NegativeInfinity) {
- // negative zero is a special case
- writer.Write('-');
- }
- writer.Write("0.0");
- } else if (double.IsInfinity(val) || double.IsNaN(val)) {
- byte[] data = BitConverter.GetBytes(val);
- writer.Write('(');
- for (int i = 0; i < data.Length; i++) {
- if (i > 0)
- writer.Write(' ');
- writer.Write(data[i].ToString("X2"));
- }
- writer.Write(')');
- } else {
- writer.Write(val.ToString("R", System.Globalization.CultureInfo.InvariantCulture));
- }
- } else if (operand is bool) {
- writer.Write((bool)operand ? "true" : "false");
- } else {
- s = ToInvariantCultureString(operand);
- writer.Write(s);
- }
- }
-
- public static string PrimitiveTypeName(string fullName)
- {
- switch (fullName) {
- case "System.SByte":
- return "int8";
- case "System.Int16":
- return "int16";
- case "System.Int32":
- return "int32";
- case "System.Int64":
- return "int64";
- case "System.Byte":
- return "uint8";
- case "System.UInt16":
- return "uint16";
- case "System.UInt32":
- return "uint32";
- case "System.UInt64":
- return "uint64";
- case "System.Single":
- return "float32";
- case "System.Double":
- return "float64";
- case "System.Void":
- return "void";
- case "System.Boolean":
- return "bool";
- case "System.String":
- return "string";
- case "System.Char":
- return "char";
- case "System.Object":
- return "object";
- case "System.IntPtr":
- return "native int";
- default:
- return null;
- }
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Disassembler/ILStructure.cs b/ICSharpCode.Decompiler/Disassembler/ILStructure.cs
deleted file mode 100644
index ff9285b2..00000000
--- a/ICSharpCode.Decompiler/Disassembler/ILStructure.cs
+++ /dev/null
@@ -1,228 +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.Diagnostics;
-using System.Linq;
-using ICSharpCode.Decompiler.FlowAnalysis;
-using Mono.Cecil.Cil;
-
-namespace ICSharpCode.Decompiler.Disassembler
-{
- /// <summary>
- /// Specifies the type of an IL structure.
- /// </summary>
- public enum ILStructureType
- {
- /// <summary>
- /// The root block of the method
- /// </summary>
- Root,
- /// <summary>
- /// A nested control structure representing a loop.
- /// </summary>
- Loop,
- /// <summary>
- /// A nested control structure representing a try block.
- /// </summary>
- Try,
- /// <summary>
- /// A nested control structure representing a catch, finally, or fault block.
- /// </summary>
- Handler,
- /// <summary>
- /// A nested control structure representing an exception filter block.
- /// </summary>
- Filter
- }
-
- /// <summary>
- /// An IL structure.
- /// </summary>
- public class ILStructure
- {
- public readonly ILStructureType Type;
-
- /// <summary>
- /// Start position of the structure.
- /// </summary>
- public readonly int StartOffset;
-
- /// <summary>
- /// End position of the structure. (exclusive)
- /// </summary>
- public readonly int EndOffset;
-
- /// <summary>
- /// The exception handler associated with the Try, Filter or Handler block.
- /// </summary>
- public readonly ExceptionHandler ExceptionHandler;
-
- /// <summary>
- /// The loop's entry point.
- /// </summary>
- public readonly Instruction LoopEntryPoint;
-
- /// <summary>
- /// The list of child structures.
- /// </summary>
- public readonly List<ILStructure> Children = new List<ILStructure>();
-
- public ILStructure(MethodBody body)
- : this(ILStructureType.Root, 0, body.CodeSize)
- {
- // Build the tree of exception structures:
- for (int i = 0; i < body.ExceptionHandlers.Count; i++) {
- ExceptionHandler eh = body.ExceptionHandlers[i];
- if (!body.ExceptionHandlers.Take(i).Any(oldEh => oldEh.TryStart == eh.TryStart && oldEh.TryEnd == eh.TryEnd))
- AddNestedStructure(new ILStructure(ILStructureType.Try, eh.TryStart.Offset, eh.TryEnd.Offset, eh));
- if (eh.HandlerType == ExceptionHandlerType.Filter)
- AddNestedStructure(new ILStructure(ILStructureType.Filter, eh.FilterStart.Offset, eh.HandlerStart.Offset, eh));
- AddNestedStructure(new ILStructure(ILStructureType.Handler, eh.HandlerStart.Offset, eh.HandlerEnd == null ? body.CodeSize : eh.HandlerEnd.Offset, eh));
- }
- // Very simple loop detection: look for backward branches
- List<KeyValuePair<Instruction, Instruction>> allBranches = FindAllBranches(body);
- // We go through the branches in reverse so that we find the biggest possible loop boundary first (think loops with "continue;")
- for (int i = allBranches.Count - 1; i >= 0; i--) {
- int loopEnd = allBranches[i].Key.GetEndOffset();
- int loopStart = allBranches[i].Value.Offset;
- if (loopStart < loopEnd) {
- // We found a backward branch. This is a potential loop.
- // Check that is has only one entry point:
- Instruction entryPoint = null;
-
- // entry point is first instruction in loop if prev inst isn't an unconditional branch
- Instruction prev = allBranches[i].Value.Previous;
- if (prev != null && !OpCodeInfo.IsUnconditionalBranch(prev.OpCode))
- entryPoint = allBranches[i].Value;
-
- bool multipleEntryPoints = false;
- foreach (var pair in allBranches) {
- if (pair.Key.Offset < loopStart || pair.Key.Offset >= loopEnd) {
- if (loopStart <= pair.Value.Offset && pair.Value.Offset < loopEnd) {
- // jump from outside the loop into the loop
- if (entryPoint == null)
- entryPoint = pair.Value;
- else if (pair.Value != entryPoint)
- multipleEntryPoints = true;
- }
- }
- }
- if (!multipleEntryPoints) {
- AddNestedStructure(new ILStructure(ILStructureType.Loop, loopStart, loopEnd, entryPoint));
- }
- }
- }
- SortChildren();
- }
-
- public ILStructure(ILStructureType type, int startOffset, int endOffset, ExceptionHandler handler = null)
- {
- Debug.Assert(startOffset < endOffset);
- Type = type;
- StartOffset = startOffset;
- EndOffset = endOffset;
- ExceptionHandler = handler;
- }
-
- public ILStructure(ILStructureType type, int startOffset, int endOffset, Instruction loopEntryPoint)
- {
- Debug.Assert(startOffset < endOffset);
- Type = type;
- StartOffset = startOffset;
- EndOffset = endOffset;
- LoopEntryPoint = loopEntryPoint;
- }
-
- bool AddNestedStructure(ILStructure newStructure)
- {
- // special case: don't consider the loop-like structure of "continue;" statements to be nested loops
- if (Type == ILStructureType.Loop && newStructure.Type == ILStructureType.Loop && newStructure.StartOffset == StartOffset)
- return false;
-
- // use <= for end-offset comparisons because both end and EndOffset are exclusive
- Debug.Assert(StartOffset <= newStructure.StartOffset && newStructure.EndOffset <= EndOffset);
- foreach (ILStructure child in Children) {
- if (child.StartOffset <= newStructure.StartOffset && newStructure.EndOffset <= child.EndOffset) {
- return child.AddNestedStructure(newStructure);
- } else if (!(child.EndOffset <= newStructure.StartOffset || newStructure.EndOffset <= child.StartOffset)) {
- // child and newStructure overlap
- if (!(newStructure.StartOffset <= child.StartOffset && child.EndOffset <= newStructure.EndOffset)) {
- // Invalid nesting, can't build a tree. -> Don't add the new structure.
- return false;
- }
- }
- }
- // Move existing structures into the new structure:
- for (int i = 0; i < Children.Count; i++) {
- ILStructure child = Children[i];
- if (newStructure.StartOffset <= child.StartOffset && child.EndOffset <= newStructure.EndOffset) {
- Children.RemoveAt(i--);
- newStructure.Children.Add(child);
- }
- }
- // Add the structure here:
- Children.Add(newStructure);
- return true;
- }
-
- /// <summary>
- /// Finds all branches. Returns list of source offset->target offset mapping.
- /// Multiple entries for the same source offset are possible (switch statements).
- /// The result is sorted by source offset.
- /// </summary>
- List<KeyValuePair<Instruction, Instruction>> FindAllBranches(MethodBody body)
- {
- var result = new List<KeyValuePair<Instruction, Instruction>>();
- foreach (Instruction inst in body.Instructions) {
- switch (inst.OpCode.OperandType) {
- case OperandType.InlineBrTarget:
- case OperandType.ShortInlineBrTarget:
- result.Add(new KeyValuePair<Instruction, Instruction>(inst, (Instruction)inst.Operand));
- break;
- case OperandType.InlineSwitch:
- foreach (Instruction target in (Instruction[])inst.Operand)
- result.Add(new KeyValuePair<Instruction, Instruction>(inst, target));
- break;
- }
- }
- return result;
- }
-
- void SortChildren()
- {
- Children.Sort((a, b) => a.StartOffset.CompareTo(b.StartOffset));
- foreach (ILStructure child in Children)
- child.SortChildren();
- }
-
- /// <summary>
- /// Gets the innermost structure containing the specified offset.
- /// </summary>
- public ILStructure GetInnermost(int offset)
- {
- Debug.Assert(StartOffset <= offset && offset < EndOffset);
- foreach (ILStructure child in Children) {
- if (child.StartOffset <= offset && offset < child.EndOffset)
- return child.GetInnermost(offset);
- }
- return this;
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
deleted file mode 100644
index 2b5db78b..00000000
--- a/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
+++ /dev/null
@@ -1,239 +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 System.Threading;
-
-using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.FlowAnalysis;
-using ICSharpCode.Decompiler.ILAst;
-using Mono.Cecil;
-using Mono.Cecil.Cil;
-
-namespace ICSharpCode.Decompiler.Disassembler
-{
- /// <summary>
- /// Disassembles a method body.
- /// </summary>
- public sealed class MethodBodyDisassembler
- {
- readonly ITextOutput output;
- readonly bool detectControlStructure;
- readonly CancellationToken cancellationToken;
-
- public MethodBodyDisassembler(ITextOutput output, bool detectControlStructure, CancellationToken cancellationToken)
- {
- if (output == null)
- throw new ArgumentNullException("output");
- this.output = output;
- this.detectControlStructure = detectControlStructure;
- this.cancellationToken = cancellationToken;
- }
-
- public void Disassemble(MethodBody body, MethodDebugSymbols debugSymbols)
- {
- // start writing IL code
- MethodDefinition method = body.Method;
- output.WriteLine("// Method begins at RVA 0x{0:x4}", method.RVA);
- output.WriteLine("// Code size {0} (0x{0:x})", body.CodeSize);
- output.WriteLine(".maxstack {0}", body.MaxStackSize);
- if (method.DeclaringType.Module.Assembly != null && method.DeclaringType.Module.Assembly.EntryPoint == method)
- output.WriteLine (".entrypoint");
-
- if (method.Body.HasVariables) {
- output.Write(".locals ");
- if (method.Body.InitLocals)
- output.Write("init ");
- output.WriteLine("(");
- output.Indent();
- foreach (var v in method.Body.Variables) {
- output.WriteDefinition("[" + v.Index + "] ", v);
- v.VariableType.WriteTo(output);
- if (!string.IsNullOrEmpty(v.Name)) {
- output.Write(' ');
- output.Write(DisassemblerHelpers.Escape(v.Name));
- }
- if (v.Index + 1 < method.Body.Variables.Count)
- output.Write(',');
- output.WriteLine();
- }
- output.Unindent();
- output.WriteLine(")");
- }
- output.WriteLine();
-
- if (detectControlStructure && body.Instructions.Count > 0) {
- Instruction inst = body.Instructions[0];
- HashSet<int> branchTargets = GetBranchTargets(body.Instructions);
- WriteStructureBody(new ILStructure(body), branchTargets, ref inst, debugSymbols, method.Body.CodeSize);
- } else {
- foreach (var inst in method.Body.Instructions) {
- var startLocation = output.Location;
- inst.WriteTo(output);
-
- if (debugSymbols != null) {
- // add IL code mappings - used in debugger
- debugSymbols.SequencePoints.Add(
- new SequencePoint() {
- StartLocation = output.Location,
- EndLocation = output.Location,
- ILRanges = new ILRange[] { new ILRange(inst.Offset, inst.Next == null ? method.Body.CodeSize : inst.Next.Offset) }
- });
- }
-
- output.WriteLine();
- }
- if (method.Body.HasExceptionHandlers) {
- output.WriteLine();
- foreach (var eh in method.Body.ExceptionHandlers) {
- eh.WriteTo(output);
- output.WriteLine();
- }
- }
- }
- }
-
- HashSet<int> GetBranchTargets(IEnumerable<Instruction> instructions)
- {
- HashSet<int> branchTargets = new HashSet<int>();
- foreach (var inst in instructions) {
- Instruction target = inst.Operand as Instruction;
- if (target != null)
- branchTargets.Add(target.Offset);
- Instruction[] targets = inst.Operand as Instruction[];
- if (targets != null)
- foreach (Instruction t in targets)
- branchTargets.Add(t.Offset);
- }
- return branchTargets;
- }
-
- void WriteStructureHeader(ILStructure s)
- {
- switch (s.Type) {
- case ILStructureType.Loop:
- output.Write("// loop start");
- if (s.LoopEntryPoint != null) {
- output.Write(" (head: ");
- DisassemblerHelpers.WriteOffsetReference(output, s.LoopEntryPoint);
- output.Write(')');
- }
- output.WriteLine();
- break;
- case ILStructureType.Try:
- output.WriteLine(".try");
- output.WriteLine("{");
- break;
- case ILStructureType.Handler:
- switch (s.ExceptionHandler.HandlerType) {
- case ExceptionHandlerType.Catch:
- case ExceptionHandlerType.Filter:
- output.Write("catch");
- if (s.ExceptionHandler.CatchType != null) {
- output.Write(' ');
- s.ExceptionHandler.CatchType.WriteTo(output, ILNameSyntax.TypeName);
- }
- output.WriteLine();
- break;
- case ExceptionHandlerType.Finally:
- output.WriteLine("finally");
- break;
- case ExceptionHandlerType.Fault:
- output.WriteLine("fault");
- break;
- default:
- throw new NotSupportedException();
- }
- output.WriteLine("{");
- break;
- case ILStructureType.Filter:
- output.WriteLine("filter");
- output.WriteLine("{");
- break;
- default:
- throw new NotSupportedException();
- }
- output.Indent();
- }
-
- void WriteStructureBody(ILStructure s, HashSet<int> branchTargets, ref Instruction inst, MethodDebugSymbols debugSymbols, int codeSize)
- {
- bool isFirstInstructionInStructure = true;
- bool prevInstructionWasBranch = false;
- int childIndex = 0;
- while (inst != null && inst.Offset < s.EndOffset) {
- int offset = inst.Offset;
- if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) {
- ILStructure child = s.Children[childIndex++];
- WriteStructureHeader(child);
- WriteStructureBody(child, branchTargets, ref inst, debugSymbols, codeSize);
- WriteStructureFooter(child);
- } else {
- if (!isFirstInstructionInStructure && (prevInstructionWasBranch || branchTargets.Contains(offset))) {
- output.WriteLine(); // put an empty line after branches, and in front of branch targets
- }
- var startLocation = output.Location;
- inst.WriteTo(output);
-
- // add IL code mappings - used in debugger
- if (debugSymbols != null) {
- debugSymbols.SequencePoints.Add(
- new SequencePoint() {
- StartLocation = startLocation,
- EndLocation = output.Location,
- ILRanges = new ILRange[] { new ILRange(inst.Offset, inst.Next == null ? codeSize : inst.Next.Offset) }
- });
- }
-
- output.WriteLine();
-
- prevInstructionWasBranch = inst.OpCode.FlowControl == FlowControl.Branch
- || inst.OpCode.FlowControl == FlowControl.Cond_Branch
- || inst.OpCode.FlowControl == FlowControl.Return
- || inst.OpCode.FlowControl == FlowControl.Throw;
-
- inst = inst.Next;
- }
- isFirstInstructionInStructure = false;
- }
- }
-
- void WriteStructureFooter(ILStructure s)
- {
- output.Unindent();
- switch (s.Type) {
- case ILStructureType.Loop:
- output.WriteLine("// end loop");
- break;
- case ILStructureType.Try:
- output.WriteLine("} // end .try");
- break;
- case ILStructureType.Handler:
- output.WriteLine("} // end handler");
- break;
- case ILStructureType.Filter:
- output.WriteLine("} // end filter");
- break;
- default:
- throw new NotSupportedException();
- }
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
deleted file mode 100644
index 2a374c3a..00000000
--- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
+++ /dev/null
@@ -1,1168 +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.Diagnostics;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using ICSharpCode.NRefactory;
-using Mono.Cecil;
-using Mono.Collections.Generic;
-
-namespace ICSharpCode.Decompiler.Disassembler
-{
- /// <summary>
- /// Disassembles type and member definitions.
- /// </summary>
- public sealed class ReflectionDisassembler
- {
- ITextOutput output;
- CancellationToken cancellationToken;
- bool isInType; // whether we are currently disassembling a whole type (-> defaultCollapsed for foldings)
- MethodBodyDisassembler methodBodyDisassembler;
- MemberReference currentMember;
-
- public ReflectionDisassembler(ITextOutput output, bool detectControlStructure, CancellationToken cancellationToken)
- {
- if (output == null)
- throw new ArgumentNullException("output");
- this.output = output;
- this.cancellationToken = cancellationToken;
- methodBodyDisassembler = new MethodBodyDisassembler(output, detectControlStructure, cancellationToken);
- }
-
- #region Disassemble Method
- EnumNameCollection<MethodAttributes> methodAttributeFlags = new EnumNameCollection<MethodAttributes>() {
- { MethodAttributes.Final, "final" },
- { MethodAttributes.HideBySig, "hidebysig" },
- { MethodAttributes.SpecialName, "specialname" },
- { MethodAttributes.PInvokeImpl, null }, // handled separately
- { MethodAttributes.UnmanagedExport, "export" },
- { MethodAttributes.RTSpecialName, "rtspecialname" },
- { MethodAttributes.RequireSecObject, "reqsecobj" },
- { MethodAttributes.NewSlot, "newslot" },
- { MethodAttributes.CheckAccessOnOverride, "strict" },
- { MethodAttributes.Abstract, "abstract" },
- { MethodAttributes.Virtual, "virtual" },
- { MethodAttributes.Static, "static" },
- { MethodAttributes.HasSecurity, null }, // ?? also invisible in ILDasm
- };
-
- EnumNameCollection<MethodAttributes> methodVisibility = new EnumNameCollection<MethodAttributes>() {
- { MethodAttributes.Private, "private" },
- { MethodAttributes.FamANDAssem, "famandassem" },
- { MethodAttributes.Assembly, "assembly" },
- { MethodAttributes.Family, "family" },
- { MethodAttributes.FamORAssem, "famorassem" },
- { MethodAttributes.Public, "public" },
- };
-
- EnumNameCollection<MethodCallingConvention> callingConvention = new EnumNameCollection<MethodCallingConvention>() {
- { MethodCallingConvention.C, "unmanaged cdecl" },
- { MethodCallingConvention.StdCall, "unmanaged stdcall" },
- { MethodCallingConvention.ThisCall, "unmanaged thiscall" },
- { MethodCallingConvention.FastCall, "unmanaged fastcall" },
- { MethodCallingConvention.VarArg, "vararg" },
- { MethodCallingConvention.Generic, null },
- };
-
- EnumNameCollection<MethodImplAttributes> methodCodeType = new EnumNameCollection<MethodImplAttributes>() {
- { MethodImplAttributes.IL, "cil" },
- { MethodImplAttributes.Native, "native" },
- { MethodImplAttributes.OPTIL, "optil" },
- { MethodImplAttributes.Runtime, "runtime" },
- };
-
- EnumNameCollection<MethodImplAttributes> methodImpl = new EnumNameCollection<MethodImplAttributes>() {
- { MethodImplAttributes.Synchronized, "synchronized" },
- { MethodImplAttributes.NoInlining, "noinlining" },
- { MethodImplAttributes.NoOptimization, "nooptimization" },
- { MethodImplAttributes.PreserveSig, "preservesig" },
- { MethodImplAttributes.InternalCall, "internalcall" },
- { MethodImplAttributes.ForwardRef, "forwardref" },
- };
-
- public void DisassembleMethod(MethodDefinition method)
- {
- // set current member
- currentMember = method;
-
- // write method header
- output.WriteDefinition(".method ", method);
- DisassembleMethodInternal(method);
- }
-
- void DisassembleMethodInternal(MethodDefinition method)
- {
- // .method public hidebysig specialname
- // instance default class [mscorlib]System.IO.TextWriter get_BaseWriter () cil managed
- //
-
- TextLocation startLocation = output.Location;
-
- //emit flags
- WriteEnum(method.Attributes & MethodAttributes.MemberAccessMask, methodVisibility);
- WriteFlags(method.Attributes & ~MethodAttributes.MemberAccessMask, methodAttributeFlags);
- if(method.IsCompilerControlled) output.Write("privatescope ");
-
- if ((method.Attributes & MethodAttributes.PInvokeImpl) == MethodAttributes.PInvokeImpl) {
- output.Write("pinvokeimpl");
- if (method.HasPInvokeInfo && method.PInvokeInfo != null) {
- PInvokeInfo info = method.PInvokeInfo;
- output.Write("(\"" + NRefactory.CSharp.TextWriterTokenWriter.ConvertString(info.Module.Name) + "\"");
-
- if (!string.IsNullOrEmpty(info.EntryPoint) && info.EntryPoint != method.Name)
- output.Write(" as \"" + NRefactory.CSharp.TextWriterTokenWriter.ConvertString(info.EntryPoint) + "\"");
-
- if (info.IsNoMangle)
- output.Write(" nomangle");
-
- if (info.IsCharSetAnsi)
- output.Write(" ansi");
- else if (info.IsCharSetAuto)
- output.Write(" autochar");
- else if (info.IsCharSetUnicode)
- output.Write(" unicode");
-
- if (info.SupportsLastError)
- output.Write(" lasterr");
-
- if (info.IsCallConvCdecl)
- output.Write(" cdecl");
- else if (info.IsCallConvFastcall)
- output.Write(" fastcall");
- else if (info.IsCallConvStdCall)
- output.Write(" stdcall");
- else if (info.IsCallConvThiscall)
- output.Write(" thiscall");
- else if (info.IsCallConvWinapi)
- output.Write(" winapi");
-
- output.Write(')');
- }
- output.Write(' ');
- }
-
- output.WriteLine();
- output.Indent();
- if (method.ExplicitThis) {
- output.Write("instance explicit ");
- } else if (method.HasThis) {
- output.Write("instance ");
- }
-
- //call convention
- WriteEnum(method.CallingConvention & (MethodCallingConvention)0x1f, callingConvention);
-
- //return type
- method.ReturnType.WriteTo(output);
- output.Write(' ');
- if (method.MethodReturnType.HasMarshalInfo) {
- WriteMarshalInfo(method.MethodReturnType.MarshalInfo);
- }
-
- if (method.IsCompilerControlled) {
- output.Write(DisassemblerHelpers.Escape(method.Name + "$PST" + method.MetadataToken.ToInt32().ToString("X8")));
- } else {
- output.Write(DisassemblerHelpers.Escape(method.Name));
- }
-
- WriteTypeParameters(output, method);
-
- //( params )
- output.Write(" (");
- if (method.HasParameters) {
- output.WriteLine();
- output.Indent();
- WriteParameters(method.Parameters);
- output.Unindent();
- }
- output.Write(") ");
- //cil managed
- WriteEnum(method.ImplAttributes & MethodImplAttributes.CodeTypeMask, methodCodeType);
- if ((method.ImplAttributes & MethodImplAttributes.ManagedMask) == MethodImplAttributes.Managed)
- output.Write("managed ");
- else
- output.Write("unmanaged ");
- WriteFlags(method.ImplAttributes & ~(MethodImplAttributes.CodeTypeMask | MethodImplAttributes.ManagedMask), methodImpl);
-
- output.Unindent();
- OpenBlock(defaultCollapsed: isInType);
- WriteAttributes(method.CustomAttributes);
- if (method.HasOverrides) {
- foreach (var methodOverride in method.Overrides) {
- output.Write(".override method ");
- methodOverride.WriteTo(output);
- output.WriteLine();
- }
- }
- foreach (var p in method.Parameters) {
- WriteParameterAttributes(p);
- }
- WriteSecurityDeclarations(method);
-
- if (method.HasBody) {
- // create IL code mappings - used in debugger
- MethodDebugSymbols debugSymbols = new MethodDebugSymbols(method);
- debugSymbols.StartLocation = startLocation;
- methodBodyDisassembler.Disassemble(method.Body, debugSymbols);
- debugSymbols.EndLocation = output.Location;
- output.AddDebugSymbols(debugSymbols);
- }
-
- CloseBlock("end of method " + DisassemblerHelpers.Escape(method.DeclaringType.Name) + "::" + DisassemblerHelpers.Escape(method.Name));
- }
-
- #region Write Security Declarations
- void WriteSecurityDeclarations(ISecurityDeclarationProvider secDeclProvider)
- {
- if (!secDeclProvider.HasSecurityDeclarations)
- return;
- foreach (var secdecl in secDeclProvider.SecurityDeclarations) {
- output.Write(".permissionset ");
- switch (secdecl.Action) {
- case SecurityAction.Request:
- output.Write("request");
- break;
- case SecurityAction.Demand:
- output.Write("demand");
- break;
- case SecurityAction.Assert:
- output.Write("assert");
- break;
- case SecurityAction.Deny:
- output.Write("deny");
- break;
- case SecurityAction.PermitOnly:
- output.Write("permitonly");
- break;
- case SecurityAction.LinkDemand:
- output.Write("linkcheck");
- break;
- case SecurityAction.InheritDemand:
- output.Write("inheritcheck");
- break;
- case SecurityAction.RequestMinimum:
- output.Write("reqmin");
- break;
- case SecurityAction.RequestOptional:
- output.Write("reqopt");
- break;
- case SecurityAction.RequestRefuse:
- output.Write("reqrefuse");
- break;
- case SecurityAction.PreJitGrant:
- output.Write("prejitgrant");
- break;
- case SecurityAction.PreJitDeny:
- output.Write("prejitdeny");
- break;
- case SecurityAction.NonCasDemand:
- output.Write("noncasdemand");
- break;
- case SecurityAction.NonCasLinkDemand:
- output.Write("noncaslinkdemand");
- break;
- case SecurityAction.NonCasInheritance:
- output.Write("noncasinheritance");
- break;
- default:
- output.Write(secdecl.Action.ToString());
- break;
- }
- output.WriteLine(" = {");
- output.Indent();
- for (int i = 0; i < secdecl.SecurityAttributes.Count; i++) {
- SecurityAttribute sa = secdecl.SecurityAttributes[i];
- if (sa.AttributeType.Scope == sa.AttributeType.Module) {
- output.Write("class ");
- output.Write(DisassemblerHelpers.Escape(GetAssemblyQualifiedName(sa.AttributeType)));
- } else {
- sa.AttributeType.WriteTo(output, ILNameSyntax.TypeName);
- }
- output.Write(" = {");
- if (sa.HasFields || sa.HasProperties) {
- output.WriteLine();
- output.Indent();
-
- foreach (CustomAttributeNamedArgument na in sa.Fields) {
- output.Write("field ");
- WriteSecurityDeclarationArgument(na);
- output.WriteLine();
- }
-
- foreach (CustomAttributeNamedArgument na in sa.Properties) {
- output.Write("property ");
- WriteSecurityDeclarationArgument(na);
- output.WriteLine();
- }
-
- output.Unindent();
- }
- output.Write('}');
-
- if (i + 1< secdecl.SecurityAttributes.Count)
- output.Write(',');
- output.WriteLine();
- }
- output.Unindent();
- output.WriteLine("}");
- }
- }
-
- void WriteSecurityDeclarationArgument(CustomAttributeNamedArgument na)
- {
- TypeReference type = na.Argument.Type;
- if (type.MetadataType == MetadataType.Class || type.MetadataType == MetadataType.ValueType) {
- output.Write("enum ");
- if (type.Scope != type.Module) {
- output.Write("class ");
- output.Write(DisassemblerHelpers.Escape(GetAssemblyQualifiedName(type)));
- } else {
- type.WriteTo(output, ILNameSyntax.TypeName);
- }
- } else {
- type.WriteTo(output);
- }
- output.Write(' ');
- output.Write(DisassemblerHelpers.Escape(na.Name));
- output.Write(" = ");
- if (na.Argument.Value is string) {
- // secdecls use special syntax for strings
- output.Write("string('{0}')", NRefactory.CSharp.TextWriterTokenWriter.ConvertString((string)na.Argument.Value).Replace("'", "\'"));
- } else {
- WriteConstant(na.Argument.Value);
- }
- }
-
- string GetAssemblyQualifiedName(TypeReference type)
- {
- AssemblyNameReference anr = type.Scope as AssemblyNameReference;
- if (anr == null) {
- ModuleDefinition md = type.Scope as ModuleDefinition;
- if (md != null) {
- anr = md.Assembly.Name;
- }
- }
- if (anr != null) {
- return type.FullName + ", " + anr.FullName;
- } else {
- return type.FullName;
- }
- }
- #endregion
-
- #region WriteMarshalInfo
- void WriteMarshalInfo(MarshalInfo marshalInfo)
- {
- output.Write("marshal(");
- WriteNativeType(marshalInfo.NativeType, marshalInfo);
- output.Write(") ");
- }
-
- void WriteNativeType(NativeType nativeType, MarshalInfo marshalInfo = null)
- {
- switch (nativeType) {
- case NativeType.None:
- break;
- case NativeType.Boolean:
- output.Write("bool");
- break;
- case NativeType.I1:
- output.Write("int8");
- break;
- case NativeType.U1:
- output.Write("unsigned int8");
- break;
- case NativeType.I2:
- output.Write("int16");
- break;
- case NativeType.U2:
- output.Write("unsigned int16");
- break;
- case NativeType.I4:
- output.Write("int32");
- break;
- case NativeType.U4:
- output.Write("unsigned int32");
- break;
- case NativeType.I8:
- output.Write("int64");
- break;
- case NativeType.U8:
- output.Write("unsigned int64");
- break;
- case NativeType.R4:
- output.Write("float32");
- break;
- case NativeType.R8:
- output.Write("float64");
- break;
- case NativeType.LPStr:
- output.Write("lpstr");
- break;
- case NativeType.Int:
- output.Write("int");
- break;
- case NativeType.UInt:
- output.Write("unsigned int");
- break;
- case NativeType.Func:
- goto default; // ??
- case NativeType.Array:
- ArrayMarshalInfo ami = (ArrayMarshalInfo)marshalInfo;
- if (ami == null)
- goto default;
- if (ami.ElementType != NativeType.Max)
- WriteNativeType(ami.ElementType);
- output.Write('[');
- if (ami.SizeParameterMultiplier == 0) {
- output.Write(ami.Size.ToString());
- } else {
- if (ami.Size >= 0)
- output.Write(ami.Size.ToString());
- output.Write(" + ");
- output.Write(ami.SizeParameterIndex.ToString());
- }
- output.Write(']');
- break;
- case NativeType.Currency:
- output.Write("currency");
- break;
- case NativeType.BStr:
- output.Write("bstr");
- break;
- case NativeType.LPWStr:
- output.Write("lpwstr");
- break;
- case NativeType.LPTStr:
- output.Write("lptstr");
- break;
- case NativeType.FixedSysString:
- output.Write("fixed sysstring[{0}]", ((FixedSysStringMarshalInfo)marshalInfo).Size);
- break;
- case NativeType.IUnknown:
- output.Write("iunknown");
- break;
- case NativeType.IDispatch:
- output.Write("idispatch");
- break;
- case NativeType.Struct:
- output.Write("struct");
- break;
- case NativeType.IntF:
- output.Write("interface");
- break;
- case NativeType.SafeArray:
- output.Write("safearray ");
- SafeArrayMarshalInfo sami = marshalInfo as SafeArrayMarshalInfo;
- if (sami != null) {
- switch (sami.ElementType) {
- case VariantType.None:
- break;
- case VariantType.I2:
- output.Write("int16");
- break;
- case VariantType.I4:
- output.Write("int32");
- break;
- case VariantType.R4:
- output.Write("float32");
- break;
- case VariantType.R8:
- output.Write("float64");
- break;
- case VariantType.CY:
- output.Write("currency");
- break;
- case VariantType.Date:
- output.Write("date");
- break;
- case VariantType.BStr:
- output.Write("bstr");
- break;
- case VariantType.Dispatch:
- output.Write("idispatch");
- break;
- case VariantType.Error:
- output.Write("error");
- break;
- case VariantType.Bool:
- output.Write("bool");
- break;
- case VariantType.Variant:
- output.Write("variant");
- break;
- case VariantType.Unknown:
- output.Write("iunknown");
- break;
- case VariantType.Decimal:
- output.Write("decimal");
- break;
- case VariantType.I1:
- output.Write("int8");
- break;
- case VariantType.UI1:
- output.Write("unsigned int8");
- break;
- case VariantType.UI2:
- output.Write("unsigned int16");
- break;
- case VariantType.UI4:
- output.Write("unsigned int32");
- break;
- case VariantType.Int:
- output.Write("int");
- break;
- case VariantType.UInt:
- output.Write("unsigned int");
- break;
- default:
- output.Write(sami.ElementType.ToString());
- break;
- }
- }
- break;
- case NativeType.FixedArray:
- output.Write("fixed array");
- FixedArrayMarshalInfo fami = marshalInfo as FixedArrayMarshalInfo;
- if (fami != null) {
- output.Write("[{0}]", fami.Size);
- if (fami.ElementType != NativeType.None) {
- output.Write(' ');
- WriteNativeType(fami.ElementType);
- }
- }
- break;
- case NativeType.ByValStr:
- output.Write("byvalstr");
- break;
- case NativeType.ANSIBStr:
- output.Write("ansi bstr");
- break;
- case NativeType.TBStr:
- output.Write("tbstr");
- break;
- case NativeType.VariantBool:
- output.Write("variant bool");
- break;
- case NativeType.ASAny:
- output.Write("as any");
- break;
- case NativeType.LPStruct:
- output.Write("lpstruct");
- break;
- case NativeType.CustomMarshaler:
- CustomMarshalInfo cmi = marshalInfo as CustomMarshalInfo;
- if (cmi == null)
- goto default;
- output.Write("custom(\"{0}\", \"{1}\"",
- NRefactory.CSharp.TextWriterTokenWriter.ConvertString(cmi.ManagedType.FullName),
- NRefactory.CSharp.TextWriterTokenWriter.ConvertString(cmi.Cookie));
- if (cmi.Guid != Guid.Empty || !string.IsNullOrEmpty(cmi.UnmanagedType)) {
- output.Write(", \"{0}\", \"{1}\"", cmi.Guid.ToString(), NRefactory.CSharp.TextWriterTokenWriter.ConvertString(cmi.UnmanagedType));
- }
- output.Write(')');
- break;
- case NativeType.Error:
- output.Write("error");
- break;
- default:
- output.Write(nativeType.ToString());
- break;
- }
- }
- #endregion
-
- void WriteParameters(Collection<ParameterDefinition> parameters)
- {
- for (int i = 0; i < parameters.Count; i++) {
- var p = parameters[i];
- if (p.IsIn)
- output.Write("[in] ");
- if (p.IsOut)
- output.Write("[out] ");
- if (p.IsOptional)
- output.Write("[opt] ");
- p.ParameterType.WriteTo(output);
- output.Write(' ');
- if (p.HasMarshalInfo) {
- WriteMarshalInfo(p.MarshalInfo);
- }
- output.WriteDefinition(DisassemblerHelpers.Escape(p.Name), p);
- if (i < parameters.Count - 1)
- output.Write(',');
- output.WriteLine();
- }
- }
-
- bool HasParameterAttributes(ParameterDefinition p)
- {
- return p.HasConstant || p.HasCustomAttributes;
- }
-
- void WriteParameterAttributes(ParameterDefinition p)
- {
- if (!HasParameterAttributes(p))
- return;
- output.Write(".param [{0}]", p.Index + 1);
- if (p.HasConstant) {
- output.Write(" = ");
- WriteConstant(p.Constant);
- }
- output.WriteLine();
- WriteAttributes(p.CustomAttributes);
- }
-
- void WriteConstant(object constant)
- {
- if (constant == null) {
- output.Write("nullref");
- } else {
- string typeName = DisassemblerHelpers.PrimitiveTypeName(constant.GetType().FullName);
- if (typeName != null && typeName != "string") {
- output.Write(typeName);
- output.Write('(');
- float? cf = constant as float?;
- double? cd = constant as double?;
- if (cf.HasValue && (float.IsNaN(cf.Value) || float.IsInfinity(cf.Value))) {
- output.Write("0x{0:x8}", BitConverter.ToInt32(BitConverter.GetBytes(cf.Value), 0));
- } else if (cd.HasValue && (double.IsNaN(cd.Value) || double.IsInfinity(cd.Value))) {
- output.Write("0x{0:x16}", BitConverter.DoubleToInt64Bits(cd.Value));
- } else {
- DisassemblerHelpers.WriteOperand(output, constant);
- }
- output.Write(')');
- } else {
- DisassemblerHelpers.WriteOperand(output, constant);
- }
- }
- }
- #endregion
-
- #region Disassemble Field
- EnumNameCollection<FieldAttributes> fieldVisibility = new EnumNameCollection<FieldAttributes>() {
- { FieldAttributes.Private, "private" },
- { FieldAttributes.FamANDAssem, "famandassem" },
- { FieldAttributes.Assembly, "assembly" },
- { FieldAttributes.Family, "family" },
- { FieldAttributes.FamORAssem, "famorassem" },
- { FieldAttributes.Public, "public" },
- };
-
- EnumNameCollection<FieldAttributes> fieldAttributes = new EnumNameCollection<FieldAttributes>() {
- { FieldAttributes.Static, "static" },
- { FieldAttributes.Literal, "literal" },
- { FieldAttributes.InitOnly, "initonly" },
- { FieldAttributes.SpecialName, "specialname" },
- { FieldAttributes.RTSpecialName, "rtspecialname" },
- { FieldAttributes.NotSerialized, "notserialized" },
- };
-
- public void DisassembleField(FieldDefinition field)
- {
- output.WriteDefinition(".field ", field);
- if (field.HasLayoutInfo) {
- output.Write("[" + field.Offset + "] ");
- }
- WriteEnum(field.Attributes & FieldAttributes.FieldAccessMask, fieldVisibility);
- const FieldAttributes hasXAttributes = FieldAttributes.HasDefault | FieldAttributes.HasFieldMarshal | FieldAttributes.HasFieldRVA;
- WriteFlags(field.Attributes & ~(FieldAttributes.FieldAccessMask | hasXAttributes), fieldAttributes);
- if (field.HasMarshalInfo) {
- WriteMarshalInfo(field.MarshalInfo);
- }
- field.FieldType.WriteTo(output);
- output.Write(' ');
- output.Write(DisassemblerHelpers.Escape(field.Name));
- if ((field.Attributes & FieldAttributes.HasFieldRVA) == FieldAttributes.HasFieldRVA) {
- output.Write(" at I_{0:x8}", field.RVA);
- }
- if (field.HasConstant) {
- output.Write(" = ");
- WriteConstant(field.Constant);
- }
- output.WriteLine();
- if (field.HasCustomAttributes) {
- output.MarkFoldStart();
- WriteAttributes(field.CustomAttributes);
- output.MarkFoldEnd();
- }
- }
- #endregion
-
- #region Disassemble Property
- EnumNameCollection<PropertyAttributes> propertyAttributes = new EnumNameCollection<PropertyAttributes>() {
- { PropertyAttributes.SpecialName, "specialname" },
- { PropertyAttributes.RTSpecialName, "rtspecialname" },
- { PropertyAttributes.HasDefault, "hasdefault" },
- };
-
- public void DisassembleProperty(PropertyDefinition property)
- {
- // set current member
- currentMember = property;
-
- output.WriteDefinition(".property ", property);
- WriteFlags(property.Attributes, propertyAttributes);
- if (property.HasThis)
- output.Write("instance ");
- property.PropertyType.WriteTo(output);
- output.Write(' ');
- output.Write(DisassemblerHelpers.Escape(property.Name));
-
- output.Write("(");
- if (property.HasParameters) {
- output.WriteLine();
- output.Indent();
- WriteParameters(property.Parameters);
- output.Unindent();
- }
- output.Write(")");
-
- OpenBlock(false);
- WriteAttributes(property.CustomAttributes);
- WriteNestedMethod(".get", property.GetMethod);
- WriteNestedMethod(".set", property.SetMethod);
-
- foreach (var method in property.OtherMethods) {
- WriteNestedMethod(".other", method);
- }
- CloseBlock();
- }
-
- void WriteNestedMethod(string keyword, MethodDefinition method)
- {
- if (method == null)
- return;
-
- output.Write(keyword);
- output.Write(' ');
- method.WriteTo(output);
- output.WriteLine();
- }
- #endregion
-
- #region Disassemble Event
- EnumNameCollection<EventAttributes> eventAttributes = new EnumNameCollection<EventAttributes>() {
- { EventAttributes.SpecialName, "specialname" },
- { EventAttributes.RTSpecialName, "rtspecialname" },
- };
-
- public void DisassembleEvent(EventDefinition ev)
- {
- // set current member
- currentMember = ev;
-
- output.WriteDefinition(".event ", ev);
- WriteFlags(ev.Attributes, eventAttributes);
- ev.EventType.WriteTo(output, ILNameSyntax.TypeName);
- output.Write(' ');
- output.Write(DisassemblerHelpers.Escape(ev.Name));
- OpenBlock(false);
- WriteAttributes(ev.CustomAttributes);
- WriteNestedMethod(".addon", ev.AddMethod);
- WriteNestedMethod(".removeon", ev.RemoveMethod);
- WriteNestedMethod(".fire", ev.InvokeMethod);
- foreach (var method in ev.OtherMethods) {
- WriteNestedMethod(".other", method);
- }
- CloseBlock();
- }
- #endregion
-
- #region Disassemble Type
- EnumNameCollection<TypeAttributes> typeVisibility = new EnumNameCollection<TypeAttributes>() {
- { TypeAttributes.Public, "public" },
- { TypeAttributes.NotPublic, "private" },
- { TypeAttributes.NestedPublic, "nested public" },
- { TypeAttributes.NestedPrivate, "nested private" },
- { TypeAttributes.NestedAssembly, "nested assembly" },
- { TypeAttributes.NestedFamily, "nested family" },
- { TypeAttributes.NestedFamANDAssem, "nested famandassem" },
- { TypeAttributes.NestedFamORAssem, "nested famorassem" },
- };
-
- EnumNameCollection<TypeAttributes> typeLayout = new EnumNameCollection<TypeAttributes>() {
- { TypeAttributes.AutoLayout, "auto" },
- { TypeAttributes.SequentialLayout, "sequential" },
- { TypeAttributes.ExplicitLayout, "explicit" },
- };
-
- EnumNameCollection<TypeAttributes> typeStringFormat = new EnumNameCollection<TypeAttributes>() {
- { TypeAttributes.AutoClass, "auto" },
- { TypeAttributes.AnsiClass, "ansi" },
- { TypeAttributes.UnicodeClass, "unicode" },
- };
-
- EnumNameCollection<TypeAttributes> typeAttributes = new EnumNameCollection<TypeAttributes>() {
- { TypeAttributes.Abstract, "abstract" },
- { TypeAttributes.Sealed, "sealed" },
- { TypeAttributes.SpecialName, "specialname" },
- { TypeAttributes.Import, "import" },
- { TypeAttributes.Serializable, "serializable" },
- { TypeAttributes.WindowsRuntime, "windowsruntime" },
- { TypeAttributes.BeforeFieldInit, "beforefieldinit" },
- { TypeAttributes.HasSecurity, null },
- };
-
- public void DisassembleType(TypeDefinition type)
- {
- // start writing IL
- output.WriteDefinition(".class ", type);
-
- if ((type.Attributes & TypeAttributes.ClassSemanticMask) == TypeAttributes.Interface)
- output.Write("interface ");
- WriteEnum(type.Attributes & TypeAttributes.VisibilityMask, typeVisibility);
- WriteEnum(type.Attributes & TypeAttributes.LayoutMask, typeLayout);
- WriteEnum(type.Attributes & TypeAttributes.StringFormatMask, typeStringFormat);
- const TypeAttributes masks = TypeAttributes.ClassSemanticMask | TypeAttributes.VisibilityMask | TypeAttributes.LayoutMask | TypeAttributes.StringFormatMask;
- WriteFlags(type.Attributes & ~masks, typeAttributes);
-
- output.Write(DisassemblerHelpers.Escape(type.DeclaringType != null ? type.Name : type.FullName));
- WriteTypeParameters(output, type);
- output.MarkFoldStart(defaultCollapsed: isInType);
- output.WriteLine();
-
- if (type.BaseType != null) {
- output.Indent();
- output.Write("extends ");
- type.BaseType.WriteTo(output, ILNameSyntax.TypeName);
- output.WriteLine();
- output.Unindent();
- }
- if (type.HasInterfaces) {
- output.Indent();
- for (int index = 0; index < type.Interfaces.Count; index++) {
- if (index > 0)
- output.WriteLine(",");
- if (index == 0)
- output.Write("implements ");
- else
- output.Write(" ");
- type.Interfaces[index].WriteTo(output, ILNameSyntax.TypeName);
- }
- output.WriteLine();
- output.Unindent();
- }
-
- output.WriteLine("{");
- output.Indent();
- bool oldIsInType = isInType;
- isInType = true;
- WriteAttributes(type.CustomAttributes);
- WriteSecurityDeclarations(type);
- if (type.HasLayoutInfo) {
- output.WriteLine(".pack {0}", type.PackingSize);
- output.WriteLine(".size {0}", type.ClassSize);
- output.WriteLine();
- }
- if (type.HasNestedTypes) {
- output.WriteLine("// Nested Types");
- foreach (var nestedType in type.NestedTypes) {
- cancellationToken.ThrowIfCancellationRequested();
- DisassembleType(nestedType);
- output.WriteLine();
- }
- output.WriteLine();
- }
- if (type.HasFields) {
- output.WriteLine("// Fields");
- foreach (var field in type.Fields) {
- cancellationToken.ThrowIfCancellationRequested();
- DisassembleField(field);
- }
- output.WriteLine();
- }
- if (type.HasMethods) {
- output.WriteLine("// Methods");
- foreach (var m in type.Methods) {
- cancellationToken.ThrowIfCancellationRequested();
- DisassembleMethod(m);
- output.WriteLine();
- }
- }
- if (type.HasEvents) {
- output.WriteLine("// Events");
- foreach (var ev in type.Events) {
- cancellationToken.ThrowIfCancellationRequested();
- DisassembleEvent(ev);
- output.WriteLine();
- }
- output.WriteLine();
- }
- if (type.HasProperties) {
- output.WriteLine("// Properties");
- foreach (var prop in type.Properties) {
- cancellationToken.ThrowIfCancellationRequested();
- DisassembleProperty(prop);
- }
- output.WriteLine();
- }
- CloseBlock("end of class " + (type.DeclaringType != null ? type.Name : type.FullName));
- isInType = oldIsInType;
- }
-
- void WriteTypeParameters(ITextOutput output, IGenericParameterProvider p)
- {
- if (p.HasGenericParameters) {
- output.Write('<');
- for (int i = 0; i < p.GenericParameters.Count; i++) {
- if (i > 0)
- output.Write(", ");
- GenericParameter gp = p.GenericParameters[i];
- if (gp.HasReferenceTypeConstraint) {
- output.Write("class ");
- } else if (gp.HasNotNullableValueTypeConstraint) {
- output.Write("valuetype ");
- }
- if (gp.HasDefaultConstructorConstraint) {
- output.Write(".ctor ");
- }
- if (gp.HasConstraints) {
- output.Write('(');
- for (int j = 0; j < gp.Constraints.Count; j++) {
- if (j > 0)
- output.Write(", ");
- gp.Constraints[j].WriteTo(output, ILNameSyntax.TypeName);
- }
- output.Write(") ");
- }
- if (gp.IsContravariant) {
- output.Write('-');
- } else if (gp.IsCovariant) {
- output.Write('+');
- }
- output.Write(DisassemblerHelpers.Escape(gp.Name));
- }
- output.Write('>');
- }
- }
- #endregion
-
- #region Helper methods
- void WriteAttributes(Collection<CustomAttribute> attributes)
- {
- foreach (CustomAttribute a in attributes) {
- output.Write(".custom ");
- a.Constructor.WriteTo(output);
- byte[] blob = a.GetBlob();
- if (blob != null) {
- output.Write(" = ");
- WriteBlob(blob);
- }
- output.WriteLine();
- }
- }
-
- void WriteBlob(byte[] blob)
- {
- output.Write("(");
- output.Indent();
-
- for (int i = 0; i < blob.Length; i++) {
- if (i % 16 == 0 && i < blob.Length - 1) {
- output.WriteLine();
- } else {
- output.Write(' ');
- }
- output.Write(blob[i].ToString("x2"));
- }
-
- output.WriteLine();
- output.Unindent();
- output.Write(")");
- }
-
- void OpenBlock(bool defaultCollapsed)
- {
- output.MarkFoldStart(defaultCollapsed: defaultCollapsed);
- output.WriteLine();
- output.WriteLine("{");
- output.Indent();
- }
-
- void CloseBlock(string comment = null)
- {
- output.Unindent();
- output.Write("}");
- if (comment != null)
- output.Write(" // " + comment);
- output.MarkFoldEnd();
- output.WriteLine();
- }
-
- void WriteFlags<T>(T flags, EnumNameCollection<T> flagNames) where T : struct
- {
- long val = Convert.ToInt64(flags);
- long tested = 0;
- foreach (var pair in flagNames) {
- tested |= pair.Key;
- if ((val & pair.Key) != 0 && pair.Value != null) {
- output.Write(pair.Value);
- output.Write(' ');
- }
- }
- if ((val & ~tested) != 0)
- output.Write("flag({0:x4}) ", val & ~tested);
- }
-
- void WriteEnum<T>(T enumValue, EnumNameCollection<T> enumNames) where T : struct
- {
- long val = Convert.ToInt64(enumValue);
- foreach (var pair in enumNames) {
- if (pair.Key == val) {
- if (pair.Value != null) {
- output.Write(pair.Value);
- output.Write(' ');
- }
- return;
- }
- }
- if (val != 0) {
- output.Write("flag({0:x4})", val);
- output.Write(' ');
- }
-
- }
-
- sealed class EnumNameCollection<T> : IEnumerable<KeyValuePair<long, string>> where T : struct
- {
- List<KeyValuePair<long, string>> names = new List<KeyValuePair<long, string>>();
-
- public void Add(T flag, string name)
- {
- names.Add(new KeyValuePair<long, string>(Convert.ToInt64(flag), name));
- }
-
- public IEnumerator<KeyValuePair<long, string>> GetEnumerator()
- {
- return names.GetEnumerator();
- }
-
- System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
- {
- return names.GetEnumerator();
- }
- }
- #endregion
-
- public void DisassembleNamespace(string nameSpace, IEnumerable<TypeDefinition> types)
- {
- if (!string.IsNullOrEmpty(nameSpace)) {
- output.Write(".namespace " + DisassemblerHelpers.Escape(nameSpace));
- OpenBlock(false);
- }
- bool oldIsInType = isInType;
- isInType = true;
- foreach (TypeDefinition td in types) {
- cancellationToken.ThrowIfCancellationRequested();
- DisassembleType(td);
- output.WriteLine();
- }
- if (!string.IsNullOrEmpty(nameSpace)) {
- CloseBlock();
- isInType = oldIsInType;
- }
- }
-
- public void WriteAssemblyHeader(AssemblyDefinition asm)
- {
- output.Write(".assembly ");
- if (asm.Name.IsWindowsRuntime)
- output.Write("windowsruntime ");
- output.Write(DisassemblerHelpers.Escape(asm.Name.Name));
- OpenBlock(false);
- WriteAttributes(asm.CustomAttributes);
- WriteSecurityDeclarations(asm);
- if (asm.Name.PublicKey != null && asm.Name.PublicKey.Length > 0) {
- output.Write(".publickey = ");
- WriteBlob(asm.Name.PublicKey);
- output.WriteLine();
- }
- if (asm.Name.HashAlgorithm != AssemblyHashAlgorithm.None) {
- output.Write(".hash algorithm 0x{0:x8}", (int)asm.Name.HashAlgorithm);
- if (asm.Name.HashAlgorithm == AssemblyHashAlgorithm.SHA1)
- output.Write(" // SHA1");
- output.WriteLine();
- }
- Version v = asm.Name.Version;
- if (v != null) {
- output.WriteLine(".ver {0}:{1}:{2}:{3}", v.Major, v.Minor, v.Build, v.Revision);
- }
- CloseBlock();
- }
-
- public void WriteAssemblyReferences(ModuleDefinition module)
- {
- foreach (var mref in module.ModuleReferences) {
- output.WriteLine(".module extern {0}", DisassemblerHelpers.Escape(mref.Name));
- }
- foreach (var aref in module.AssemblyReferences) {
- output.Write(".assembly extern ");
- if (aref.IsWindowsRuntime)
- output.Write("windowsruntime ");
- output.Write(DisassemblerHelpers.Escape(aref.Name));
- OpenBlock(false);
- if (aref.PublicKeyToken != null) {
- output.Write(".publickeytoken = ");
- WriteBlob(aref.PublicKeyToken);
- output.WriteLine();
- }
- if (aref.Version != null) {
- output.WriteLine(".ver {0}:{1}:{2}:{3}", aref.Version.Major, aref.Version.Minor, aref.Version.Build, aref.Version.Revision);
- }
- CloseBlock();
- }
- }
-
- public void WriteModuleHeader(ModuleDefinition module)
- {
- if (module.HasExportedTypes) {
- foreach (ExportedType exportedType in module.ExportedTypes) {
- output.Write(".class extern ");
- if (exportedType.IsForwarder)
- output.Write("forwarder ");
- output.Write(exportedType.DeclaringType != null ? exportedType.Name : exportedType.FullName);
- OpenBlock(false);
- if (exportedType.DeclaringType != null)
- output.WriteLine(".class extern {0}", DisassemblerHelpers.Escape(exportedType.DeclaringType.FullName));
- else
- output.WriteLine(".assembly extern {0}", DisassemblerHelpers.Escape(exportedType.Scope.Name));
- CloseBlock();
- }
- }
-
- output.WriteLine(".module {0}", module.Name);
- output.WriteLine("// MVID: {0}", module.Mvid.ToString("B").ToUpperInvariant());
- // TODO: imagebase, file alignment, stackreserve, subsystem
- output.WriteLine(".corflags 0x{0:x} // {1}", module.Attributes, module.Attributes.ToString());
-
- WriteAttributes(module.CustomAttributes);
- }
-
- public void WriteModuleContents(ModuleDefinition module)
- {
- foreach (TypeDefinition td in module.Types) {
- DisassembleType(td);
- output.WriteLine();
- }
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowEdge.cs b/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowEdge.cs
deleted file mode 100644
index 98bd4399..00000000
--- a/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowEdge.cs
+++ /dev/null
@@ -1,78 +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;
-
-namespace ICSharpCode.Decompiler.FlowAnalysis
-{
- /// <summary>
- /// Describes the type of a control flow egde.
- /// </summary>
- public enum JumpType
- {
- /// <summary>
- /// A regular control flow edge.
- /// </summary>
- Normal,
- /// <summary>
- /// Jump to exception handler (an exception occurred)
- /// </summary>
- JumpToExceptionHandler,
- /// <summary>
- /// Jump from try block to leave target:
- /// This is not a real jump, as the finally handler is executed first!
- /// </summary>
- LeaveTry,
- /// <summary>
- /// Jump at endfinally (to any of the potential leave targets).
- /// For any leave-instruction, control flow enters the finally block - the edge to the leave target (LeaveTry) is not a real control flow edge.
- /// EndFinally edges are inserted at the end of the finally block, jumping to any of the targets of the leave instruction.
- /// This edge type is only used when copying of finally blocks is disabled (with copying, a normal deterministic edge is used at each copy of the endfinally node).
- /// </summary>
- EndFinally
- }
-
- /// <summary>
- /// Represents an edge in the control flow graph, pointing from Source to Target.
- /// </summary>
- public sealed class ControlFlowEdge
- {
- public readonly ControlFlowNode Source;
- public readonly ControlFlowNode Target;
- public readonly JumpType Type;
-
- public ControlFlowEdge(ControlFlowNode source, ControlFlowNode target, JumpType type)
- {
- Source = source;
- Target = target;
- Type = type;
- }
-
- public override string ToString()
- {
- switch (Type) {
- case JumpType.Normal:
- return "#" + Target.BlockIndex;
- case JumpType.JumpToExceptionHandler:
- return "e:#" + Target.BlockIndex;
- default:
- return Type.ToString() + ":#" + Target.BlockIndex;
- }
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowGraph.cs b/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowGraph.cs
deleted file mode 100644
index 7cc815a6..00000000
--- a/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowGraph.cs
+++ /dev/null
@@ -1,191 +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.Collections.ObjectModel;
-using System.Diagnostics;
-using System.Linq;
-using System.Threading;
-
-using ICSharpCode.NRefactory.Utils;
-
-namespace ICSharpCode.Decompiler.FlowAnalysis
-{
- /// <summary>
- /// Contains the control flow graph.
- /// </summary>
- /// <remarks>Use ControlFlowGraph builder to create instances of the ControlFlowGraph.</remarks>
- public sealed class ControlFlowGraph
- {
- readonly ReadOnlyCollection<ControlFlowNode> nodes;
-
- public ControlFlowNode EntryPoint {
- get { return nodes[0]; }
- }
-
- public ControlFlowNode RegularExit {
- get { return nodes[1]; }
- }
-
- public ControlFlowNode ExceptionalExit {
- get { return nodes[2]; }
- }
-
- public ReadOnlyCollection<ControlFlowNode> Nodes {
- get { return nodes; }
- }
-
- internal ControlFlowGraph(ControlFlowNode[] nodes)
- {
- this.nodes = new ReadOnlyCollection<ControlFlowNode>(nodes);
- Debug.Assert(EntryPoint.NodeType == ControlFlowNodeType.EntryPoint);
- Debug.Assert(RegularExit.NodeType == ControlFlowNodeType.RegularExit);
- Debug.Assert(ExceptionalExit.NodeType == ControlFlowNodeType.ExceptionalExit);
- }
-
- public GraphVizGraph ExportGraph()
- {
- GraphVizGraph graph = new GraphVizGraph();
- foreach (ControlFlowNode node in nodes) {
- graph.AddNode(new GraphVizNode(node.BlockIndex) { label = node.ToString(), shape = "box" });
- }
- foreach (ControlFlowNode node in nodes) {
- foreach (ControlFlowEdge edge in node.Outgoing) {
- GraphVizEdge e = new GraphVizEdge(edge.Source.BlockIndex, edge.Target.BlockIndex);
- switch (edge.Type) {
- case JumpType.Normal:
- break;
- case JumpType.LeaveTry:
- case JumpType.EndFinally:
- e.color = "red";
- break;
- default:
- e.color = "gray";
- //e.constraint = false;
- break;
- }
- graph.AddEdge(e);
- }
- if (node.ImmediateDominator != null) {
- graph.AddEdge(new GraphVizEdge(node.ImmediateDominator.BlockIndex, node.BlockIndex) { color = "green", constraint = false });
- }
- }
- return graph;
- }
-
- /// <summary>
- /// Resets "Visited" to false for all nodes in this graph.
- /// </summary>
- public void ResetVisited()
- {
- foreach (ControlFlowNode node in nodes) {
- node.Visited = false;
- }
- }
-
- /// <summary>
- /// Computes the dominator tree.
- /// </summary>
- public void ComputeDominance(CancellationToken cancellationToken = default(CancellationToken))
- {
- // A Simple, Fast Dominance Algorithm
- // Keith D. Cooper, Timothy J. Harvey and Ken Kennedy
-
- EntryPoint.ImmediateDominator = EntryPoint;
- bool changed = true;
- while (changed) {
- changed = false;
- ResetVisited();
-
- cancellationToken.ThrowIfCancellationRequested();
-
- // for all nodes b except the entry point
- EntryPoint.TraversePreOrder(
- b => b.Successors,
- b => {
- if (b != EntryPoint) {
- ControlFlowNode newIdom = b.Predecessors.First(block => block.Visited && block != b);
- // for all other predecessors p of b
- foreach (ControlFlowNode p in b.Predecessors) {
- if (p != b && p.ImmediateDominator != null) {
- newIdom = FindCommonDominator(p, newIdom);
- }
- }
- if (b.ImmediateDominator != newIdom) {
- b.ImmediateDominator = newIdom;
- changed = true;
- }
- }
- });
- }
- EntryPoint.ImmediateDominator = null;
- foreach (ControlFlowNode node in nodes) {
- if (node.ImmediateDominator != null)
- node.ImmediateDominator.DominatorTreeChildren.Add(node);
- }
- }
-
- static ControlFlowNode FindCommonDominator(ControlFlowNode b1, ControlFlowNode b2)
- {
- // Here we could use the postorder numbers to get rid of the hashset, see "A Simple, Fast Dominance Algorithm"
- HashSet<ControlFlowNode> path1 = new HashSet<ControlFlowNode>();
- while (b1 != null && path1.Add(b1))
- b1 = b1.ImmediateDominator;
- while (b2 != null) {
- if (path1.Contains(b2))
- return b2;
- else
- b2 = b2.ImmediateDominator;
- }
- throw new Exception("No common dominator found!");
- }
-
- /// <summary>
- /// Computes dominance frontiers.
- /// This method requires that the dominator tree is already computed!
- /// </summary>
- public void ComputeDominanceFrontier()
- {
- ResetVisited();
-
- EntryPoint.TraversePostOrder(
- b => b.DominatorTreeChildren,
- n => {
- //logger.WriteLine("Calculating dominance frontier for " + n.Name);
- n.DominanceFrontier = new HashSet<ControlFlowNode>();
- // DF_local computation
- foreach (ControlFlowNode succ in n.Successors) {
- if (succ.ImmediateDominator != n) {
- //logger.WriteLine(" local: " + succ.Name);
- n.DominanceFrontier.Add(succ);
- }
- }
- // DF_up computation
- foreach (ControlFlowNode child in n.DominatorTreeChildren) {
- foreach (ControlFlowNode p in child.DominanceFrontier) {
- if (p.ImmediateDominator != n) {
- //logger.WriteLine(" DF_up: " + p.Name + " (child=" + child.Name);
- n.DominanceFrontier.Add(p);
- }
- }
- }
- });
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowGraphBuilder.cs b/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowGraphBuilder.cs
deleted file mode 100644
index 7570884a..00000000
--- a/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowGraphBuilder.cs
+++ /dev/null
@@ -1,439 +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.Diagnostics;
-using System.Linq;
-
-using Mono.Cecil.Cil;
-
-namespace ICSharpCode.Decompiler.FlowAnalysis
-{
- /// <summary>
- /// Constructs the Control Flow Graph from a Cecil method body.
- /// </summary>
- public sealed class ControlFlowGraphBuilder
- {
- public static ControlFlowGraph Build(MethodBody methodBody)
- {
- return new ControlFlowGraphBuilder(methodBody).Build();
- }
-
- // This option controls how finally blocks are handled:
- // false means that the endfinally instruction will jump to any of the leave targets (EndFinally edge type).
- // true means that a copy of the whole finally block is created for each leave target. In this case, each endfinally node will be connected with the leave
- // target using a normal edge.
- bool copyFinallyBlocks = false;
-
- MethodBody methodBody;
- int[] offsets; // array index = instruction index; value = IL offset
- bool[] hasIncomingJumps; // array index = instruction index
- List<ControlFlowNode> nodes = new List<ControlFlowNode>();
- ControlFlowNode entryPoint;
- ControlFlowNode regularExit;
- ControlFlowNode exceptionalExit;
-
- ControlFlowGraphBuilder(MethodBody methodBody)
- {
- this.methodBody = methodBody;
- offsets = methodBody.Instructions.Select(i => i.Offset).ToArray();
- hasIncomingJumps = new bool[methodBody.Instructions.Count];
-
- entryPoint = new ControlFlowNode(0, 0, ControlFlowNodeType.EntryPoint);
- nodes.Add(entryPoint);
- regularExit = new ControlFlowNode(1, -1, ControlFlowNodeType.RegularExit);
- nodes.Add(regularExit);
- exceptionalExit = new ControlFlowNode(2, -1, ControlFlowNodeType.ExceptionalExit);
- nodes.Add(exceptionalExit);
- Debug.Assert(nodes.Count == 3);
- }
-
- /// <summary>
- /// Determines the index of the instruction (for use with the hasIncomingJumps array)
- /// </summary>
- int GetInstructionIndex(Instruction inst)
- {
- int index = Array.BinarySearch(offsets, inst.Offset);
- Debug.Assert(index >= 0);
- return index;
- }
-
- /// <summary>
- /// Builds the ControlFlowGraph.
- /// </summary>
- public ControlFlowGraph Build()
- {
- CalculateHasIncomingJumps();
- CreateNodes();
- CreateRegularControlFlow();
- CreateExceptionalControlFlow();
- if (copyFinallyBlocks)
- CopyFinallyBlocksIntoLeaveEdges();
- else
- TransformLeaveEdges();
- return new ControlFlowGraph(nodes.ToArray());
- }
-
- #region Step 1: calculate which instructions are the targets of jump instructions.
- void CalculateHasIncomingJumps()
- {
- foreach (Instruction inst in methodBody.Instructions) {
- if (inst.OpCode.OperandType == OperandType.InlineBrTarget || inst.OpCode.OperandType == OperandType.ShortInlineBrTarget) {
- hasIncomingJumps[GetInstructionIndex((Instruction)inst.Operand)] = true;
- } else if (inst.OpCode.OperandType == OperandType.InlineSwitch) {
- foreach (Instruction i in (Instruction[])inst.Operand)
- hasIncomingJumps[GetInstructionIndex(i)] = true;
- }
- }
- foreach (ExceptionHandler eh in methodBody.ExceptionHandlers) {
- if (eh.FilterStart != null) {
- hasIncomingJumps[GetInstructionIndex(eh.FilterStart)] = true;
- }
- hasIncomingJumps[GetInstructionIndex(eh.HandlerStart)] = true;
- }
- }
- #endregion
-
- #region Step 2: create nodes
- void CreateNodes()
- {
- // Step 2a: find basic blocks and create nodes for them
- for (int i = 0; i < methodBody.Instructions.Count; i++) {
- Instruction blockStart = methodBody.Instructions[i];
- ExceptionHandler blockStartEH = FindInnermostExceptionHandler(blockStart.Offset);
- // try and see how big we can make that block:
- for (; i + 1 < methodBody.Instructions.Count; i++) {
- Instruction inst = methodBody.Instructions[i];
- if (IsBranch(inst.OpCode) || CanThrowException(inst.OpCode))
- break;
- if (hasIncomingJumps[i + 1])
- break;
- if (inst.Next != null) {
- // ensure that blocks never contain instructions from different try blocks
- ExceptionHandler instEH = FindInnermostExceptionHandler(inst.Next.Offset);
- if (instEH != blockStartEH)
- break;
- }
- }
-
- nodes.Add(new ControlFlowNode(nodes.Count, blockStart, methodBody.Instructions[i]));
- }
- // Step 2b: Create special nodes for the exception handling constructs
- foreach (ExceptionHandler handler in methodBody.ExceptionHandlers) {
- if (handler.HandlerType == ExceptionHandlerType.Filter)
- throw new NotSupportedException();
- ControlFlowNode endFinallyOrFaultNode = null;
- if (handler.HandlerType == ExceptionHandlerType.Finally || handler.HandlerType == ExceptionHandlerType.Fault) {
- endFinallyOrFaultNode = new ControlFlowNode(nodes.Count, handler.HandlerEnd.Offset, ControlFlowNodeType.EndFinallyOrFault);
- nodes.Add(endFinallyOrFaultNode);
- }
- nodes.Add(new ControlFlowNode(nodes.Count, handler, endFinallyOrFaultNode));
- }
- }
- #endregion
-
- #region Step 3: create edges for the normal flow of control (assuming no exceptions thrown)
- void CreateRegularControlFlow()
- {
- CreateEdge(entryPoint, methodBody.Instructions[0], JumpType.Normal);
- foreach (ControlFlowNode node in nodes) {
- if (node.End != null) {
- // create normal edges from one instruction to the next
- if (!OpCodeInfo.IsUnconditionalBranch(node.End.OpCode))
- CreateEdge(node, node.End.Next, JumpType.Normal);
-
- // create edges for branch instructions
- if (node.End.OpCode.OperandType == OperandType.InlineBrTarget || node.End.OpCode.OperandType == OperandType.ShortInlineBrTarget) {
- if (node.End.OpCode == OpCodes.Leave || node.End.OpCode == OpCodes.Leave_S) {
- var handlerBlock = FindInnermostHandlerBlock(node.End.Offset);
- if (handlerBlock.NodeType == ControlFlowNodeType.FinallyOrFaultHandler)
- CreateEdge(node, (Instruction)node.End.Operand, JumpType.LeaveTry);
- else
- CreateEdge(node, (Instruction)node.End.Operand, JumpType.Normal);
- } else {
- CreateEdge(node, (Instruction)node.End.Operand, JumpType.Normal);
- }
- } else if (node.End.OpCode.OperandType == OperandType.InlineSwitch) {
- foreach (Instruction i in (Instruction[])node.End.Operand)
- CreateEdge(node, i, JumpType.Normal);
- }
-
- // create edges for return instructions
- if (node.End.OpCode.FlowControl == FlowControl.Return) {
- switch (node.End.OpCode.Code) {
- case Code.Ret:
- CreateEdge(node, regularExit, JumpType.Normal);
- break;
- case Code.Endfinally:
- ControlFlowNode handlerBlock = FindInnermostHandlerBlock(node.End.Offset);
- if (handlerBlock.EndFinallyOrFaultNode == null)
- throw new InvalidProgramException("Found endfinally in block " + handlerBlock);
- CreateEdge(node, handlerBlock.EndFinallyOrFaultNode, JumpType.Normal);
- break;
- default:
- throw new NotSupportedException(node.End.OpCode.ToString());
- }
- }
- }
- }
- }
- #endregion
-
- #region Step 4: create edges for the exceptional control flow (from instructions that might throw, to the innermost containing exception handler)
- void CreateExceptionalControlFlow()
- {
- foreach (ControlFlowNode node in nodes) {
- if (node.End != null && CanThrowException(node.End.OpCode)) {
- CreateEdge(node, FindInnermostExceptionHandlerNode(node.End.Offset), JumpType.JumpToExceptionHandler);
- }
- if (node.ExceptionHandler != null) {
- if (node.EndFinallyOrFaultNode != null) {
- // For Fault and Finally blocks, create edge from "EndFinally" to next exception handler.
- // This represents the exception bubbling up after finally block was executed.
- CreateEdge(node.EndFinallyOrFaultNode, FindParentExceptionHandlerNode(node), JumpType.JumpToExceptionHandler);
- } else {
- // For Catch blocks, create edge from "CatchHandler" block (at beginning) to next exception handler.
- // This represents the exception bubbling up because it did not match the type of the catch block.
- CreateEdge(node, FindParentExceptionHandlerNode(node), JumpType.JumpToExceptionHandler);
- }
- CreateEdge(node, node.ExceptionHandler.HandlerStart, JumpType.Normal);
- }
- }
- }
-
- ExceptionHandler FindInnermostExceptionHandler(int instructionOffsetInTryBlock)
- {
- foreach (ExceptionHandler h in methodBody.ExceptionHandlers) {
- if (h.TryStart.Offset <= instructionOffsetInTryBlock && instructionOffsetInTryBlock < h.TryEnd.Offset) {
- return h;
- }
- }
- return null;
- }
-
- ControlFlowNode FindInnermostExceptionHandlerNode(int instructionOffsetInTryBlock)
- {
- ExceptionHandler h = FindInnermostExceptionHandler(instructionOffsetInTryBlock);
- if (h != null)
- return nodes.Single(n => n.ExceptionHandler == h && n.CopyFrom == null);
- else
- return exceptionalExit;
- }
-
- ControlFlowNode FindInnermostHandlerBlock(int instructionOffset)
- {
- foreach (ExceptionHandler h in methodBody.ExceptionHandlers) {
- if (h.TryStart.Offset <= instructionOffset && instructionOffset < h.TryEnd.Offset
- || h.HandlerStart.Offset <= instructionOffset && instructionOffset < h.HandlerEnd.Offset)
- {
- return nodes.Single(n => n.ExceptionHandler == h && n.CopyFrom == null);
- }
- }
- return exceptionalExit;
- }
-
- ControlFlowNode FindParentExceptionHandlerNode(ControlFlowNode exceptionHandler)
- {
- Debug.Assert(exceptionHandler.NodeType == ControlFlowNodeType.CatchHandler
- || exceptionHandler.NodeType == ControlFlowNodeType.FinallyOrFaultHandler);
- int offset = exceptionHandler.ExceptionHandler.TryStart.Offset;
- for (int i = exceptionHandler.BlockIndex + 1; i < nodes.Count; i++) {
- ExceptionHandler h = nodes[i].ExceptionHandler;
- if (h != null && h.TryStart.Offset <= offset && offset < h.TryEnd.Offset)
- return nodes[i];
- }
- return exceptionalExit;
- }
- #endregion
-
- #region Step 5a: replace LeaveTry edges with EndFinally edges
- // this is used only for copyFinallyBlocks==false; see Step 5b otherwise
- void TransformLeaveEdges()
- {
- for (int i = nodes.Count - 1; i >= 0; i--) {
- ControlFlowNode node = nodes[i];
- if (node.End != null && node.Outgoing.Count == 1 && node.Outgoing[0].Type == JumpType.LeaveTry) {
- Debug.Assert(node.End.OpCode == OpCodes.Leave || node.End.OpCode == OpCodes.Leave_S);
-
- ControlFlowNode target = node.Outgoing[0].Target;
- // remove the edge
- target.Incoming.Remove(node.Outgoing[0]);
- node.Outgoing.Clear();
-
- ControlFlowNode handler = FindInnermostExceptionHandlerNode(node.End.Offset);
- Debug.Assert(handler.NodeType == ControlFlowNodeType.FinallyOrFaultHandler);
-
- CreateEdge(node, handler, JumpType.Normal);
- CreateEdge(handler.EndFinallyOrFaultNode, target, JumpType.EndFinally);
- }
- }
- }
- #endregion
-
- #region Step 5b: copy finally blocks into the LeaveTry edges
- void CopyFinallyBlocksIntoLeaveEdges()
- {
- // We need to process try-finally blocks inside-out.
- // We'll do that by going through all instructions in reverse order
- for (int i = nodes.Count - 1; i >= 0; i--) {
- ControlFlowNode node = nodes[i];
- if (node.End != null && node.Outgoing.Count == 1 && node.Outgoing[0].Type == JumpType.LeaveTry) {
- Debug.Assert(node.End.OpCode == OpCodes.Leave || node.End.OpCode == OpCodes.Leave_S);
-
- ControlFlowNode target = node.Outgoing[0].Target;
- // remove the edge
- target.Incoming.Remove(node.Outgoing[0]);
- node.Outgoing.Clear();
-
- ControlFlowNode handler = FindInnermostExceptionHandlerNode(node.End.Offset);
- Debug.Assert(handler.NodeType == ControlFlowNodeType.FinallyOrFaultHandler);
-
- ControlFlowNode copy = CopyFinallySubGraph(handler, handler.EndFinallyOrFaultNode, target);
- CreateEdge(node, copy, JumpType.Normal);
- }
- }
- }
-
- /// <summary>
- /// Creates a copy of all nodes pointing to 'end' and replaces those references with references to 'newEnd'.
- /// Nodes pointing to the copied node are copied recursively to update those references, too.
- /// This recursion stops at 'start'. The modified version of start is returned.
- /// </summary>
- ControlFlowNode CopyFinallySubGraph(ControlFlowNode start, ControlFlowNode end, ControlFlowNode newEnd)
- {
- return new CopyFinallySubGraphLogic(this, start, end, newEnd).CopyFinallySubGraph();
- }
-
- class CopyFinallySubGraphLogic
- {
- readonly ControlFlowGraphBuilder builder;
- readonly Dictionary<ControlFlowNode, ControlFlowNode> oldToNew = new Dictionary<ControlFlowNode, ControlFlowNode>();
- readonly ControlFlowNode start;
- readonly ControlFlowNode end;
- readonly ControlFlowNode newEnd;
-
- public CopyFinallySubGraphLogic(ControlFlowGraphBuilder builder, ControlFlowNode start, ControlFlowNode end, ControlFlowNode newEnd)
- {
- this.builder = builder;
- this.start = start;
- this.end = end;
- this.newEnd = newEnd;
- }
-
- internal ControlFlowNode CopyFinallySubGraph()
- {
- foreach (ControlFlowNode n in end.Predecessors) {
- CollectNodes(n);
- }
- foreach (var pair in oldToNew)
- ReconstructEdges(pair.Key, pair.Value);
- return GetNew(start);
- }
-
- void CollectNodes(ControlFlowNode node)
- {
- if (node == end || node == newEnd)
- throw new InvalidOperationException("unexpected cycle involving finally construct");
- if (!oldToNew.ContainsKey(node)) {
- int newBlockIndex = builder.nodes.Count;
- ControlFlowNode copy;
- switch (node.NodeType) {
- case ControlFlowNodeType.Normal:
- copy = new ControlFlowNode(newBlockIndex, node.Start, node.End);
- break;
- case ControlFlowNodeType.FinallyOrFaultHandler:
- copy = new ControlFlowNode(newBlockIndex, node.ExceptionHandler, node.EndFinallyOrFaultNode);
- break;
- default:
- // other nodes shouldn't occur when copying finally blocks
- throw new NotSupportedException(node.NodeType.ToString());
- }
- copy.CopyFrom = node;
- builder.nodes.Add(copy);
- oldToNew.Add(node, copy);
-
- if (node != start) {
- foreach (ControlFlowNode n in node.Predecessors) {
- CollectNodes(n);
- }
- }
- }
- }
-
- void ReconstructEdges(ControlFlowNode oldNode, ControlFlowNode newNode)
- {
- foreach (ControlFlowEdge oldEdge in oldNode.Outgoing) {
- builder.CreateEdge(newNode, GetNew(oldEdge.Target), oldEdge.Type);
- }
- }
-
- ControlFlowNode GetNew(ControlFlowNode oldNode)
- {
- if (oldNode == end)
- return newEnd;
- ControlFlowNode newNode;
- if (oldToNew.TryGetValue(oldNode, out newNode))
- return newNode;
- return oldNode;
- }
- }
- #endregion
-
- #region CreateEdge methods
- void CreateEdge(ControlFlowNode fromNode, Instruction toInstruction, JumpType type)
- {
- CreateEdge(fromNode, nodes.Single(n => n.Start == toInstruction), type);
- }
-
- void CreateEdge(ControlFlowNode fromNode, ControlFlowNode toNode, JumpType type)
- {
- ControlFlowEdge edge = new ControlFlowEdge(fromNode, toNode, type);
- fromNode.Outgoing.Add(edge);
- toNode.Incoming.Add(edge);
- }
- #endregion
-
- #region OpCode info
- static bool CanThrowException(OpCode opcode)
- {
- if (opcode.OpCodeType == OpCodeType.Prefix)
- return false;
- return OpCodeInfo.Get(opcode).CanThrow;
- }
-
- static bool IsBranch(OpCode opcode)
- {
- if (opcode.OpCodeType == OpCodeType.Prefix)
- return false;
- switch (opcode.FlowControl) {
- case FlowControl.Cond_Branch:
- case FlowControl.Branch:
- case FlowControl.Throw:
- case FlowControl.Return:
- return true;
- case FlowControl.Next:
- case FlowControl.Call:
- return false;
- default:
- throw new NotSupportedException(opcode.FlowControl.ToString());
- }
- }
- #endregion
- }
-}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowNode.cs b/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowNode.cs
deleted file mode 100644
index 83294fd9..00000000
--- a/ICSharpCode.Decompiler/FlowAnalysis/ControlFlowNode.cs
+++ /dev/null
@@ -1,305 +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.Diagnostics;
-using System.IO;
-using System.Linq;
-
-using ICSharpCode.Decompiler.Disassembler;
-using Mono.Cecil.Cil;
-
-namespace ICSharpCode.Decompiler.FlowAnalysis
-{
- /// <summary>
- /// Type of the control flow node
- /// </summary>
- public enum ControlFlowNodeType
- {
- /// <summary>
- /// A normal node represents a basic block.
- /// </summary>
- Normal,
- /// <summary>
- /// The entry point of the method.
- /// </summary>
- EntryPoint,
- /// <summary>
- /// The exit point of the method (every ret instruction branches to this node)
- /// </summary>
- RegularExit,
- /// <summary>
- /// This node represents leaving a method irregularly by throwing an exception.
- /// </summary>
- ExceptionalExit,
- /// <summary>
- /// This node is used as a header for exception handler blocks.
- /// </summary>
- CatchHandler,
- /// <summary>
- /// This node is used as a header for finally blocks and fault blocks.
- /// Every leave instruction in the try block leads to the handler of the containing finally block;
- /// and exceptional control flow also leads to this handler.
- /// </summary>
- FinallyOrFaultHandler,
- /// <summary>
- /// This node is used as footer for finally blocks and fault blocks.
- /// Depending on the "copyFinallyBlocks" option used when creating the graph, it is connected with all leave targets using
- /// EndFinally edges (when not copying); or with a specific leave target using a normal edge (when copying).
- /// For fault blocks, an exception edge is used to represent the "re-throwing" of the exception.
- /// </summary>
- EndFinallyOrFault
- }
-
- /// <summary>
- /// Represents a block in the control flow graph.
- /// </summary>
- public sealed class ControlFlowNode
- {
- /// <summary>
- /// Index of this node in the ControlFlowGraph.Nodes collection.
- /// </summary>
- public readonly int BlockIndex;
-
- /// <summary>
- /// Gets the IL offset of this node.
- /// </summary>
- public readonly int Offset;
-
- /// <summary>
- /// Type of the node.
- /// </summary>
- public readonly ControlFlowNodeType NodeType;
-
- /// <summary>
- /// If this node is a FinallyOrFaultHandler node, this field points to the corresponding EndFinallyOrFault node.
- /// Otherwise, this field is null.
- /// </summary>
- public readonly ControlFlowNode EndFinallyOrFaultNode;
-
- /// <summary>
- /// Visited flag, used in various algorithms.
- /// Before using it in your algorithm, reset it to false by calling ControlFlowGraph.ResetVisited();
- /// </summary>
- public bool Visited;
-
- /// <summary>
- /// Gets whether this node is reachable. Requires that dominance is computed!
- /// </summary>
- public bool IsReachable {
- get { return ImmediateDominator != null || NodeType == ControlFlowNodeType.EntryPoint; }
- }
-
- /// <summary>
- /// Signalizes that this node is a copy of another node.
- /// </summary>
- public ControlFlowNode CopyFrom { get; internal set; }
-
- /// <summary>
- /// Gets the immediate dominator (the parent in the dominator tree).
- /// Null if dominance has not been calculated; or if the node is unreachable.
- /// </summary>
- public ControlFlowNode ImmediateDominator { get; internal set; }
-
- /// <summary>
- /// List of children in the dominator tree.
- /// </summary>
- public readonly List<ControlFlowNode> DominatorTreeChildren = new List<ControlFlowNode>();
-
- /// <summary>
- /// The dominance frontier of this node.
- /// This is the set of nodes for which this node dominates a predecessor, but which are not strictly dominated by this node.
- /// </summary>
- /// <remarks>
- /// b.DominanceFrontier = { y in CFG; (exists p in predecessors(y): b dominates p) and not (b strictly dominates y)}
- /// </remarks>
- public HashSet<ControlFlowNode> DominanceFrontier;
-
- /// <summary>
- /// Start of code block represented by this node. Only set for nodetype == Normal.
- /// </summary>
- public readonly Instruction Start;
-
- /// <summary>
- /// End of the code block represented by this node. Only set for nodetype == Normal.
- /// The end is exclusive, the end instruction itself does not belong to this block.
- /// </summary>
- public readonly Instruction End;
-
- /// <summary>
- /// Gets the exception handler associated with this node.
- /// Only set for nodetype == CatchHandler or nodetype == FinallyOrFaultHandler.
- /// </summary>
- public readonly ExceptionHandler ExceptionHandler;
-
- /// <summary>
- /// List of incoming control flow edges.
- /// </summary>
- public readonly List<ControlFlowEdge> Incoming = new List<ControlFlowEdge>();
-
- /// <summary>
- /// List of outgoing control flow edges.
- /// </summary>
- public readonly List<ControlFlowEdge> Outgoing = new List<ControlFlowEdge>();
-
- /// <summary>
- /// Any user data
- /// </summary>
- public object UserData;
-
- internal ControlFlowNode(int blockIndex, int offset, ControlFlowNodeType nodeType)
- {
- BlockIndex = blockIndex;
- Offset = offset;
- NodeType = nodeType;
- }
-
- internal ControlFlowNode(int blockIndex, Instruction start, Instruction end)
- {
- if (start == null)
- throw new ArgumentNullException("start");
- if (end == null)
- throw new ArgumentNullException("end");
- BlockIndex = blockIndex;
- NodeType = ControlFlowNodeType.Normal;
- Start = start;
- End = end;
- Offset = start.Offset;
- }
-
- internal ControlFlowNode(int blockIndex, ExceptionHandler exceptionHandler, ControlFlowNode endFinallyOrFaultNode)
- {
- BlockIndex = blockIndex;
- NodeType = endFinallyOrFaultNode != null ? ControlFlowNodeType.FinallyOrFaultHandler : ControlFlowNodeType.CatchHandler;
- ExceptionHandler = exceptionHandler;
- EndFinallyOrFaultNode = endFinallyOrFaultNode;
- Debug.Assert((exceptionHandler.HandlerType == ExceptionHandlerType.Finally || exceptionHandler.HandlerType == ExceptionHandlerType.Fault) == (endFinallyOrFaultNode != null));
- Offset = exceptionHandler.HandlerStart.Offset;
- }
-
- /// <summary>
- /// Gets all predecessors (=sources of incoming edges)
- /// </summary>
- public IEnumerable<ControlFlowNode> Predecessors {
- get {
- return Incoming.Select(e => e.Source);
- }
- }
-
- /// <summary>
- /// Gets all successors (=targets of outgoing edges)
- /// </summary>
- public IEnumerable<ControlFlowNode> Successors {
- get {
- return Outgoing.Select(e => e.Target);
- }
- }
-
- /// <summary>
- /// Gets all instructions in this node.
- /// Returns an empty list for special nodes that don't have any instructions.
- /// </summary>
- public IEnumerable<Instruction> Instructions {
- get {
- Instruction inst = Start;
- if (inst != null) {
- yield return inst;
- while (inst != End) {
- inst = inst.Next;
- yield return inst;
- }
- }
- }
- }
-
- public void TraversePreOrder(Func<ControlFlowNode, IEnumerable<ControlFlowNode>> children, Action<ControlFlowNode> visitAction)
- {
- if (Visited)
- return;
- Visited = true;
- visitAction(this);
- foreach (ControlFlowNode t in children(this))
- t.TraversePreOrder(children, visitAction);
- }
-
- public void TraversePostOrder(Func<ControlFlowNode, IEnumerable<ControlFlowNode>> children, Action<ControlFlowNode> visitAction)
- {
- if (Visited)
- return;
- Visited = true;
- foreach (ControlFlowNode t in children(this))
- t.TraversePostOrder(children, visitAction);
- visitAction(this);
- }
-
- public override string ToString()
- {
- StringWriter writer = new StringWriter();
- switch (NodeType) {
- case ControlFlowNodeType.Normal:
- writer.Write("Block #{0}", BlockIndex);
- if (Start != null)
- writer.Write(": IL_{0:x4}", Start.Offset);
- if (End != null)
- writer.Write(" to IL_{0:x4}", End.GetEndOffset());
- break;
- case ControlFlowNodeType.CatchHandler:
- case ControlFlowNodeType.FinallyOrFaultHandler:
- writer.Write("Block #{0}: {1}: ", BlockIndex, NodeType);
- DisassemblerHelpers.WriteTo(ExceptionHandler, new PlainTextOutput(writer));
- break;
- default:
- writer.Write("Block #{0}: {1}", BlockIndex, NodeType);
- break;
- }
-// if (ImmediateDominator != null) {
-// writer.WriteLine();
-// writer.Write("ImmediateDominator: #{0}", ImmediateDominator.BlockIndex);
-// }
- if (DominanceFrontier != null && DominanceFrontier.Any()) {
- writer.WriteLine();
- writer.Write("DominanceFrontier: " + string.Join(",", DominanceFrontier.OrderBy(d => d.BlockIndex).Select(d => d.BlockIndex.ToString())));
- }
- foreach (Instruction inst in Instructions) {
- writer.WriteLine();
- DisassemblerHelpers.WriteTo(inst, new PlainTextOutput(writer));
- }
- if (UserData != null) {
- writer.WriteLine();
- writer.Write(UserData.ToString());
- }
- return writer.ToString();
- }
-
- /// <summary>
- /// Gets whether <c>this</c> dominates <paramref name="node"/>.
- /// </summary>
- public bool Dominates(ControlFlowNode node)
- {
- // TODO: this can be made O(1) by numbering the dominator tree
- ControlFlowNode tmp = node;
- while (tmp != null) {
- if (tmp == this)
- return true;
- tmp = tmp.ImmediateDominator;
- }
- return false;
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/ControlStructureDetector.cs b/ICSharpCode.Decompiler/FlowAnalysis/ControlStructureDetector.cs
deleted file mode 100644
index b7b77e07..00000000
--- a/ICSharpCode.Decompiler/FlowAnalysis/ControlStructureDetector.cs
+++ /dev/null
@@ -1,241 +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.Diagnostics;
-using System.Linq;
-using System.Threading;
-using Mono.Cecil.Cil;
-
-namespace ICSharpCode.Decompiler.FlowAnalysis
-{
- /// <summary>
- /// Detects the structure of the control flow (exception blocks and loops).
- /// </summary>
- public class ControlStructureDetector
- {
- public static ControlStructure DetectStructure(ControlFlowGraph g, IEnumerable<ExceptionHandler> exceptionHandlers, CancellationToken cancellationToken)
- {
- ControlStructure root = new ControlStructure(new HashSet<ControlFlowNode>(g.Nodes), g.EntryPoint, ControlStructureType.Root);
- // First build a structure tree out of the exception table
- DetectExceptionHandling(root, g, exceptionHandlers);
- // Then run the loop detection.
- DetectLoops(g, root, cancellationToken);
- return root;
- }
-
- #region Exception Handling
- static void DetectExceptionHandling(ControlStructure current, ControlFlowGraph g, IEnumerable<ExceptionHandler> exceptionHandlers)
- {
- // We rely on the fact that the exception handlers are sorted so that the innermost come first.
- // For each exception handler, we determine the nodes and substructures inside that handler, and move them into a new substructure.
- // This is always possible because exception handlers are guaranteed (by the CLR spec) to be properly nested and non-overlapping;
- // so they directly form the tree that we need.
- foreach (ExceptionHandler eh in exceptionHandlers) {
- var tryNodes = FindNodes(current, eh.TryStart, eh.TryEnd);
- current.Nodes.ExceptWith(tryNodes);
- ControlStructure tryBlock = new ControlStructure(
- tryNodes,
- g.Nodes.Single(n => n.Start == eh.TryStart),
- ControlStructureType.Try);
- tryBlock.ExceptionHandler = eh;
- MoveControlStructures(current, tryBlock, eh.TryStart, eh.TryEnd);
- current.Children.Add(tryBlock);
-
- if (eh.FilterStart != null) {
- throw new NotSupportedException();
- }
-
- var handlerNodes = FindNodes(current, eh.HandlerStart, eh.HandlerEnd);
- var handlerNode = current.Nodes.Single(n => n.ExceptionHandler == eh);
- handlerNodes.Add(handlerNode);
- if (handlerNode.EndFinallyOrFaultNode != null)
- handlerNodes.Add(handlerNode.EndFinallyOrFaultNode);
- current.Nodes.ExceptWith(handlerNodes);
- ControlStructure handlerBlock = new ControlStructure(
- handlerNodes, handlerNode, ControlStructureType.Handler);
- handlerBlock.ExceptionHandler = eh;
- MoveControlStructures(current, handlerBlock, eh.HandlerStart, eh.HandlerEnd);
- current.Children.Add(handlerBlock);
- }
- }
-
- /// <summary>
- /// Removes all nodes from start to end (exclusive) from this ControlStructure and moves them to the target structure.
- /// </summary>
- static HashSet<ControlFlowNode> FindNodes(ControlStructure current, Instruction startInst, Instruction endInst)
- {
- HashSet<ControlFlowNode> result = new HashSet<ControlFlowNode>();
- int start = startInst.Offset;
- int end = endInst.Offset;
- foreach (var node in current.Nodes.ToArray()) {
- if (node.Start != null && start <= node.Start.Offset && node.Start.Offset < end) {
- result.Add(node);
- }
- }
- return result;
- }
-
- static void MoveControlStructures(ControlStructure current, ControlStructure target, Instruction startInst, Instruction endInst)
- {
- for (int i = 0; i < current.Children.Count; i++) {
- var child = current.Children[i];
- if (startInst.Offset <= child.EntryPoint.Offset && child.EntryPoint.Offset < endInst.Offset) {
- current.Children.RemoveAt(i--);
- target.Children.Add(child);
- target.AllNodes.UnionWith(child.AllNodes);
- }
- }
- }
- #endregion
-
- #region Loop Detection
- // Loop detection works like this:
- // We find a top-level loop by looking for its entry point, which is characterized by a node dominating its own predecessor.
- // Then we determine all other nodes that belong to such a loop (all nodes which lead to the entry point, and are dominated by it).
- // Finally, we check whether our result conforms with potential existing exception structures, and create the substructure for the loop if successful.
-
- // This algorithm is applied recursively for any substructures (both detected loops and exception blocks)
-
- // But maybe we should get rid of this complex stuff and instead treat every backward jump as a loop?
- // That should still work with the IL produced by compilers, and has the advantage that the detected loop bodies are consecutive IL regions.
-
- static void DetectLoops(ControlFlowGraph g, ControlStructure current, CancellationToken cancellationToken)
- {
- if (!current.EntryPoint.IsReachable)
- return;
- g.ResetVisited();
- cancellationToken.ThrowIfCancellationRequested();
- FindLoops(current, current.EntryPoint);
- foreach (ControlStructure loop in current.Children)
- DetectLoops(g, loop, cancellationToken);
- }
-
- static void FindLoops(ControlStructure current, ControlFlowNode node)
- {
- if (node.Visited)
- return;
- node.Visited = true;
- if (current.Nodes.Contains(node)
- && node.DominanceFrontier.Contains(node)
- && !(node == current.EntryPoint && current.Type == ControlStructureType.Loop))
- {
- HashSet<ControlFlowNode> loopContents = new HashSet<ControlFlowNode>();
- FindLoopContents(current, loopContents, node, node);
- List<ControlStructure> containedChildStructures = new List<ControlStructure>();
- bool invalidNesting = false;
- foreach (ControlStructure childStructure in current.Children) {
- if (childStructure.AllNodes.IsSubsetOf(loopContents)) {
- containedChildStructures.Add(childStructure);
- } else if (childStructure.AllNodes.Intersect(loopContents).Any()) {
- invalidNesting = true;
- }
- }
- if (!invalidNesting) {
- current.Nodes.ExceptWith(loopContents);
- ControlStructure ctl = new ControlStructure(loopContents, node, ControlStructureType.Loop);
- foreach (ControlStructure childStructure in containedChildStructures) {
- ctl.Children.Add(childStructure);
- current.Children.Remove(childStructure);
- ctl.Nodes.ExceptWith(childStructure.AllNodes);
- }
- current.Children.Add(ctl);
- }
- }
- foreach (var edge in node.Outgoing) {
- FindLoops(current, edge.Target);
- }
- }
-
- static void FindLoopContents(ControlStructure current, HashSet<ControlFlowNode> loopContents, ControlFlowNode loopHead, ControlFlowNode node)
- {
- if (current.AllNodes.Contains(node) && loopHead.Dominates(node) && loopContents.Add(node)) {
- foreach (var edge in node.Incoming) {
- FindLoopContents(current, loopContents, loopHead, edge.Source);
- }
- }
- }
- #endregion
- }
-
- public enum ControlStructureType
- {
- /// <summary>
- /// The root block of the method
- /// </summary>
- Root,
- /// <summary>
- /// A nested control structure representing a loop.
- /// </summary>
- Loop,
- /// <summary>
- /// A nested control structure representing a try block.
- /// </summary>
- Try,
- /// <summary>
- /// A nested control structure representing a catch, finally, or fault block.
- /// </summary>
- Handler,
- /// <summary>
- /// A nested control structure representing an exception filter block.
- /// </summary>
- Filter
- }
-
- /// <summary>
- /// Represents the structure detected by the <see cref="ControlStructureDetector"/>.
- ///
- /// This is a tree of ControlStructure nodes. Each node contains a set of CFG nodes, and every CFG node is contained in exactly one ControlStructure node.
- /// </summary>
- public class ControlStructure
- {
- public readonly ControlStructureType Type;
- public readonly List<ControlStructure> Children = new List<ControlStructure>();
-
- /// <summary>
- /// The nodes in this control structure.
- /// </summary>
- public readonly HashSet<ControlFlowNode> Nodes;
-
- /// <summary>
- /// The nodes in this control structure and in all child control structures.
- /// </summary>
- public readonly HashSet<ControlFlowNode> AllNodes;
-
- /// <summary>
- /// The entry point of this control structure.
- /// </summary>
- public readonly ControlFlowNode EntryPoint;
-
- /// <summary>
- /// The exception handler associated with this Try,Handler or Finally structure.
- /// </summary>
- public ExceptionHandler ExceptionHandler;
-
- public ControlStructure(HashSet<ControlFlowNode> nodes, ControlFlowNode entryPoint, ControlStructureType type)
- {
- if (nodes == null)
- throw new ArgumentNullException("nodes");
- Nodes = nodes;
- EntryPoint = entryPoint;
- Type = type;
- AllNodes = new HashSet<ControlFlowNode>(nodes);
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/OpCodeInfo.cs b/ICSharpCode.Decompiler/FlowAnalysis/OpCodeInfo.cs
deleted file mode 100644
index e0dc724f..00000000
--- a/ICSharpCode.Decompiler/FlowAnalysis/OpCodeInfo.cs
+++ /dev/null
@@ -1,312 +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 Mono.Cecil.Cil;
-
-namespace ICSharpCode.Decompiler.FlowAnalysis
-{
- /// <summary>
- /// Additional info about opcodes.
- /// </summary>
- internal sealed class OpCodeInfo
- {
- public static bool IsUnconditionalBranch(OpCode opcode)
- {
- if (opcode.OpCodeType == OpCodeType.Prefix)
- return false;
- switch (opcode.FlowControl) {
- case FlowControl.Branch:
- case FlowControl.Throw:
- case FlowControl.Return:
- return true;
- case FlowControl.Next:
- case FlowControl.Call:
- case FlowControl.Cond_Branch:
- return false;
- default:
- throw new NotSupportedException(opcode.FlowControl.ToString());
- }
- }
-
- static readonly OpCodeInfo[] knownOpCodes = {
- #region Base Instructions
- new OpCodeInfo(OpCodes.Add) { CanThrow = false },
- new OpCodeInfo(OpCodes.Add_Ovf) { CanThrow = true },
- new OpCodeInfo(OpCodes.Add_Ovf_Un) { CanThrow = true },
- new OpCodeInfo(OpCodes.And) { CanThrow = false },
- new OpCodeInfo(OpCodes.Arglist) { CanThrow = false },
- new OpCodeInfo(OpCodes.Beq) { CanThrow = false },
- new OpCodeInfo(OpCodes.Beq_S) { CanThrow = false },
- new OpCodeInfo(OpCodes.Bge) { CanThrow = false },
- new OpCodeInfo(OpCodes.Bge_S) { CanThrow = false },
- new OpCodeInfo(OpCodes.Bge_Un) { CanThrow = false },
- new OpCodeInfo(OpCodes.Bge_Un_S) { CanThrow = false },
- new OpCodeInfo(OpCodes.Bgt) { CanThrow = false },
- new OpCodeInfo(OpCodes.Bgt_S) { CanThrow = false },
- new OpCodeInfo(OpCodes.Bgt_Un) { CanThrow = false },
- new OpCodeInfo(OpCodes.Bgt_Un_S) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ble) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ble_S) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ble_Un) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ble_Un_S) { CanThrow = false },
- new OpCodeInfo(OpCodes.Blt) { CanThrow = false },
- new OpCodeInfo(OpCodes.Blt_S) { CanThrow = false },
- new OpCodeInfo(OpCodes.Blt_Un) { CanThrow = false },
- new OpCodeInfo(OpCodes.Blt_Un_S) { CanThrow = false },
- new OpCodeInfo(OpCodes.Bne_Un) { CanThrow = false },
- new OpCodeInfo(OpCodes.Bne_Un_S) { CanThrow = false },
- new OpCodeInfo(OpCodes.Br) { CanThrow = false },
- new OpCodeInfo(OpCodes.Br_S) { CanThrow = false },
- new OpCodeInfo(OpCodes.Break) { CanThrow = true },
- new OpCodeInfo(OpCodes.Brfalse) { CanThrow = false },
- new OpCodeInfo(OpCodes.Brfalse_S) { CanThrow = false },
- new OpCodeInfo(OpCodes.Brtrue) { CanThrow = false },
- new OpCodeInfo(OpCodes.Brtrue_S) { CanThrow = false },
- new OpCodeInfo(OpCodes.Call) { CanThrow = true },
- new OpCodeInfo(OpCodes.Calli) { CanThrow = true },
- new OpCodeInfo(OpCodes.Ceq) { CanThrow = false },
- new OpCodeInfo(OpCodes.Cgt) { CanThrow = false },
- new OpCodeInfo(OpCodes.Cgt_Un) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ckfinite) { CanThrow = true },
- new OpCodeInfo(OpCodes.Clt) { CanThrow = false },
- new OpCodeInfo(OpCodes.Clt_Un) { CanThrow = false },
- // conv.<to type>
- new OpCodeInfo(OpCodes.Conv_I1) { CanThrow = false },
- new OpCodeInfo(OpCodes.Conv_I2) { CanThrow = false },
- new OpCodeInfo(OpCodes.Conv_I4) { CanThrow = false },
- new OpCodeInfo(OpCodes.Conv_I8) { CanThrow = false },
- new OpCodeInfo(OpCodes.Conv_R4) { CanThrow = false },
- new OpCodeInfo(OpCodes.Conv_R8) { CanThrow = false },
- new OpCodeInfo(OpCodes.Conv_U1) { CanThrow = false },
- new OpCodeInfo(OpCodes.Conv_U2) { CanThrow = false },
- new OpCodeInfo(OpCodes.Conv_U4) { CanThrow = false },
- new OpCodeInfo(OpCodes.Conv_U8) { CanThrow = false },
- new OpCodeInfo(OpCodes.Conv_I) { CanThrow = false },
- new OpCodeInfo(OpCodes.Conv_U) { CanThrow = false },
- new OpCodeInfo(OpCodes.Conv_R_Un) { CanThrow = false },
- // conv.ovf.<to type>
- new OpCodeInfo(OpCodes.Conv_Ovf_I1) { CanThrow = true},
- new OpCodeInfo(OpCodes.Conv_Ovf_I2) { CanThrow = true},
- new OpCodeInfo(OpCodes.Conv_Ovf_I4) { CanThrow = true},
- new OpCodeInfo(OpCodes.Conv_Ovf_I8) { CanThrow = true},
- new OpCodeInfo(OpCodes.Conv_Ovf_U1) { CanThrow = true},
- new OpCodeInfo(OpCodes.Conv_Ovf_U2) { CanThrow = true},
- new OpCodeInfo(OpCodes.Conv_Ovf_U4) { CanThrow = true},
- new OpCodeInfo(OpCodes.Conv_Ovf_U8) { CanThrow = true},
- new OpCodeInfo(OpCodes.Conv_Ovf_I) { CanThrow = true},
- new OpCodeInfo(OpCodes.Conv_Ovf_U) { CanThrow = true},
- // conv.ovf.<to type>.un
- new OpCodeInfo(OpCodes.Conv_Ovf_I1_Un) { CanThrow = true },
- new OpCodeInfo(OpCodes.Conv_Ovf_I2_Un) { CanThrow = true },
- new OpCodeInfo(OpCodes.Conv_Ovf_I4_Un) { CanThrow = true },
- new OpCodeInfo(OpCodes.Conv_Ovf_I8_Un) { CanThrow = true },
- new OpCodeInfo(OpCodes.Conv_Ovf_U1_Un) { CanThrow = true },
- new OpCodeInfo(OpCodes.Conv_Ovf_U2_Un) { CanThrow = true },
- new OpCodeInfo(OpCodes.Conv_Ovf_U4_Un) { CanThrow = true },
- new OpCodeInfo(OpCodes.Conv_Ovf_U8_Un) { CanThrow = true },
- new OpCodeInfo(OpCodes.Conv_Ovf_I_Un) { CanThrow = true },
- new OpCodeInfo(OpCodes.Conv_Ovf_U_Un) { CanThrow = true },
-
- //new OpCodeInfo(OpCodes.Cpblk) { CanThrow = true }, - no idea whether this might cause trouble for the type system, C# shouldn't use it so I'll disable it
- new OpCodeInfo(OpCodes.Div) { CanThrow = true },
- new OpCodeInfo(OpCodes.Div_Un) { CanThrow = true },
- new OpCodeInfo(OpCodes.Dup) { CanThrow = true, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Endfilter) { CanThrow = false },
- new OpCodeInfo(OpCodes.Endfinally) { CanThrow = false },
- //new OpCodeInfo(OpCodes.Initblk) { CanThrow = true }, - no idea whether this might cause trouble for the type system, C# shouldn't use it so I'll disable it
- //new OpCodeInfo(OpCodes.Jmp) { CanThrow = true } - We don't support non-local control transfers.
- new OpCodeInfo(OpCodes.Ldarg) { CanThrow = false, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Ldarg_0) { CanThrow = false, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Ldarg_1) { CanThrow = false, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Ldarg_2) { CanThrow = false, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Ldarg_3) { CanThrow = false, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Ldarg_S) { CanThrow = false, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Ldarga) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldarga_S) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldc_I4) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldc_I4_M1) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldc_I4_0) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldc_I4_1) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldc_I4_2) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldc_I4_3) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldc_I4_4) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldc_I4_5) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldc_I4_6) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldc_I4_7) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldc_I4_8) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldc_I4_S) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldc_I8) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldc_R4) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldc_R8) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldftn) { CanThrow = false },
- // ldind.<type>
- new OpCodeInfo(OpCodes.Ldind_I1) { CanThrow = true },
- new OpCodeInfo(OpCodes.Ldind_I2) { CanThrow = true },
- new OpCodeInfo(OpCodes.Ldind_I4) { CanThrow = true },
- new OpCodeInfo(OpCodes.Ldind_I8) { CanThrow = true },
- new OpCodeInfo(OpCodes.Ldind_U1) { CanThrow = true },
- new OpCodeInfo(OpCodes.Ldind_U2) { CanThrow = true },
- new OpCodeInfo(OpCodes.Ldind_U4) { CanThrow = true },
- new OpCodeInfo(OpCodes.Ldind_R4) { CanThrow = true },
- new OpCodeInfo(OpCodes.Ldind_R8) { CanThrow = true },
- new OpCodeInfo(OpCodes.Ldind_I) { CanThrow = true },
- new OpCodeInfo(OpCodes.Ldind_Ref) { CanThrow = true },
- // the ldloc exceptions described in the spec can only occur on methods without .localsinit - but csc always sets that flag
- new OpCodeInfo(OpCodes.Ldloc) { CanThrow = false, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Ldloc_0) { CanThrow = false, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Ldloc_1) { CanThrow = false, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Ldloc_2) { CanThrow = false, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Ldloc_3) { CanThrow = false, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Ldloc_S) { CanThrow = false, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Ldloca) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldloca_S) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldnull) { CanThrow = false },
- new OpCodeInfo(OpCodes.Leave) { CanThrow = false },
- new OpCodeInfo(OpCodes.Leave_S) { CanThrow = false },
- new OpCodeInfo(OpCodes.Localloc) { CanThrow = true },
- new OpCodeInfo(OpCodes.Mul) { CanThrow = false },
- new OpCodeInfo(OpCodes.Mul_Ovf) { CanThrow = true },
- new OpCodeInfo(OpCodes.Mul_Ovf_Un) { CanThrow = true },
- new OpCodeInfo(OpCodes.Neg) { CanThrow = false },
- new OpCodeInfo(OpCodes.Nop) { CanThrow = false },
- new OpCodeInfo(OpCodes.Not) { CanThrow = false },
- new OpCodeInfo(OpCodes.Or) { CanThrow = false },
- new OpCodeInfo(OpCodes.Pop) { CanThrow = false },
- new OpCodeInfo(OpCodes.Rem) { CanThrow = true },
- new OpCodeInfo(OpCodes.Rem_Un) { CanThrow = true },
- new OpCodeInfo(OpCodes.Ret) { CanThrow = false },
- new OpCodeInfo(OpCodes.Shl) { CanThrow = false },
- new OpCodeInfo(OpCodes.Shr) { CanThrow = false },
- new OpCodeInfo(OpCodes.Shr_Un) { CanThrow = false },
- new OpCodeInfo(OpCodes.Starg) { CanThrow = false, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Starg_S) { CanThrow = false, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Stind_I1) { CanThrow = true },
- new OpCodeInfo(OpCodes.Stind_I2) { CanThrow = true },
- new OpCodeInfo(OpCodes.Stind_I4) { CanThrow = true },
- new OpCodeInfo(OpCodes.Stind_I8) { CanThrow = true },
- new OpCodeInfo(OpCodes.Stind_R4) { CanThrow = true },
- new OpCodeInfo(OpCodes.Stind_R8) { CanThrow = true },
- new OpCodeInfo(OpCodes.Stind_I) { CanThrow = true },
- new OpCodeInfo(OpCodes.Stind_Ref) { CanThrow = true },
- new OpCodeInfo(OpCodes.Stloc) { CanThrow = false, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Stloc_0) { CanThrow = false, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Stloc_1) { CanThrow = false, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Stloc_2) { CanThrow = false, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Stloc_3) { CanThrow = false, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Stloc_S) { CanThrow = false, IsMoveInstruction = true },
- new OpCodeInfo(OpCodes.Sub) { CanThrow = false },
- new OpCodeInfo(OpCodes.Sub_Ovf) { CanThrow = true },
- new OpCodeInfo(OpCodes.Sub_Ovf_Un) { CanThrow = true },
- new OpCodeInfo(OpCodes.Switch) { CanThrow = false },
- new OpCodeInfo(OpCodes.Xor) { CanThrow = false },
- #endregion
- #region Object model instructions
- // CanThrow is true by default - most OO instructions can throw, so we don't specify CanThrow all of the time
- new OpCodeInfo(OpCodes.Box),
- new OpCodeInfo(OpCodes.Callvirt),
- new OpCodeInfo(OpCodes.Castclass),
- new OpCodeInfo(OpCodes.Cpobj),
- new OpCodeInfo(OpCodes.Initobj) { CanThrow = false },
- new OpCodeInfo(OpCodes.Isinst) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldelem_Any),
- // ldelem.<type>
- new OpCodeInfo(OpCodes.Ldelem_I) ,
- new OpCodeInfo(OpCodes.Ldelem_I1),
- new OpCodeInfo(OpCodes.Ldelem_I2),
- new OpCodeInfo(OpCodes.Ldelem_I4),
- new OpCodeInfo(OpCodes.Ldelem_I8),
- new OpCodeInfo(OpCodes.Ldelem_R4),
- new OpCodeInfo(OpCodes.Ldelem_R8),
- new OpCodeInfo(OpCodes.Ldelem_Ref),
- new OpCodeInfo(OpCodes.Ldelem_U1),
- new OpCodeInfo(OpCodes.Ldelem_U2),
- new OpCodeInfo(OpCodes.Ldelem_U4),
- new OpCodeInfo(OpCodes.Ldelema) ,
- new OpCodeInfo(OpCodes.Ldfld) ,
- new OpCodeInfo(OpCodes.Ldflda),
- new OpCodeInfo(OpCodes.Ldlen) ,
- new OpCodeInfo(OpCodes.Ldobj) ,
- new OpCodeInfo(OpCodes.Ldsfld),
- new OpCodeInfo(OpCodes.Ldsflda),
- new OpCodeInfo(OpCodes.Ldstr) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldtoken) { CanThrow = false },
- new OpCodeInfo(OpCodes.Ldvirtftn),
- new OpCodeInfo(OpCodes.Mkrefany),
- new OpCodeInfo(OpCodes.Newarr),
- new OpCodeInfo(OpCodes.Newobj),
- new OpCodeInfo(OpCodes.Refanytype) { CanThrow = false },
- new OpCodeInfo(OpCodes.Refanyval),
- new OpCodeInfo(OpCodes.Rethrow),
- new OpCodeInfo(OpCodes.Sizeof) { CanThrow = false },
- new OpCodeInfo(OpCodes.Stelem_Any),
- new OpCodeInfo(OpCodes.Stelem_I1),
- new OpCodeInfo(OpCodes.Stelem_I2),
- new OpCodeInfo(OpCodes.Stelem_I4),
- new OpCodeInfo(OpCodes.Stelem_I8),
- new OpCodeInfo(OpCodes.Stelem_R4),
- new OpCodeInfo(OpCodes.Stelem_R8),
- new OpCodeInfo(OpCodes.Stelem_Ref),
- new OpCodeInfo(OpCodes.Stfld),
- new OpCodeInfo(OpCodes.Stobj),
- new OpCodeInfo(OpCodes.Stsfld),
- new OpCodeInfo(OpCodes.Throw),
- new OpCodeInfo(OpCodes.Unbox),
- new OpCodeInfo(OpCodes.Unbox_Any),
- #endregion
- };
- static readonly Dictionary<Code, OpCodeInfo> knownOpCodeDict = knownOpCodes.ToDictionary(info => info.OpCode.Code);
-
- public static OpCodeInfo Get(OpCode opCode)
- {
- return Get(opCode.Code);
- }
-
- public static OpCodeInfo Get(Code code)
- {
- OpCodeInfo info;
- if (knownOpCodeDict.TryGetValue(code, out info))
- return info;
- else
- throw new NotSupportedException(code.ToString());
- }
-
- OpCode opcode;
-
- OpCodeInfo(OpCode opcode)
- {
- this.opcode = opcode;
- CanThrow = true;
- }
-
- public OpCode OpCode { get { return opcode; } }
-
- /// <summary>
- /// 'Move' kind of instructions have one input (may be stack or local variable) and copy that value to all outputs (again stack or local variable).
- /// </summary>
- public bool IsMoveInstruction { get; private set; }
-
- /// <summary>
- /// Specifies whether this opcode is capable of throwing exceptions.
- /// </summary>
- public bool CanThrow { get; private set; }
- }
-}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/SimplifyByRefCalls.cs b/ICSharpCode.Decompiler/FlowAnalysis/SimplifyByRefCalls.cs
deleted file mode 100644
index 42c30914..00000000
--- a/ICSharpCode.Decompiler/FlowAnalysis/SimplifyByRefCalls.cs
+++ /dev/null
@@ -1,174 +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.Diagnostics;
-
-using Mono.Cecil;
-using Mono.Cecil.Cil;
-
-namespace ICSharpCode.Decompiler.FlowAnalysis
-{
- /// <summary>
- /// This is a transformation working on SSA form.
- /// It removes ldloca instructions and replaces them with SpecialOpCode.PrepareByOutCall or SpecialOpCode.PrepareByRefCall.
- /// This then allows the variable that had its address taken to also be transformed into SSA.
- /// </summary>
- internal sealed class SimplifyByRefCalls
- {
- public static bool MakeByRefCallsSimple(SsaForm ssaForm)
- {
- SimplifyByRefCalls instance = new SimplifyByRefCalls(ssaForm);
- foreach (SsaBlock block in ssaForm.Blocks) {
- for (int i = 0; i < block.Instructions.Count; i++) {
- SsaInstruction inst = block.Instructions[i];
- if (inst.Instruction != null) {
- switch (inst.Instruction.OpCode.Code) {
- case Code.Call:
- case Code.Callvirt:
- instance.MakeByRefCallSimple(block, ref i, (IMethodSignature)inst.Instruction.Operand);
- break;
- case Code.Initobj:
- instance.MakeInitObjCallSimple(block, ref i);
- break;
- case Code.Ldfld:
- instance.MakeLoadFieldCallSimple(block, ref i);
- break;
- }
- }
- }
- }
- instance.RemoveRedundantInstructions();
- if (instance.couldSimplifySomething)
- ssaForm.ComputeVariableUsage();
- return instance.couldSimplifySomething;
- }
-
- readonly SsaForm ssaForm;
-
- bool couldSimplifySomething;
-
- // the list of ldloca instructions we will remove
- readonly List<SsaInstruction> redundantLoadAddressInstructions = new List<SsaInstruction>();
-
- SimplifyByRefCalls(SsaForm ssaForm)
- {
- this.ssaForm = ssaForm;
- }
-
- void MakeByRefCallSimple(SsaBlock block, ref int instructionIndexInBlock, IMethodSignature targetMethod)
- {
- SsaInstruction inst = block.Instructions[instructionIndexInBlock];
- for (int i = 0; i < inst.Operands.Length; i++) {
- SsaVariable operand = inst.Operands[i];
- if (operand.IsSingleAssignment && operand.Usage.Count == 1 && IsLoadAddress(operand.Definition)) {
- // address is used for this method call only
-
- Instruction loadAddressInstruction = operand.Definition.Instruction;
-
- // find target parameter type:
- bool isOut;
- if (i == 0 && targetMethod.HasThis) {
- isOut = false;
- } else {
- ParameterDefinition parameter = targetMethod.Parameters[i - (targetMethod.HasThis ? 1 : 0)];
- isOut = parameter.IsOut;
- }
-
- SsaVariable addressTakenOf = GetVariableFromLoadAddressInstruction(loadAddressInstruction);
-
- // insert "Prepare" instruction on front
- SpecialOpCode loadOpCode = isOut ? SpecialOpCode.PrepareByOutCall : SpecialOpCode.PrepareByRefCall;
- block.Instructions.Insert(instructionIndexInBlock++, new SsaInstruction(
- block, null, operand, new SsaVariable[] { addressTakenOf }, specialOpCode: loadOpCode));
-
- // insert "WriteAfterByRefOrOutCall" instruction after call
- block.Instructions.Insert(instructionIndexInBlock + 1, new SsaInstruction(
- block, null, addressTakenOf, new SsaVariable[] { operand }, specialOpCode: SpecialOpCode.WriteAfterByRefOrOutCall));
-
- couldSimplifySomething = true;
-
- // remove the loadAddressInstruction later
- // (later because it might be defined in the current block and we don't want instructionIndex to become invalid)
- redundantLoadAddressInstructions.Add(operand.Definition);
- }
- }
- }
-
- SsaVariable GetVariableFromLoadAddressInstruction(Instruction loadAddressInstruction)
- {
- if (loadAddressInstruction.OpCode == OpCodes.Ldloca) {
- return ssaForm.GetOriginalVariable((VariableReference)loadAddressInstruction.Operand);
- } else {
- Debug.Assert(loadAddressInstruction.OpCode == OpCodes.Ldarga);
- return ssaForm.GetOriginalVariable((ParameterReference)loadAddressInstruction.Operand);
- }
- }
-
- static bool IsLoadAddress(SsaInstruction inst)
- {
- return inst.Instruction != null && (inst.Instruction.OpCode == OpCodes.Ldloca || inst.Instruction.OpCode == OpCodes.Ldarga);
- }
-
- void MakeInitObjCallSimple(SsaBlock block, ref int instructionIndexInBlock)
- {
- SsaInstruction inst = block.Instructions[instructionIndexInBlock];
- Debug.Assert(inst.Operands.Length == 1);
- SsaVariable operand = inst.Operands[0];
- if (operand.IsSingleAssignment && operand.Usage.Count == 1 && IsLoadAddress(operand.Definition)) {
- // replace instruction with special "InitObj" instruction
- block.Instructions[instructionIndexInBlock] = new SsaInstruction(
- inst.ParentBlock, null, GetVariableFromLoadAddressInstruction(operand.Definition.Instruction), null,
- specialOpCode: SpecialOpCode.InitObj,
- typeOperand: (TypeReference)inst.Instruction.Operand);
-
- couldSimplifySomething = true;
-
- // remove the loadAddressInstruction later
- redundantLoadAddressInstructions.Add(operand.Definition);
- }
- }
-
- void MakeLoadFieldCallSimple(SsaBlock block, ref int instructionIndexInBlock)
- {
- SsaInstruction inst = block.Instructions[instructionIndexInBlock];
- Debug.Assert(inst.Operands.Length == 1);
- SsaVariable operand = inst.Operands[0];
- if (operand.IsSingleAssignment && operand.Usage.Count == 1 && IsLoadAddress(operand.Definition)) {
- // insert special "PrepareForFieldAccess" instruction in front
- block.Instructions.Insert(instructionIndexInBlock++, new SsaInstruction(
- inst.ParentBlock, null, operand,
- new SsaVariable[] { GetVariableFromLoadAddressInstruction(operand.Definition.Instruction) },
- specialOpCode: SpecialOpCode.PrepareForFieldAccess));
-
- couldSimplifySomething = true;
-
- // remove the loadAddressInstruction later
- redundantLoadAddressInstructions.Add(operand.Definition);
- }
- }
-
- void RemoveRedundantInstructions()
- {
- foreach (SsaInstruction inst in redundantLoadAddressInstructions) {
- inst.ParentBlock.Instructions.Remove(inst);
- }
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/SsaBlock.cs b/ICSharpCode.Decompiler/FlowAnalysis/SsaBlock.cs
deleted file mode 100644
index b1767b9b..00000000
--- a/ICSharpCode.Decompiler/FlowAnalysis/SsaBlock.cs
+++ /dev/null
@@ -1,60 +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.IO;
-
-namespace ICSharpCode.Decompiler.FlowAnalysis
-{
- /// <summary>
- /// A block in a control flow graph; with instructions represented by "SsaInstructions" (instructions use variables, no evaluation stack).
- /// Usually these variables are in SSA form to make analysis easier.
- /// </summary>
- public sealed class SsaBlock
- {
- public readonly List<SsaBlock> Successors = new List<SsaBlock>();
- public readonly List<SsaBlock> Predecessors = new List<SsaBlock>();
- public readonly ControlFlowNodeType NodeType;
- public readonly List<SsaInstruction> Instructions = new List<SsaInstruction>();
-
- /// <summary>
- /// The block index in the control flow graph.
- /// This correspons to the node index in ControlFlowGraph.Nodes, so it can be used to retrieve the original CFG node and look
- /// up additional information (e.g. dominance).
- /// </summary>
- public readonly int BlockIndex;
-
- internal SsaBlock(ControlFlowNode node)
- {
- NodeType = node.NodeType;
- BlockIndex = node.BlockIndex;
- }
-
- public override string ToString()
- {
- StringWriter writer = new StringWriter();
- writer.Write("Block #{0} ({1})", BlockIndex, NodeType);
- foreach (SsaInstruction inst in Instructions) {
- writer.WriteLine();
- inst.WriteTo(writer);
- }
- return writer.ToString();
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/SsaForm.cs b/ICSharpCode.Decompiler/FlowAnalysis/SsaForm.cs
deleted file mode 100644
index baf520eb..00000000
--- a/ICSharpCode.Decompiler/FlowAnalysis/SsaForm.cs
+++ /dev/null
@@ -1,162 +0,0 @@
-// Copyright (c) 2010 Daniel Grunwald
-//
-// 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.Collections.ObjectModel;
-using System.Diagnostics;
-using System.Linq;
-
-using ICSharpCode.NRefactory.Utils;
-using Mono.Cecil;
-using Mono.Cecil.Cil;
-
-namespace ICSharpCode.Decompiler.FlowAnalysis
-{
- /// <summary>
- /// Represents a graph of SsaBlocks.
- /// </summary>
- public sealed class SsaForm
- {
- readonly SsaVariable[] parameters;
- readonly SsaVariable[] locals;
- public readonly ReadOnlyCollection<SsaVariable> OriginalVariables;
- public readonly ReadOnlyCollection<SsaBlock> Blocks;
- readonly bool methodHasThis;
-
- public SsaBlock EntryPoint {
- get { return Blocks[0]; }
- }
-
- public SsaBlock RegularExit {
- get { return Blocks[1]; }
- }
-
- public SsaBlock ExceptionalExit {
- get { return Blocks[2]; }
- }
-
- internal SsaForm(SsaBlock[] blocks, SsaVariable[] parameters, SsaVariable[] locals, SsaVariable[] stackLocations, bool methodHasThis)
- {
- this.parameters = parameters;
- this.locals = locals;
- Blocks = new ReadOnlyCollection<SsaBlock>(blocks);
- OriginalVariables = new ReadOnlyCollection<SsaVariable>(parameters.Concat(locals).Concat(stackLocations).ToList());
- this.methodHasThis = methodHasThis;
-
- Debug.Assert(EntryPoint.NodeType == ControlFlowNodeType.EntryPoint);
- Debug.Assert(RegularExit.NodeType == ControlFlowNodeType.RegularExit);
- Debug.Assert(ExceptionalExit.NodeType == ControlFlowNodeType.ExceptionalExit);
- for (int i = 0; i < OriginalVariables.Count; i++) {
- OriginalVariables[i].OriginalVariableIndex = i;
- }
- }
-
- public GraphVizGraph ExportBlockGraph(Func<SsaBlock, string> labelProvider = null)
- {
- if (labelProvider == null)
- labelProvider = b => b.ToString();
- GraphVizGraph graph = new GraphVizGraph();
- foreach (SsaBlock block in Blocks) {
- graph.AddNode(new GraphVizNode(block.BlockIndex) { label = labelProvider(block), shape = "box" });
- }
- foreach (SsaBlock block in Blocks) {
- foreach (SsaBlock s in block.Successors) {
- graph.AddEdge(new GraphVizEdge(block.BlockIndex, s.BlockIndex));
- }
- }
- return graph;
- }
-
- public GraphVizGraph ExportVariableGraph(Func<SsaVariable, string> labelProvider = null)
- {
- if (labelProvider == null)
- labelProvider = v => v.ToString();
- GraphVizGraph graph = new GraphVizGraph();
- foreach (SsaVariable v in AllVariables) {
- graph.AddNode(new GraphVizNode(v.Name) { label = labelProvider(v) });
- }
- int instructionIndex = 0;
- foreach (SsaBlock block in Blocks) {
- foreach (SsaInstruction inst in block.Instructions) {
- if (inst.Operands.Length == 0 && inst.Target == null)
- continue;
- string id = "instruction" + (++instructionIndex);
- graph.AddNode(new GraphVizNode(id) { label = inst.ToString(), shape = "box" });
- foreach (SsaVariable op in inst.Operands)
- graph.AddEdge(new GraphVizEdge(op.Name, id));
- if (inst.Target != null)
- graph.AddEdge(new GraphVizEdge(id, inst.Target.Name));
- }
- }
- return graph;
- }
-
- public SsaVariable GetOriginalVariable(ParameterReference parameter)
- {
- if (methodHasThis)
- return parameters[parameter.Index + 1];
- else
- return parameters[parameter.Index];
- }
-
- public SsaVariable GetOriginalVariable(VariableReference variable)
- {
- return locals[variable.Index];
- }
-
- #region ComputeVariableUsage
- public void ComputeVariableUsage()
- {
- // clear data from previous runs
- foreach (SsaBlock block in Blocks) {
- foreach (SsaInstruction inst in block.Instructions) {
- foreach (SsaVariable v in inst.Operands) {
- if (v.Usage != null)
- v.Usage.Clear();
- }
- if (inst.Target != null && inst.Target.Usage != null)
- inst.Target.Usage.Clear();
- }
- }
- foreach (SsaBlock block in Blocks) {
- foreach (SsaInstruction inst in block.Instructions) {
- foreach (SsaVariable v in inst.Operands) {
- if (v.Usage == null)
- v.Usage = new List<SsaInstruction>();
- v.Usage.Add(inst);
- }
- if (inst.Target != null && inst.Target.Usage == null)
- inst.Target.Usage = new List<SsaInstruction>();
- }
- }
- }
- #endregion
-
- public IEnumerable<SsaVariable> AllVariables {
- get {
- return (
- from block in Blocks
- from instruction in block.Instructions
- where instruction.Target != null
- select instruction.Target
- ).Distinct();
- }
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/SsaFormBuilder.cs b/ICSharpCode.Decompiler/FlowAnalysis/SsaFormBuilder.cs
deleted file mode 100644
index c7c86a57..00000000
--- a/ICSharpCode.Decompiler/FlowAnalysis/SsaFormBuilder.cs
+++ /dev/null
@@ -1,257 +0,0 @@
-// Copyright (c) 2010 Daniel Grunwald
-//
-// 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 Mono.Cecil;
-using Mono.Cecil.Cil;
-
-namespace ICSharpCode.Decompiler.FlowAnalysis
-{
- /// <summary>
- /// Constructs "SsaForm" graph for a CFG.
- /// This class transforms the method from stack-based IL to a register-based IL language.
- /// Then it calls into TransformToSsa to convert the resulting graph to static single assignment form.
- /// </summary>
- public sealed class SsaFormBuilder
- {
- public static SsaForm Build(MethodDefinition method)
- {
- if (method == null)
- throw new ArgumentNullException("method");
- var cfg = ControlFlowGraphBuilder.Build(method.Body);
- cfg.ComputeDominance();
- cfg.ComputeDominanceFrontier();
- var ssa = BuildRegisterIL(method, cfg);
- TransformToSsa.Transform(cfg, ssa);
- return ssa;
- }
-
- public static SsaForm BuildRegisterIL(MethodDefinition method, ControlFlowGraph cfg)
- {
- if (method == null)
- throw new ArgumentNullException("method");
- if (cfg == null)
- throw new ArgumentNullException("cfg");
- return new SsaFormBuilder(method, cfg).Build();
- }
-
- readonly MethodDefinition method;
- readonly ControlFlowGraph cfg;
-
- readonly SsaBlock[] blocks; // array index = block index
- readonly int[] stackSizeAtBlockStart; // array index = block index
-
- readonly SsaVariable[] parameters; // array index = parameter number
- readonly SsaVariable[] locals; // array index = local number
- readonly SsaVariable[] stackLocations; // array index = position on the IL evaluation stack
- SsaForm ssaForm;
-
- SsaFormBuilder(MethodDefinition method, ControlFlowGraph cfg)
- {
- this.method = method;
- this.cfg = cfg;
-
- blocks = new SsaBlock[cfg.Nodes.Count];
- stackSizeAtBlockStart = new int[cfg.Nodes.Count];
- for (int i = 0; i < stackSizeAtBlockStart.Length; i++) {
- stackSizeAtBlockStart[i] = -1;
- }
- stackSizeAtBlockStart[cfg.EntryPoint.BlockIndex] = 0;
-
- parameters = new SsaVariable[method.Parameters.Count + (method.HasThis ? 1 : 0)];
- if (method.HasThis)
- parameters[0] = new SsaVariable(method.Body.ThisParameter);
- for (int i = 0; i < method.Parameters.Count; i++)
- parameters[i + (method.HasThis ? 1 : 0)] = new SsaVariable(method.Parameters[i]);
-
- locals = new SsaVariable[method.Body.Variables.Count];
- for (int i = 0; i < locals.Length; i++)
- locals[i] = new SsaVariable(method.Body.Variables[i]);
-
- stackLocations = new SsaVariable[method.Body.MaxStackSize];
- for (int i = 0; i < stackLocations.Length; i++) {
- stackLocations[i] = new SsaVariable(i);
- }
- }
-
- internal SsaForm Build()
- {
- CreateGraphStructure();
- ssaForm = new SsaForm(blocks, parameters, locals, stackLocations, method.HasThis);
- CreateInstructions(cfg.EntryPoint.BlockIndex);
- CreateSpecialInstructions();
- return ssaForm;
- }
-
- void CreateGraphStructure()
- {
- for (int i = 0; i < blocks.Length; i++) {
- blocks[i] = new SsaBlock(cfg.Nodes[i]);
- }
- for (int i = 0; i < blocks.Length; i++) {
- foreach (ControlFlowNode node in cfg.Nodes[i].Successors) {
- blocks[i].Successors.Add(blocks[node.BlockIndex]);
- blocks[node.BlockIndex].Predecessors.Add(blocks[i]);
- }
- }
- }
-
- void CreateInstructions(int blockIndex)
- {
- ControlFlowNode cfgNode = cfg.Nodes[blockIndex];
- SsaBlock block = blocks[blockIndex];
-
- int stackSize = stackSizeAtBlockStart[blockIndex];
- Debug.Assert(stackSize >= 0);
-
- List<Instruction> prefixes = new List<Instruction>();
- foreach (Instruction inst in cfgNode.Instructions) {
- if (inst.OpCode.OpCodeType == OpCodeType.Prefix) {
- prefixes.Add(inst);
- continue;
- }
-
- int popCount = inst.GetPopDelta(method) ?? stackSize;
- stackSize -= popCount;
- if (stackSize < 0)
- throw new InvalidProgramException("IL stack underflow");
-
- int pushCount = inst.GetPushDelta();
- if (stackSize + pushCount > stackLocations.Length)
- throw new InvalidProgramException("IL stack overflow");
-
- SsaVariable target;
- SsaVariable[] operands;
- DetermineOperands(stackSize, inst, popCount, pushCount, out target, out operands);
-
- Instruction[] prefixArray = prefixes.Count > 0 ? prefixes.ToArray() : null;
- prefixes.Clear();
-
- // ignore NOP instructions
- if (!(inst.OpCode == OpCodes.Nop || inst.OpCode == OpCodes.Pop)) {
- block.Instructions.Add(new SsaInstruction(block, inst, target, operands, prefixArray));
- }
- stackSize += pushCount;
- }
-
- foreach (ControlFlowEdge edge in cfgNode.Outgoing) {
- int newStackSize;
- switch (edge.Type) {
- case JumpType.Normal:
- newStackSize = stackSize;
- break;
- case JumpType.EndFinally:
- if (stackSize != 0)
- throw new NotSupportedException("stacksize must be 0 in endfinally edge");
- newStackSize = 0;
- break;
- case JumpType.JumpToExceptionHandler:
- switch (edge.Target.NodeType) {
- case ControlFlowNodeType.FinallyOrFaultHandler:
- newStackSize = 0;
- break;
- case ControlFlowNodeType.ExceptionalExit:
- case ControlFlowNodeType.CatchHandler:
- newStackSize = 1;
- break;
- default:
- throw new NotSupportedException("unsupported target node type: " + edge.Target.NodeType);
- }
- break;
- default:
- throw new NotSupportedException("unsupported jump type: " + edge.Type);
- }
-
- int nextStackSize = stackSizeAtBlockStart[edge.Target.BlockIndex];
- if (nextStackSize == -1) {
- stackSizeAtBlockStart[edge.Target.BlockIndex] = newStackSize;
- CreateInstructions(edge.Target.BlockIndex);
- } else if (nextStackSize != newStackSize) {
- throw new InvalidProgramException("Stack size doesn't match");
- }
- }
- }
-
- void DetermineOperands(int stackSize, Instruction inst, int popCount, int pushCount, out SsaVariable target, out SsaVariable[] operands)
- {
- switch (inst.OpCode.Code) {
- case Code.Ldarg:
- operands = new SsaVariable[] { ssaForm.GetOriginalVariable((ParameterReference)inst.Operand) };
- target = stackLocations[stackSize];
- break;
- case Code.Starg:
- operands = new SsaVariable[] { stackLocations[stackSize] };
- target = ssaForm.GetOriginalVariable((ParameterReference)inst.Operand);
- break;
- case Code.Ldloc:
- operands = new SsaVariable[] { ssaForm.GetOriginalVariable((VariableReference)inst.Operand) };
- target = stackLocations[stackSize];
- break;
- case Code.Stloc:
- operands = new SsaVariable[] { stackLocations[stackSize] };
- target = ssaForm.GetOriginalVariable((VariableReference)inst.Operand);
- break;
- case Code.Dup:
- operands = new SsaVariable[] { stackLocations[stackSize] };
- target = stackLocations[stackSize + 1];
- break;
- default:
- operands = new SsaVariable[popCount];
- for (int i = 0; i < popCount; i++) {
- operands[i] = stackLocations[stackSize + i];
- }
-
- switch (pushCount) {
- case 0:
- target = null;
- break;
- case 1:
- target = stackLocations[stackSize];
- break;
- default:
- throw new NotSupportedException("unsupported pushCount=" + pushCount);
- }
- break;
- }
- }
-
- void CreateSpecialInstructions()
- {
- // Everything needs an initial write for the SSA transformation to work correctly.
- foreach (SsaVariable v in parameters) {
- ssaForm.EntryPoint.Instructions.Add(new SsaInstruction(ssaForm.EntryPoint, null, v, null, specialOpCode: SpecialOpCode.Parameter));
- }
- foreach (SsaVariable v in locals) {
- ssaForm.EntryPoint.Instructions.Add(new SsaInstruction(ssaForm.EntryPoint, null, v, null, specialOpCode: SpecialOpCode.Uninitialized));
- }
- foreach (SsaVariable v in stackLocations) {
- ssaForm.EntryPoint.Instructions.Add(new SsaInstruction(ssaForm.EntryPoint, null, v, null, specialOpCode: SpecialOpCode.Uninitialized));
- }
- foreach (SsaBlock b in blocks) {
- if (b.NodeType == ControlFlowNodeType.CatchHandler) {
- b.Instructions.Add(new SsaInstruction(b, null, stackLocations[0], null,
- specialOpCode: SpecialOpCode.Exception,
- typeOperand: cfg.Nodes[b.BlockIndex].ExceptionHandler.CatchType));
- }
- }
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/SsaInstruction.cs b/ICSharpCode.Decompiler/FlowAnalysis/SsaInstruction.cs
deleted file mode 100644
index c9375852..00000000
--- a/ICSharpCode.Decompiler/FlowAnalysis/SsaInstruction.cs
+++ /dev/null
@@ -1,191 +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.Diagnostics;
-using System.IO;
-
-using ICSharpCode.Decompiler.Disassembler;
-using Mono.Cecil;
-using Mono.Cecil.Cil;
-
-namespace ICSharpCode.Decompiler.FlowAnalysis
-{
- public enum SpecialOpCode
- {
- /// <summary>
- /// No special op code: SsaInstruction has a normal IL instruction
- /// </summary>
- None,
- /// <summary>
- /// Φ function: chooses the appropriate variable based on which CFG edge was used to enter this block
- /// </summary>
- Phi,
- /// <summary>
- /// Variable is read from before passing it by ref.
- /// This instruction constructs a managed reference to the variable.
- /// </summary>
- PrepareByRefCall,
- /// <summary>
- /// This instruction constructs a managed reference to the variable.
- /// The variable is not really read from.
- /// </summary>
- PrepareByOutCall,
- /// <summary>
- /// This instruction constructs a managed reference to the variable.
- /// The reference is used for a field access on a value type.
- /// </summary>
- PrepareForFieldAccess,
- /// <summary>
- /// Variable is written to after passing it by ref or out.
- /// </summary>
- WriteAfterByRefOrOutCall,
- /// <summary>
- /// Variable is not initialized.
- /// </summary>
- Uninitialized,
- /// <summary>
- /// Value is passed in as parameter
- /// </summary>
- Parameter,
- /// <summary>
- /// Value is a caught exception.
- /// TypeOperand is set to the exception type.
- /// </summary>
- Exception,
- /// <summary>
- /// Initialize a value type. Unlike the real initobj instruction, this one does not take an address
- /// but assigns to the target variable.
- /// TypeOperand is set to the type being created.
- /// </summary>
- InitObj
- }
-
- public sealed class SsaInstruction
- {
- public readonly SsaBlock ParentBlock;
- public readonly SpecialOpCode SpecialOpCode;
-
- /// <summary>
- /// The original IL instruction.
- /// May be null for "invented" instructions (SpecialOpCode != None).
- /// </summary>
- public readonly Instruction Instruction;
-
- /// <summary>
- /// Prefixes in front of the IL instruction.
- /// </summary>
- public readonly Instruction[] Prefixes;
-
- /// <summary>
- /// Gets the type operand. This is used only in combination with some special opcodes.
- /// </summary>
- public readonly TypeReference TypeOperand;
-
- public SsaVariable Target;
- public SsaVariable[] Operands;
-
- static readonly SsaVariable[] emptyVariableArray = {};
- static readonly Instruction[] emptyInstructionArray = {};
-
- public SsaInstruction(SsaBlock parentBlock, Instruction instruction, SsaVariable target, SsaVariable[] operands,
- Instruction[] prefixes = null, SpecialOpCode specialOpCode = SpecialOpCode.None,
- TypeReference typeOperand = null)
- {
- ParentBlock = parentBlock;
- Instruction = instruction;
- Prefixes = prefixes ?? emptyInstructionArray;
- Target = target;
- Operands = operands ?? emptyVariableArray;
- SpecialOpCode = specialOpCode;
- TypeOperand = typeOperand;
- Debug.Assert((typeOperand != null) == (specialOpCode == SpecialOpCode.Exception || specialOpCode == SpecialOpCode.InitObj));
- }
-
- /// <summary>
- /// Gets whether this instruction is a simple assignment from one variable to another.
- /// </summary>
- public bool IsMoveInstruction {
- get {
- return Target != null && Operands.Length == 1 && Instruction != null && OpCodeInfo.Get(Instruction.OpCode).IsMoveInstruction;
- }
- }
-
- public void ReplaceVariableInOperands(SsaVariable oldVar, SsaVariable newVar)
- {
- for (int i = 0; i < Operands.Length; i++) {
- if (Operands[i] == oldVar)
- Operands[i] = newVar;
- }
- }
-
- public override string ToString()
- {
- StringWriter w = new StringWriter();
- WriteTo(w);
- return w.ToString();
- }
-
- public void WriteTo(TextWriter writer)
- {
- foreach (Instruction prefix in Prefixes) {
- DisassemblerHelpers.WriteTo(prefix, new PlainTextOutput(writer));
- writer.WriteLine();
- }
- if (Instruction != null && Instruction.Offset >= 0) {
- writer.Write(CecilExtensions.OffsetToString(Instruction.Offset));
- writer.Write(": ");
- }
- if (Target != null) {
- writer.Write(Target.ToString());
- writer.Write(" = ");
- }
- if (IsMoveInstruction) {
- writer.Write(Operands[0].ToString());
- if (Instruction != null) {
- writer.Write(" (" + Instruction.OpCode.Name + ")");
- }
- } else {
- if (Instruction == null) {
- writer.Write(SpecialOpCode.ToString());
- } else {
- writer.Write(Instruction.OpCode.Name);
- if(null != Instruction.Operand) {
- writer.Write(' ');
- DisassemblerHelpers.WriteOperand(new PlainTextOutput(writer), Instruction.Operand);
- writer.Write(' ');
- }
- }
- if (TypeOperand != null) {
- writer.Write(' ');
- writer.Write(TypeOperand.ToString());
- writer.Write(' ');
- }
- if (Operands.Length > 0) {
- writer.Write('(');
- for (int i = 0; i < Operands.Length; i++) {
- if (i > 0)
- writer.Write(", ");
- writer.Write(Operands[i].ToString());
- }
- writer.Write(')');
- }
- }
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/SsaOptimization.cs b/ICSharpCode.Decompiler/FlowAnalysis/SsaOptimization.cs
deleted file mode 100644
index 71696992..00000000
--- a/ICSharpCode.Decompiler/FlowAnalysis/SsaOptimization.cs
+++ /dev/null
@@ -1,138 +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.Diagnostics;
-
-using Mono.Cecil.Cil;
-
-namespace ICSharpCode.Decompiler.FlowAnalysis
-{
- /// <summary>
- /// Contains some very simple optimizations that work on the SSA form.
- /// </summary>
- internal static class SsaOptimization
- {
- public static void Optimize(SsaForm ssaForm)
- {
- DirectlyStoreToVariables(ssaForm);
- SimpleCopyPropagation(ssaForm);
- RemoveDeadAssignments(ssaForm);
- }
-
- /// <summary>
- /// When any instructions stores its result in a stack location that's used only once in a 'stloc' or 'starg' instruction,
- /// we optimize this to directly store in the target location.
- /// As optimization this is redundant (does the same as copy propagation), but it'll make us keep the variables named
- /// after locals instead of keeping the temps as using only the simple copy propagation would do.
- /// </summary>
- public static void DirectlyStoreToVariables(SsaForm ssaForm)
- {
- foreach (SsaBlock block in ssaForm.Blocks) {
- block.Instructions.RemoveAll(
- inst => {
- if (inst.Instruction != null && (inst.Instruction.OpCode == OpCodes.Stloc || inst.Instruction.OpCode == OpCodes.Starg)) {
- SsaVariable target = inst.Target;
- SsaVariable temp = inst.Operands[0];
- if (target.IsSingleAssignment && temp.IsSingleAssignment && temp.Usage.Count == 1 && temp.IsStackLocation) {
- temp.Definition.Target = target;
- return true;
- }
- }
- return false;
- });
- }
- ssaForm.ComputeVariableUsage(); // update usage after we modified stuff
- }
-
- public static void SimpleCopyPropagation(SsaForm ssaForm, bool onlyForStackLocations = true)
- {
- foreach (SsaBlock block in ssaForm.Blocks) {
- foreach (SsaInstruction inst in block.Instructions) {
- if (inst.IsMoveInstruction && inst.Target.IsSingleAssignment && inst.Operands[0].IsSingleAssignment) {
- if (inst.Target.IsStackLocation || !onlyForStackLocations) {
- // replace all uses of 'target' with 'operands[0]'.
- foreach (SsaInstruction useInstruction in inst.Target.Usage) {
- useInstruction.ReplaceVariableInOperands(inst.Target, inst.Operands[0]);
- }
- }
- }
- }
- }
- ssaForm.ComputeVariableUsage(); // update usage after we modified stuff
- }
-
- public static void RemoveDeadAssignments(SsaForm ssaForm)
- {
- HashSet<SsaVariable> liveVariables = new HashSet<SsaVariable>();
- // find variables that are used directly
- foreach (SsaBlock block in ssaForm.Blocks) {
- foreach (SsaInstruction inst in block.Instructions) {
- if (!CanRemoveAsDeadCode(inst)) {
- if (inst.Target != null)
- liveVariables.Add(inst.Target);
- foreach (SsaVariable op in inst.Operands) {
- liveVariables.Add(op);
- }
- }
- }
- }
- Queue<SsaVariable> queue = new Queue<SsaVariable>(liveVariables);
- // find variables that are used indirectly
- while (queue.Count > 0) {
- SsaVariable v = queue.Dequeue();
- if (v.IsSingleAssignment) {
- foreach (SsaVariable op in v.Definition.Operands) {
- if (liveVariables.Add(op))
- queue.Enqueue(op);
- }
- }
- }
- // remove assignments to all unused variables
- foreach (SsaBlock block in ssaForm.Blocks) {
- block.Instructions.RemoveAll(
- inst => {
- if (inst.Target != null && !liveVariables.Contains(inst.Target)) {
- Debug.Assert(inst.Target.IsSingleAssignment);
- return true;
- }
- return false;
- });
- }
- ssaForm.ComputeVariableUsage(); // update usage after we modified stuff
- }
-
- static bool CanRemoveAsDeadCode(SsaInstruction inst)
- {
- if (inst.Target != null && !inst.Target.IsSingleAssignment)
- return false;
- switch (inst.SpecialOpCode) {
- case SpecialOpCode.Phi:
- case SpecialOpCode.Exception:
- case SpecialOpCode.Parameter:
- case SpecialOpCode.Uninitialized:
- return true;
- case SpecialOpCode.None:
- return inst.IsMoveInstruction;
- default:
- return false;
- }
- }
- }
-}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/SsaVariable.cs b/ICSharpCode.Decompiler/FlowAnalysis/SsaVariable.cs
deleted file mode 100644
index 902b7002..00000000
--- a/ICSharpCode.Decompiler/FlowAnalysis/SsaVariable.cs
+++ /dev/null
@@ -1,91 +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 Mono.Cecil;
-using Mono.Cecil.Cil;
-
-namespace ICSharpCode.Decompiler.FlowAnalysis
-{
- /// <summary>
- /// Represents a variable used with the SsaInstruction register-based instructions.
- /// Despite what the name suggests, the variable is not necessarily in single-assignment form - take a look at "bool IsSingleAssignment".
- /// </summary>
- public sealed class SsaVariable
- {
- public int OriginalVariableIndex;
- public readonly string Name;
- public readonly bool IsStackLocation;
-
- public readonly ParameterDefinition Parameter;
- public readonly VariableDefinition Variable;
-
- public SsaVariable(ParameterDefinition p)
- {
- Name = string.IsNullOrEmpty(p.Name) ? "param" + p.Index : p.Name;
- Parameter = p;
- }
-
- public SsaVariable(VariableDefinition v)
- {
- Name = string.IsNullOrEmpty(v.Name) ? "V_" + v.Index : v.Name;
- Variable = v;
- }
-
- public SsaVariable(int stackLocation)
- {
- Name = "stack" + stackLocation;
- IsStackLocation = true;
- }
-
- public SsaVariable(SsaVariable original, string newName)
- {
- Name = newName;
- IsStackLocation = original.IsStackLocation;
- OriginalVariableIndex = original.OriginalVariableIndex;
- Parameter = original.Parameter;
- Variable = original.Variable;
- }
-
- public override string ToString()
- {
- return Name;
- }
-
- /// <summary>
- /// Gets whether this variable has only a single assignment.
- /// This field is initialized in TransformToSsa step.
- /// </summary>
- /// <remarks>Not all variables can be transformed to single assignment form: variables that have their address taken
- /// cannot be represented in SSA (although SimplifyByRefCalls will get rid of the address-taking instruction in almost all cases)</remarks>
- public bool IsSingleAssignment;
-
- /// <summary>
- /// Gets the instruction defining the variable.
- /// This field is initialized in TransformToSsa step. It is only set for variables with a single assignment.
- /// </summary>
- public SsaInstruction Definition;
-
- /// <summary>
- /// Gets the places where a variable is used.
- /// If a single instruction reads a variable 2 times (e.g. adding to itself), then it must be included 2 times in this list!
- /// </summary>
- public List<SsaInstruction> Usage;
- }
-}
diff --git a/ICSharpCode.Decompiler/FlowAnalysis/TransformToSsa.cs b/ICSharpCode.Decompiler/FlowAnalysis/TransformToSsa.cs
deleted file mode 100644
index 47ff7bff..00000000
--- a/ICSharpCode.Decompiler/FlowAnalysis/TransformToSsa.cs
+++ /dev/null
@@ -1,254 +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.Collections.ObjectModel;
-using System.Diagnostics;
-using System.Linq;
-
-using Mono.Cecil;
-using Mono.Cecil.Cil;
-
-namespace ICSharpCode.Decompiler.FlowAnalysis
-{
- /// <summary>
- /// Convers a method to static single assignment form.
- /// </summary>
- internal sealed class TransformToSsa
- {
- public static void Transform(ControlFlowGraph cfg, SsaForm ssa, bool optimize = true)
- {
- TransformToSsa transform = new TransformToSsa(cfg, ssa);
- transform.ConvertVariablesToSsa();
- SsaOptimization.RemoveDeadAssignments(ssa); // required so that 'MakeByRefCallsSimple' can detect more cases
- if (SimplifyByRefCalls.MakeByRefCallsSimple(ssa)) {
- transform.ConvertVariablesToSsa();
- }
- if (optimize)
- SsaOptimization.Optimize(ssa);
- }
-
- readonly ControlFlowGraph cfg;
- readonly SsaForm ssaForm;
- readonly List<SsaInstruction>[] writeToOriginalVariables; // array index -> SsaVariable OriginalVariableIndex
- readonly bool[] addressTaken; // array index -> SsaVariable OriginalVariableIndex; value = whether ldloca instruction was used with variable
-
- TransformToSsa(ControlFlowGraph cfg, SsaForm ssaForm)
- {
- this.cfg = cfg;
- this.ssaForm = ssaForm;
- writeToOriginalVariables = new List<SsaInstruction>[ssaForm.OriginalVariables.Count];
- addressTaken = new bool[ssaForm.OriginalVariables.Count];
- }
-
- #region CollectInformationAboutOriginalVariableUse
- void CollectInformationAboutOriginalVariableUse()
- {
- Debug.Assert(addressTaken.Length == writeToOriginalVariables.Length);
- for (int i = 0; i < writeToOriginalVariables.Length; i++) {
- Debug.Assert(ssaForm.OriginalVariables[i].OriginalVariableIndex == i);
-
- addressTaken[i] = false;
- // writeToOriginalVariables is only used when placing phi functions
- // we don't need to do that anymore for variables that are already in SSA form
- if (ssaForm.OriginalVariables[i].IsSingleAssignment)
- writeToOriginalVariables[i] = null;
- else
- writeToOriginalVariables[i] = new List<SsaInstruction>();
- }
- foreach (SsaBlock block in ssaForm.Blocks) {
- foreach (SsaInstruction inst in block.Instructions) {
- if (inst.Target != null ) {
- var list = writeToOriginalVariables[inst.Target.OriginalVariableIndex];
- if (list != null)
- list.Add(inst);
- }
- if (inst.Instruction != null) {
- if (inst.Instruction.OpCode == OpCodes.Ldloca) {
- addressTaken[ssaForm.GetOriginalVariable((VariableDefinition)inst.Instruction.Operand).OriginalVariableIndex] = true;
- } else if (inst.Instruction.OpCode == OpCodes.Ldarga) {
- addressTaken[ssaForm.GetOriginalVariable((ParameterDefinition)inst.Instruction.Operand).OriginalVariableIndex] = true;
- }
- }
- }
- }
- }
- #endregion
-
- #region ConvertToSsa
- void ConvertVariablesToSsa()
- {
- CollectInformationAboutOriginalVariableUse();
- bool[] processVariable = new bool[ssaForm.OriginalVariables.Count];
- foreach (SsaVariable variable in ssaForm.OriginalVariables) {
- if (!variable.IsSingleAssignment && !addressTaken[variable.OriginalVariableIndex]) {
- PlacePhiFunctions(variable);
- processVariable[variable.OriginalVariableIndex] = true;
- }
- }
- RenameVariables(processVariable);
- foreach (SsaVariable variable in ssaForm.OriginalVariables) {
- if (!addressTaken[variable.OriginalVariableIndex]) {
- Debug.Assert(variable.IsSingleAssignment && variable.Definition != null);
- }
- }
- ssaForm.ComputeVariableUsage();
- }
- #endregion
-
- #region PlacePhiFunctions
- void PlacePhiFunctions(SsaVariable variable)
- {
- cfg.ResetVisited();
- HashSet<SsaBlock> blocksWithPhi = new HashSet<SsaBlock>();
- Queue<ControlFlowNode> worklist = new Queue<ControlFlowNode>();
- foreach (SsaInstruction writeInstruction in writeToOriginalVariables[variable.OriginalVariableIndex]) {
- ControlFlowNode cfgNode = cfg.Nodes[writeInstruction.ParentBlock.BlockIndex];
- if (!cfgNode.Visited) {
- cfgNode.Visited = true;
- worklist.Enqueue(cfgNode);
- }
- }
- while (worklist.Count > 0) {
- ControlFlowNode cfgNode = worklist.Dequeue();
- foreach (ControlFlowNode dfNode in cfgNode.DominanceFrontier) {
- // we don't need phi functions in the exit node
- if (dfNode.NodeType == ControlFlowNodeType.RegularExit || dfNode.NodeType == ControlFlowNodeType.ExceptionalExit)
- continue;
- SsaBlock y = ssaForm.Blocks[dfNode.BlockIndex];
- if (blocksWithPhi.Add(y)) {
- // add a phi instruction in y
- SsaVariable[] operands = Enumerable.Repeat(variable, dfNode.Incoming.Count).ToArray();
- y.Instructions.Insert(0, new SsaInstruction(y, null, variable, operands, specialOpCode: SpecialOpCode.Phi));
- if (!dfNode.Visited) {
- dfNode.Visited = true;
- worklist.Enqueue(dfNode);
- }
- }
- }
- }
- }
- #endregion
-
- #region RenameVariable
- int tempVariableCounter = 1;
-
- void RenameVariables(bool[] processVariable)
- {
- VariableRenamer r = new VariableRenamer(this, processVariable);
- r.Visit(ssaForm.EntryPoint);
- }
-
- sealed class VariableRenamer
- {
- readonly TransformToSsa transform;
- readonly ReadOnlyCollection<SsaVariable> inputVariables;
- internal readonly Stack<SsaVariable>[] versionStacks;
- int[] versionCounters; // specifies for each input variable the next version number
-
- // processVariable = specifies for each input variable whether we should rename it
- public VariableRenamer(TransformToSsa transform, bool[] processVariable)
- {
- this.transform = transform;
- inputVariables = transform.ssaForm.OriginalVariables;
- Debug.Assert(inputVariables.Count == processVariable.Length);
- versionCounters = new int[inputVariables.Count];
- versionStacks = new Stack<SsaVariable>[inputVariables.Count];
- for (int i = 0; i < versionStacks.Length; i++) {
- if (processVariable[i]) {
- Debug.Assert(inputVariables[i].IsSingleAssignment == false);
- // only create version stacks for the variables that we need to process and that weren't already processed earlier
- versionStacks[i] = new Stack<SsaVariable>();
- versionStacks[i].Push(inputVariables[i]);
- }
- }
- }
-
- SsaVariable MakeNewVersion(int variableIndex)
- {
- int versionCounter = ++versionCounters[variableIndex];
- SsaVariable x = inputVariables[variableIndex];
- if (versionCounter == 1) {
- return x;
- } else {
- if (x.IsStackLocation) {
- return new SsaVariable(x, "temp" + (transform.tempVariableCounter++));
- } else {
- return new SsaVariable(x, x.Name + "_" + versionCounter);
- }
- }
- }
-
- internal void Visit(SsaBlock block)
- {
- // duplicate top of all stacks
- foreach (var stack in versionStacks) {
- if (stack != null)
- stack.Push(stack.Peek());
- }
-
- foreach (SsaInstruction s in block.Instructions) {
- // replace all uses of variables being processed with their current version.
- if (s.SpecialOpCode != SpecialOpCode.Phi) {
- for (int i = 0; i < s.Operands.Length; i++) {
- var stack = versionStacks[s.Operands[i].OriginalVariableIndex]