|
|
|
@ -18,6 +18,7 @@
@@ -18,6 +18,7 @@
|
|
|
|
|
|
|
|
|
|
using System; |
|
|
|
|
using System.Collections.Generic; |
|
|
|
|
using System.Diagnostics; |
|
|
|
|
using System.Linq; |
|
|
|
|
using System.Text; |
|
|
|
|
using System.Threading; |
|
|
|
@ -36,8 +37,22 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -36,8 +37,22 @@ namespace ICSharpCode.Decompiler.CSharp
|
|
|
|
|
public class CSharpDecompiler |
|
|
|
|
{ |
|
|
|
|
readonly DecompilerTypeSystem typeSystem; |
|
|
|
|
TypeSystemAstBuilder typeSystemAstBuilder; |
|
|
|
|
List<IAstTransform> astTransforms; |
|
|
|
|
List<IAstTransform> astTransforms = new List<IAstTransform> { |
|
|
|
|
//new PushNegation(),
|
|
|
|
|
//new DelegateConstruction(context),
|
|
|
|
|
//new PatternStatementTransform(context),
|
|
|
|
|
new ReplaceMethodCallsWithOperators(), |
|
|
|
|
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(), |
|
|
|
|
//new IntroduceExtensionMethods(context), // must run after IntroduceUsingDeclarations
|
|
|
|
|
//new IntroduceQueryExpressions(context), // must run after IntroduceExtensionMethods
|
|
|
|
|
//new CombineQueryExpressions(context),
|
|
|
|
|
//new FlattenSwitchBlocks(),
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
public CancellationToken CancellationToken { get; set; } |
|
|
|
|
|
|
|
|
@ -58,38 +73,27 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -58,38 +73,27 @@ namespace ICSharpCode.Decompiler.CSharp
|
|
|
|
|
if (typeSystem == null) |
|
|
|
|
throw new ArgumentNullException("typeSystem"); |
|
|
|
|
this.typeSystem = typeSystem; |
|
|
|
|
|
|
|
|
|
astTransforms = new List<IAstTransform> { |
|
|
|
|
//new PushNegation(),
|
|
|
|
|
//new DelegateConstruction(context),
|
|
|
|
|
//new PatternStatementTransform(context),
|
|
|
|
|
new ReplaceMethodCallsWithOperators(), |
|
|
|
|
new IntroduceUnsafeModifier(), |
|
|
|
|
new AddCheckedBlocks(), |
|
|
|
|
//new DeclareVariables(context), // should run after most transforms that modify statements
|
|
|
|
|
new ConvertConstructorCallIntoInitializer(typeSystem), // 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(),
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
typeSystemAstBuilder = new TypeSystemAstBuilder(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
TypeSystemAstBuilder CreateAstBuilder(ITypeResolveContext decompilationContext) |
|
|
|
|
{ |
|
|
|
|
var typeSystemAstBuilder = new TypeSystemAstBuilder(); |
|
|
|
|
typeSystemAstBuilder.AlwaysUseShortTypeNames = true; |
|
|
|
|
typeSystemAstBuilder.AddAnnotations = true; |
|
|
|
|
typeSystemAstBuilder.AddResolveResultAnnotations = true; |
|
|
|
|
return typeSystemAstBuilder; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void RunTransforms(AstNode rootNode) |
|
|
|
|
void RunTransforms(AstNode rootNode, ITypeResolveContext decompilationContext) |
|
|
|
|
{ |
|
|
|
|
var context = new TransformContext(typeSystem, decompilationContext); |
|
|
|
|
foreach (var transform in astTransforms) |
|
|
|
|
transform.Run(rootNode); |
|
|
|
|
transform.Run(rootNode, context); |
|
|
|
|
rootNode.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true }); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public SyntaxTree DecompileWholeModuleAsSingleFile() |
|
|
|
|
{ |
|
|
|
|
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainAssembly); |
|
|
|
|
SyntaxTree syntaxTree = new SyntaxTree(); |
|
|
|
|
foreach (var g in typeSystem.Compilation.MainAssembly.TopLevelTypeDefinitions.GroupBy(t => t.Namespace)) { |
|
|
|
|
AstNode groupNode; |
|
|
|
@ -104,11 +108,11 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -104,11 +108,11 @@ namespace ICSharpCode.Decompiler.CSharp
|
|
|
|
|
foreach (var typeDef in g) { |
|
|
|
|
if (typeDef.Name == "<Module>" && typeDef.Members.Count == 0) |
|
|
|
|
continue; |
|
|
|
|
var typeDecl = DoDecompile(typeDef); |
|
|
|
|
var typeDecl = DoDecompile(typeDef, decompilationContext.WithCurrentTypeDefinition(typeDef)); |
|
|
|
|
groupNode.AddChild(typeDecl, SyntaxTree.MemberRole); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
RunTransforms(syntaxTree); |
|
|
|
|
RunTransforms(syntaxTree, decompilationContext); |
|
|
|
|
return syntaxTree; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -116,16 +120,19 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -116,16 +120,19 @@ namespace ICSharpCode.Decompiler.CSharp
|
|
|
|
|
{ |
|
|
|
|
if (typeDefinition == null) |
|
|
|
|
throw new ArgumentNullException("typeDefinition"); |
|
|
|
|
ITypeDefinition typeDef = typeSystem.GetType(typeDefinition).GetDefinition(); |
|
|
|
|
ITypeDefinition typeDef = typeSystem.Resolve(typeDefinition).GetDefinition(); |
|
|
|
|
if (typeDef == null) |
|
|
|
|
throw new InvalidOperationException("Could not find type definition in NR type system"); |
|
|
|
|
var decl = DoDecompile(typeDef); |
|
|
|
|
RunTransforms(decl); |
|
|
|
|
var decompilationContext = new SimpleTypeResolveContext(typeDef); |
|
|
|
|
var decl = DoDecompile(typeDef, decompilationContext); |
|
|
|
|
RunTransforms(decl, decompilationContext); |
|
|
|
|
return decl; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
EntityDeclaration DoDecompile(ITypeDefinition typeDef) |
|
|
|
|
EntityDeclaration DoDecompile(ITypeDefinition typeDef, ITypeResolveContext decompilationContext) |
|
|
|
|
{ |
|
|
|
|
Debug.Assert(decompilationContext.CurrentTypeDefinition == typeDef); |
|
|
|
|
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); |
|
|
|
|
var entityDecl = typeSystemAstBuilder.ConvertEntity(typeDef); |
|
|
|
|
var typeDecl = entityDecl as TypeDeclaration; |
|
|
|
|
if (typeDecl == null) { |
|
|
|
@ -135,7 +142,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -135,7 +142,7 @@ namespace ICSharpCode.Decompiler.CSharp
|
|
|
|
|
foreach (var method in typeDef.Methods) { |
|
|
|
|
var methodDef = typeSystem.GetCecil(method) as MethodDefinition; |
|
|
|
|
if (methodDef != null) { |
|
|
|
|
var memberDecl = DoDecompile(methodDef, method); |
|
|
|
|
var memberDecl = DoDecompile(methodDef, method, decompilationContext.WithCurrentMember(method)); |
|
|
|
|
typeDecl.Members.Add(memberDecl); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -146,16 +153,19 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -146,16 +153,19 @@ namespace ICSharpCode.Decompiler.CSharp
|
|
|
|
|
{ |
|
|
|
|
if (methodDefinition == null) |
|
|
|
|
throw new ArgumentNullException("methodDefinition"); |
|
|
|
|
var method = typeSystem.GetMethod(methodDefinition); |
|
|
|
|
var method = typeSystem.Resolve(methodDefinition); |
|
|
|
|
if (method == null) |
|
|
|
|
throw new InvalidOperationException("Could not find method in NR type system"); |
|
|
|
|
var decl = DoDecompile(methodDefinition, method); |
|
|
|
|
RunTransforms(decl); |
|
|
|
|
var decompilationContext = new SimpleTypeResolveContext(method); |
|
|
|
|
var decl = DoDecompile(methodDefinition, method, decompilationContext); |
|
|
|
|
RunTransforms(decl, decompilationContext); |
|
|
|
|
return decl; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
EntityDeclaration DoDecompile(MethodDefinition methodDefinition, IMethod method) |
|
|
|
|
EntityDeclaration DoDecompile(MethodDefinition methodDefinition, IMethod method, ITypeResolveContext decompilationContext) |
|
|
|
|
{ |
|
|
|
|
Debug.Assert(decompilationContext.CurrentMember == method); |
|
|
|
|
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); |
|
|
|
|
var entityDecl = typeSystemAstBuilder.ConvertEntity(method); |
|
|
|
|
if (methodDefinition.HasBody) { |
|
|
|
|
var ilReader = new ILReader(typeSystem); |
|
|
|
@ -163,7 +173,7 @@ namespace ICSharpCode.Decompiler.CSharp
@@ -163,7 +173,7 @@ namespace ICSharpCode.Decompiler.CSharp
|
|
|
|
|
function.CheckInvariant(); |
|
|
|
|
function.Body = function.Body.AcceptVisitor(new TransformingVisitor()); |
|
|
|
|
function.CheckInvariant(); |
|
|
|
|
var statementBuilder = new StatementBuilder(method); |
|
|
|
|
var statementBuilder = new StatementBuilder(decompilationContext); |
|
|
|
|
var body = statementBuilder.ConvertAsBlock(function.Body); |
|
|
|
|
|
|
|
|
|
// insert variables at start of body
|
|
|
|
|