diff --git a/Decompiler.csproj b/Decompiler.csproj
index 953d4d2c3..ca332c2cc 100644
--- a/Decompiler.csproj
+++ b/Decompiler.csproj
@@ -25,6 +25,9 @@
+
+ lib\NRefactory\ICSharpCode.NRefactory.dll
+
@@ -35,7 +38,6 @@
-
diff --git a/src/CodeDomBuilder.cs b/src/CodeDomBuilder.cs
index 5770093aa..dfe80397a 100644
--- a/src/CodeDomBuilder.cs
+++ b/src/CodeDomBuilder.cs
@@ -1,41 +1,30 @@
using System;
-using System.CodeDom;
-using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using Microsoft.CSharp;
+using Ast = ICSharpCode.NRefactory.Ast;
+using ICSharpCode.NRefactory.Ast;
+using ICSharpCode.NRefactory.PrettyPrinter;
+
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace Decompiler
{
- public class CodeDomBuilder
+ public class ASTBuilder
{
- CodeCompileUnit codeCompileUnit = new CodeCompileUnit();
- Dictionary codeNamespaces = new Dictionary();
+ CompilationUnit astCompileUnit = new CompilationUnit();
+ Dictionary astNamespaces = new Dictionary();
public string GenerateCode()
{
- CSharpCodeProvider provider = new CSharpCodeProvider();
-
- TextWriter stringWriter = new StringWriter();
+ CSharpOutputVisitor csOutVisitor = new CSharpOutputVisitor();
- CodeGeneratorOptions options = new CodeGeneratorOptions();
- options.BlankLinesBetweenMembers = true;
- options.BracingStyle = "C";
- options.ElseOnClosing = true;
- options.IndentString = " ";
- options.VerbatimOrder = true;
+ astCompileUnit.AcceptVisitor(csOutVisitor, null);
- provider.GenerateCodeFromCompileUnit(codeCompileUnit, stringWriter, options);
-
- // Remove the generated comments at the start
- string code = stringWriter.ToString();
- while(code.StartsWith("//") || code.StartsWith("\r\n")) {
- code = code.Remove(0, code.IndexOf("\r\n") + "\r\n".Length);
- }
+ string code = csOutVisitor.Text.Replace("\t", " ");
// Post processing commands
while(true) {
@@ -77,142 +66,152 @@ namespace Decompiler
}
}
- CodeNamespace GetCodeNamespace(string name)
+ NamespaceDeclaration GetCodeNamespace(string name)
{
- if (codeNamespaces.ContainsKey(name)) {
- return codeNamespaces[name];
+ if (astNamespaces.ContainsKey(name)) {
+ return astNamespaces[name];
} else {
// Create the namespace
- CodeNamespace codeNamespace = new CodeNamespace(name);
- codeCompileUnit.Namespaces.Add(codeNamespace);
- codeNamespaces[name] = codeNamespace;
- return codeNamespace;
+ NamespaceDeclaration astNamespace = new NamespaceDeclaration(name);
+ astCompileUnit.Children.Add(astNamespace);
+ astNamespaces[name] = astNamespace;
+ return astNamespace;
}
}
public void AddType(TypeDefinition typeDef)
{
- CodeTypeDeclaration codeType = CreateType(typeDef);
- GetCodeNamespace(typeDef.Namespace).Types.Add(codeType);
+ TypeDeclaration astType = CreateType(typeDef);
+ GetCodeNamespace(typeDef.Namespace).Children.Add(astType);
}
- public CodeTypeDeclaration CreateType(TypeDefinition typeDef)
+ public TypeDeclaration CreateType(TypeDefinition typeDef)
{
- CodeTypeDeclaration codeType = new CodeTypeDeclaration();
- codeType.Name = typeDef.Name;
-
- // Copy modifiers across (includes 'is interface' attribute)
- codeType.TypeAttributes = (System.Reflection.TypeAttributes)typeDef.Attributes;
-
- // Is struct or enum?
- if (typeDef.IsValueType) {
- if (typeDef.IsEnum) { // NB: Enum is value type
- codeType.IsEnum = true;
- } else {
- codeType.IsStruct = true;
- }
+ TypeDeclaration astType = new TypeDeclaration(ConvertModifiers(typeDef), new List());
+ astType.Name = typeDef.Name;
+
+ if (typeDef.IsEnum) { // NB: Enum is value type
+ astType.Type = ClassType.Enum;
+ } else if (typeDef.IsValueType) {
+ astType.Type = ClassType.Struct;
+ } else if (typeDef.IsInterface) {
+ astType.Type = ClassType.Interface;
+ } else {
+ astType.Type = ClassType.Class;
}
// Nested types
foreach(TypeDefinition nestedTypeDef in typeDef.NestedTypes) {
- codeType.Members.Add(CreateType(nestedTypeDef));
+ astType.Children.Add(CreateType(nestedTypeDef));
}
// Base type
if (typeDef.BaseType != null && !typeDef.IsValueType && typeDef.BaseType.FullName != Constants.Object) {
- codeType.BaseTypes.Add(typeDef.BaseType.FullName);
+ astType.BaseTypes.Add(new Ast.TypeReference(typeDef.BaseType.FullName));
}
- AddTypeMembers(codeType, typeDef);
+ AddTypeMembers(astType, typeDef);
- return codeType;
+ return astType;
}
- MemberAttributes GetMethodAttributes(MethodDefinition methodDef)
+ Modifiers ConvertModifiers(TypeDefinition typeDef)
{
- MemberAttributes noAttribs = (MemberAttributes)0;
return
- // Access modifiers
- (methodDef.IsCompilerControlled ? noAttribs : noAttribs) |
- (methodDef.IsPrivate ? MemberAttributes.Private : noAttribs) |
- (methodDef.IsFamilyAndAssembly ? MemberAttributes.FamilyAndAssembly : noAttribs) |
- (methodDef.IsAssembly ? MemberAttributes.Assembly : noAttribs) |
- (methodDef.IsFamily ? MemberAttributes.Family : noAttribs) |
- (methodDef.IsFamilyOrAssembly ? MemberAttributes.FamilyOrAssembly : noAttribs) |
- (methodDef.IsPublic ? MemberAttributes.Public : noAttribs) |
- // Others
- (methodDef.IsStatic ? MemberAttributes.Static : noAttribs) |
- // Method specific
- (methodDef.IsFinal ? MemberAttributes.Final : noAttribs) |
- (methodDef.IsAbstract ? MemberAttributes.Abstract : noAttribs);
+ (typeDef.IsNestedPrivate ? Modifiers.Private : Modifiers.None) |
+ (typeDef.IsNestedFamilyAndAssembly ? Modifiers.Protected : Modifiers.None) | // TODO: Extended access
+ (typeDef.IsNestedAssembly ? Modifiers.Internal : Modifiers.None) |
+ (typeDef.IsNestedFamily ? Modifiers.Protected : Modifiers.None) |
+ (typeDef.IsNestedFamilyOrAssembly ? Modifiers.Protected | Modifiers.Internal : Modifiers.None) |
+ (typeDef.IsPublic ? Modifiers.Public : Modifiers.None) |
+ (typeDef.IsAbstract ? Modifiers.Abstract : Modifiers.None);
}
- void AddTypeMembers(CodeTypeDeclaration codeType, TypeDefinition typeDef)
+ Modifiers ConvertModifiers(FieldDefinition fieldDef)
+ {
+ return
+ (fieldDef.IsPrivate ? Modifiers.Private : Modifiers.None) |
+ (fieldDef.IsFamilyAndAssembly ? Modifiers.Protected : Modifiers.None) | // TODO: Extended access
+ (fieldDef.IsAssembly ? Modifiers.Internal : Modifiers.None) |
+ (fieldDef.IsFamily ? Modifiers.Protected : Modifiers.None) |
+ (fieldDef.IsFamilyOrAssembly ? Modifiers.Protected | Modifiers.Internal : Modifiers.None) |
+ (fieldDef.IsPublic ? Modifiers.Public : Modifiers.None) |
+ (fieldDef.IsLiteral ? Modifiers.Const : Modifiers.None) |
+ (fieldDef.IsStatic ? Modifiers.Static : Modifiers.None);
+ }
+
+ Modifiers ConvertModifiers(MethodDefinition methodDef)
+ {
+ return
+ (methodDef.IsCompilerControlled ? Modifiers.None : Modifiers.None) |
+ (methodDef.IsPrivate ? Modifiers.Private : Modifiers.None) |
+ (methodDef.IsFamilyAndAssembly ? Modifiers.Protected : Modifiers.None) | // TODO: Extended access
+ (methodDef.IsAssembly ? Modifiers.Internal : Modifiers.None) |
+ (methodDef.IsFamily ? Modifiers.Protected : Modifiers.None) |
+ (methodDef.IsFamilyOrAssembly ? Modifiers.Protected | Modifiers.Internal : Modifiers.None) |
+ (methodDef.IsPublic ? Modifiers.Public : Modifiers.None) |
+ (methodDef.IsStatic ? Modifiers.Static : Modifiers.None) |
+ (methodDef.IsVirtual ? Modifiers.Virtual : Modifiers.None) |
+ (methodDef.IsAbstract ? Modifiers.Abstract : Modifiers.None);
+ }
+
+ void AddTypeMembers(TypeDeclaration astType, TypeDefinition typeDef)
{
- MemberAttributes noAttribs = (MemberAttributes)0;
-
// Add fields
foreach(FieldDefinition fieldDef in typeDef.Fields) {
- CodeMemberField codeField = new CodeMemberField();
- codeField.Name = fieldDef.Name;
- codeField.Type = new CodeTypeReference(fieldDef.FieldType.FullName);
- codeField.Attributes =
- // Access modifiers
- (fieldDef.IsCompilerControlled ? noAttribs : noAttribs) |
- (fieldDef.IsPrivate ? MemberAttributes.Private : noAttribs) |
- (fieldDef.IsFamilyAndAssembly ? MemberAttributes.FamilyAndAssembly : noAttribs) |
- (fieldDef.IsAssembly ? MemberAttributes.Assembly : noAttribs) |
- (fieldDef.IsFamily ? MemberAttributes.Family : noAttribs) |
- (fieldDef.IsFamilyOrAssembly ? MemberAttributes.FamilyOrAssembly : noAttribs) |
- (fieldDef.IsPublic ? MemberAttributes.Public : noAttribs) |
- // Others
- (fieldDef.IsLiteral ? MemberAttributes.Const : noAttribs) |
- (fieldDef.IsStatic ? MemberAttributes.Static : noAttribs);
+ Ast.FieldDeclaration astField = new Ast.FieldDeclaration(new List());
+ astField.Fields.Add(new Ast.VariableDeclaration(fieldDef.Name));
+ astField.TypeReference = new Ast.TypeReference(fieldDef.FieldType.FullName);
+ astField.Modifier = ConvertModifiers(fieldDef);
- codeType.Members.Add(codeField);
+ astType.Children.Add(astField);
}
// Add properties
foreach(PropertyDefinition propDef in typeDef.Properties) {
- CodeMemberProperty codeProp = new CodeMemberProperty();
- codeProp.Name = propDef.Name;
- codeProp.Type = new CodeTypeReference(propDef.PropertyType.FullName);
- codeProp.Attributes = GetMethodAttributes(propDef.GetMethod);
-
- codeType.Members.Add(codeProp);
+ Ast.PropertyDeclaration astProp = new Ast.PropertyDeclaration(
+ ConvertModifiers(propDef.GetMethod),
+ new List(),
+ propDef.Name,
+ new List()
+ );
+ astProp.TypeReference = new Ast.TypeReference(propDef.PropertyType.FullName);
+ astType.Children.Add(astProp);
}
foreach(EventDefinition eventDef in typeDef.Events) {
- CodeMemberEvent codeEvent = new CodeMemberEvent();
- codeEvent.Name = eventDef.Name;
- codeEvent.Type = new CodeTypeReference(eventDef.EventType.FullName);
- codeEvent.Attributes = GetMethodAttributes(eventDef.AddMethod);
+ Ast.EventDeclaration astEvent = new Ast.EventDeclaration();
+ astEvent.Name = eventDef.Name;
+ astEvent.TypeReference = new Ast.TypeReference(eventDef.EventType.FullName);
+ astEvent.Modifier = ConvertModifiers(eventDef.AddMethod);
- codeType.Members.Add(codeEvent);
+ astType.Children.Add(astEvent);
}
foreach(MethodDefinition methodDef in typeDef.Methods) {
if (methodDef.IsSpecialName) continue;
- CodeMemberMethod codeMethod = new CodeMemberMethod();
- codeMethod.Name = methodDef.Name;
- codeMethod.ReturnType = new CodeTypeReference(methodDef.ReturnType.ReturnType.FullName);
- codeMethod.Attributes = GetMethodAttributes(methodDef);
+ Ast.MethodDeclaration astMethod = new Ast.MethodDeclaration();
+ astMethod.Name = methodDef.Name;
+ astMethod.TypeReference = new Ast.TypeReference(methodDef.ReturnType.ReturnType.FullName);
+ astMethod.Modifier = ConvertModifiers(methodDef);
foreach(ParameterDefinition paramDef in methodDef.Parameters) {
- CodeParameterDeclarationExpression codeParam = new CodeParameterDeclarationExpression();
- codeParam.Name = paramDef.Name;
- codeParam.Type = new CodeTypeReference(paramDef.ParameterType.FullName);
- if (paramDef.IsIn && !paramDef.IsOut) codeParam.Direction = FieldDirection.In;
- if (!paramDef.IsIn && paramDef.IsOut) codeParam.Direction = FieldDirection.Out;
- if (paramDef.IsIn && paramDef.IsOut) codeParam.Direction = FieldDirection.Ref;
+ Ast.ParameterDeclarationExpression astParam = new Ast.ParameterDeclarationExpression(
+ new Ast.TypeReference(paramDef.ParameterType.FullName),
+ paramDef.Name
+ );
+
+ if (paramDef.IsIn && !paramDef.IsOut) astParam.ParamModifier = ParameterModifiers.In;
+ if (!paramDef.IsIn && paramDef.IsOut) astParam.ParamModifier = ParameterModifiers.Out;
+ if (paramDef.IsIn && paramDef.IsOut) astParam.ParamModifier = ParameterModifiers.Ref;
- codeMethod.Parameters.Add(codeParam);
+ astMethod.Parameters.Add(astParam);
}
- codeMethod.Statements.AddRange(CodeDomMetodBodyBuilder.CreateMetodBody(methodDef));
+ //astMethod.Statements.AddRange(ASTMetodBodyBuilder.CreateMetodBody(methodDef));
- codeType.Members.Add(codeMethod);
+ astType.Children.Add(astMethod);
}
}
}
diff --git a/src/CodeDomMetodBodyBuilder.cs b/src/CodeDomMetodBodyBuilder.cs
index fe7580489..d8cbf20f8 100644
--- a/src/CodeDomMetodBodyBuilder.cs
+++ b/src/CodeDomMetodBodyBuilder.cs
@@ -1,14 +1,15 @@
using System;
-using System.CodeDom;
+
+using ICSharpCode.NRefactory.Ast;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace Decompiler
{
- public class CodeDomMetodBodyBuilder
+ public class ASTMetodBodyBuilder
{
- public static CodeStatementCollection CreateMetodBody(MethodDefinition methodDef)
+ public static BlockStatement CreateMetodBody(MethodDefinition methodDef)
{
CodeStatementCollection codeStmtCol = new CodeStatementCollection();
@@ -69,7 +70,7 @@ namespace Decompiler
}
}
- static object MakeCodeDomExpression(Instruction inst, params CodeExpression[] args)
+ static object MakeCodeDomExpression(Instruction inst, params Expression[] args)
{
OpCode opCode = inst.OpCode;
object operand = inst.Operand;
diff --git a/src/Program.cs b/src/Program.cs
index dc69bfe76..16f7d78a5 100644
--- a/src/Program.cs
+++ b/src/Program.cs
@@ -33,7 +33,7 @@ namespace Decompiler
static string Decompile(string filename)
{
AssemblyDefinition assembly = AssemblyFactory.GetAssembly(filename);
- CodeDomBuilder codeDomBuilder = new CodeDomBuilder();
+ ASTBuilder codeDomBuilder = new ASTBuilder();
codeDomBuilder.AddAssembly(assembly);
return codeDomBuilder.GenerateCode();
}