├── $packages
├── AshMind.Extensions.1.0.4
│ ├── AshMind.Extensions.1.0.4.nupkg
│ └── lib
│ │ └── 3.5
│ │ ├── AshMind.Extensions.dll
│ │ └── AshMind.Extensions.xml
└── repositories.config
├── $tools
└── NuGet.exe
├── .gitignore
├── Expressive.Tests
├── ExpectedExpressionAttribute.cs
├── Expressive.Tests.csproj
├── GeneralTests.cs
├── Helpers
│ ├── Assembler.cs
│ ├── Method.cs
│ ├── Property.cs
│ └── ToStringVisitor.cs
├── InlinerTest.cs
├── Massive
│ ├── InstructionCollectionVisitor.cs
│ └── InstructionSupportTest.cs
├── Methods
│ ├── TestDisassembler.cs
│ ├── TestMethod.cs
│ ├── TestMethodBuilder.cs
│ └── TestMethodParameter.cs
├── Properties
│ └── AssemblyInfo.cs
├── TestClasses
│ ├── Booleans.cs
│ ├── ClassWithNames.cs
│ ├── Constants.cs
│ ├── Conversions.cs
│ ├── Initializers.cs
│ ├── Lambdas.cs
│ ├── Nulls.cs
│ ├── Numerics.cs
│ └── Range.cs
└── packages.config
├── Expressive.sln
├── Expressive
├── Abstraction
│ ├── IManagedContext.cs
│ ├── IManagedMethod.cs
│ ├── IManagedMethodParameter.cs
│ ├── MethodBaseAdapter.cs
│ ├── MethodBaseModuleContext.cs
│ └── ParameterInfoAdapter.cs
├── Decompilation
│ ├── BooleanSupport.cs
│ ├── DecompilationContext.cs
│ ├── IDecompilationStep.cs
│ ├── Pipelines
│ │ ├── DecompilationPipeline.cs
│ │ ├── DefaultPipeline.cs
│ │ └── IDecompilationPipeline.cs
│ └── Steps
│ │ ├── AddressOfToCreateDelegateVisitor.cs
│ │ ├── BooleanEqualityImprovementVisitor.cs
│ │ ├── BranchProcessing.cs
│ │ ├── BranchResolutionStep.cs
│ │ ├── BranchStackFrame.cs
│ │ ├── BranchingAwareStepBase.cs
│ │ ├── Clarity
│ │ ├── CoalescingVisitor.cs
│ │ ├── ConditionImprovementVisitor.cs
│ │ ├── NewNullableToCastVisitor.cs
│ │ └── NotImprovementVisitor.cs
│ │ ├── ContextualVisitor.cs
│ │ ├── IndividualDecompilationContext.cs
│ │ ├── IndividualDecompilationStep.cs
│ │ ├── IndividualElements
│ │ ├── BranchToCondition.cs
│ │ ├── CallToExpression.cs
│ │ ├── ConvToConvert.cs
│ │ ├── CxxToCondition.cs
│ │ ├── DupToCopy.cs
│ │ ├── ElementInterpretation.cs
│ │ ├── IElementInterpretation.cs
│ │ ├── InstructionToExpression.cs
│ │ ├── LdargToParameter.cs
│ │ ├── LdcToConstant.cs
│ │ ├── LdfldToField.cs
│ │ ├── LdftnToAddressOf.cs
│ │ ├── LdlocToVariable.cs
│ │ ├── LdnullToConstant.cs
│ │ ├── LdstrToConstant.cs
│ │ ├── MathToExpression.cs
│ │ ├── NewarrToNewArray.cs
│ │ ├── NewobjToNew.cs
│ │ ├── OtherToCondition.cs
│ │ ├── PopToRemove.cs
│ │ ├── RetToReturn.cs
│ │ ├── StelemToAssignment.cs
│ │ ├── StfldToAssignment.cs
│ │ └── StlocToAssignment.cs
│ │ ├── NopRemovalStep.cs
│ │ ├── StatementInlining
│ │ ├── AssignmentInlining
│ │ │ ├── AssignmentEstimatingVisitor.cs
│ │ │ ├── AssignmentInliner.cs
│ │ │ └── AssignmentInliningVisitor.cs
│ │ ├── IfAssignmentInliningVisitor.cs
│ │ ├── IfReturnInliningVisitor.cs
│ │ ├── IfThenCollapsingVisitor.cs
│ │ ├── InitializerCollectors
│ │ │ ├── ArrayInitializerCollector.cs
│ │ │ ├── CollectionInitializerCollector.cs
│ │ │ ├── IInitializerCollector.cs
│ │ │ ├── InitializerCollector.cs
│ │ │ └── ObjectInitializerCollector.cs
│ │ ├── InitializerDetectingVisitor.cs
│ │ ├── LambdaInliningVisitor.cs
│ │ └── VariableInliningStep.cs
│ │ ├── UnconditionalBranchesRemovalStep.cs
│ │ └── VisitorSequenceStep.cs
├── DecompilationException.cs
├── Decompiler.cs
├── Disassembler.cs
├── Disassembly
│ ├── IInstructionReader.cs
│ ├── InstructionReader.cs
│ └── Instructions
│ │ ├── BranchInstruction.cs
│ │ ├── FieldReferenceInstruction.cs
│ │ ├── IValueInstruction.cs
│ │ ├── Instruction.cs
│ │ ├── MemberReferenceInstruction.cs
│ │ ├── MethodReferenceInstruction.cs
│ │ ├── SimpleInstruction.cs
│ │ ├── SwitchInstruction.cs
│ │ ├── TypeReferenceInstruction.cs
│ │ ├── UnsupportedInstruction.cs
│ │ ├── ValueInstruction.cs
│ │ └── VariableReferenceInstruction.cs
├── Elements
│ ├── ArrayItemAssignmentElement.cs
│ ├── BranchingElement.cs
│ ├── ElementKind.cs
│ ├── ElementVisitor.cs
│ ├── ExpressionElement.cs
│ ├── Expressions
│ │ ├── AddressOfExpression.cs
│ │ ├── ExpressionTreeVisitor.cs
│ │ └── LocalExpression.cs
│ ├── IElement.cs
│ ├── IPreservingOffset.cs
│ ├── IfThenElement.cs
│ ├── InstructionElement.cs
│ ├── MemberAssignmentElement.cs
│ ├── Presentation
│ │ ├── ElementHelper.cs
│ │ └── Indent.cs
│ ├── ReturnElement.cs
│ └── VariableAssignmentElement.cs
├── Expressive.csproj
├── Expressive.nuspec
├── ExpressiveEngine.cs
├── ExpressiveExtensions.cs
├── External
│ └── ExpressionVisitor.cs
├── IDecompiler.cs
├── IDisassembler.cs
├── IInliner.cs
├── Inliner.cs
├── Inlining
│ └── InliningVisitor.cs
├── Matching
│ ├── Matcher.cs
│ ├── MatcherBinaryExtensions.cs
│ ├── MatcherCollectionExtensions.cs
│ ├── MatcherConstantExtensions.cs
│ ├── MatcherExpressionExtensions.cs
│ ├── MatcherMemberExtensions.cs
│ ├── MatcherMethodCallExtensions.cs
│ ├── MatcherNewExtensions.cs
│ ├── MatcherParameterExtensions.cs
│ └── MatcherUnaryExtensions.cs
├── Properties
│ └── AssemblyInfo.cs
└── packages.config
├── nuget-pack.bat
├── nuget.bat
├── nuget.config
└── readme.md
/$packages/AshMind.Extensions.1.0.4/AshMind.Extensions.1.0.4.nupkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ashmind/expressive/4c33c8db5f6e9a89d559bfc99746cb7b7df47a98/$packages/AshMind.Extensions.1.0.4/AshMind.Extensions.1.0.4.nupkg
--------------------------------------------------------------------------------
/$packages/AshMind.Extensions.1.0.4/lib/3.5/AshMind.Extensions.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ashmind/expressive/4c33c8db5f6e9a89d559bfc99746cb7b7df47a98/$packages/AshMind.Extensions.1.0.4/lib/3.5/AshMind.Extensions.dll
--------------------------------------------------------------------------------
/$packages/repositories.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/$tools/NuGet.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ashmind/expressive/4c33c8db5f6e9a89d559bfc99746cb7b7df47a98/$tools/NuGet.exe
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | bin
2 | Bin
3 | obj
4 | Obj
5 | *.user
6 | *.suo
7 | *.vs10x
8 | _ReSharper.*
9 |
--------------------------------------------------------------------------------
/Expressive.Tests/ExpectedExpressionAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.Linq;
5 |
6 | using AshMind.Extensions;
7 |
8 | namespace Expressive.Tests {
9 | [AttributeUsage(AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Field, AllowMultiple = false)]
10 | public class ExpectedExpressionAttribute : Attribute {
11 | public ExpectedExpressionAttribute(params string[] patterns) {
12 | this.Patterns = patterns.AsReadOnly();
13 | }
14 |
15 | public ReadOnlyCollection Patterns { get; private set; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Expressive.Tests/GeneralTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Linq.Expressions;
5 | using System.Reflection;
6 | using Expressive.Abstraction;
7 | using Expressive.Disassembly;
8 | using Expressive.Tests.Helpers;
9 | using MbUnit.Framework;
10 |
11 | using AshMind.Extensions;
12 |
13 | using Expressive.Decompilation.Pipelines;
14 | using Expressive.Tests.Methods;
15 | using Expressive.Tests.TestClasses;
16 |
17 | namespace Expressive.Tests {
18 | [TestFixture]
19 | public class GeneralTests {
20 | [Test]
21 | [Factory("GetTestMethods")]
22 | public void TestDecompilesTo(IManagedMethod method, IEnumerable patterns) {
23 | var decompiled = Decompile(method);
24 |
25 | var parameterNames = decompiled.Parameters.Select(p => p.Name).ToArray();
26 | var expected = patterns.Select(
27 | p => p.Contains("{0}") ? string.Format(p, parameterNames) : p
28 | ).ToList();
29 |
30 | if (expected.Count <= 1) {
31 | Assert.AreEqual(expected.Single(), ToStringVisitor.ToString(decompiled));
32 | }
33 | else {
34 | Assert.Contains(expected, ToStringVisitor.ToString(decompiled));
35 | }
36 | }
37 |
38 | [Test]
39 | [Factory("GetTestMethods")]
40 | public void TestDecompilationResultHasCorrectParameters(IManagedMethod method) {
41 | var decompiled = Decompile(method);
42 | var parameterTypes = method.GetParameters().Select(p => p.ParameterType).ToList();
43 | if (!method.IsStatic)
44 | parameterTypes.Insert(0, method.DeclaringType);
45 |
46 | Assert.AreElementsSame(parameterTypes, decompiled.Parameters.Select(p => p.Type));
47 | }
48 |
49 | [Test]
50 | [Factory("GetTestMethods")]
51 | public void TestDecompilationResultIsCompilable(IManagedMethod method) {
52 | var decompiled = Decompile(method);
53 | Assert.DoesNotThrow(() => decompiled.Compile());
54 | }
55 |
56 | [Test]
57 | [Ignore("http://connect.microsoft.com/VisualStudio/feedback/details/361546/provide-implementation-for-getmethodbody-in-dynamicmethod")]
58 | public void TestDecompilationOfConversion(
59 | [Column(typeof(int))] Type originalType,
60 | [Column(typeof(int))] Type targetType
61 | ) {
62 | var parameter = Expression.Parameter(originalType, "x");
63 | var lambda = Expression.Lambda(
64 | typeof(Func<,>).MakeGenericType(originalType, targetType),
65 | parameter,
66 | parameter
67 | ).Compile();
68 |
69 | var decompiled = Decompile(new MethodBaseAdapter(lambda.Method));
70 | Assert.AreEqual("x => x", decompiled.ToString());
71 | }
72 |
73 | private static LambdaExpression Decompile(IManagedMethod method) {
74 | return new Decompiler(
75 | new TestDisassembler((bytes, context) => new InstructionReader(bytes, context)),
76 | new DefaultPipeline()
77 | ).Decompile(method);
78 | }
79 |
80 | public IEnumerable