Browse Source

Output the skeleton code using NRefactory instead of CodeDom

pull/1/head^2
David Srbecký 18 years ago
parent
commit
e5500abf75
  1. 4
      Decompiler.csproj
  2. 211
      src/CodeDomBuilder.cs
  3. 9
      src/CodeDomMetodBodyBuilder.cs
  4. 2
      src/Program.cs

4
Decompiler.csproj

@ -25,6 +25,9 @@
</PropertyGroup> </PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
<ItemGroup> <ItemGroup>
<Reference Include="ICSharpCode.NRefactory">
<HintPath>lib\NRefactory\ICSharpCode.NRefactory.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Drawing" /> <Reference Include="System.Drawing" />
@ -35,7 +38,6 @@
<Folder Include="src" /> <Folder Include="src" />
<Compile Include="src\AssemblyInfo.cs" /> <Compile Include="src\AssemblyInfo.cs" />
<Compile Include="src\CodeDomBuilder.cs" /> <Compile Include="src\CodeDomBuilder.cs" />
<Compile Include="src\CodeDomMetodBodyBuilder.cs" />
<Compile Include="src\MainForm.cs" /> <Compile Include="src\MainForm.cs" />
<Compile Include="src\MainForm.Designer.cs" /> <Compile Include="src\MainForm.Designer.cs" />
<Compile Include="src\Program.cs" /> <Compile Include="src\Program.cs" />

211
src/CodeDomBuilder.cs

@ -1,41 +1,30 @@
using System; using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Windows.Forms; using System.Windows.Forms;
using Microsoft.CSharp; using Microsoft.CSharp;
using Ast = ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.PrettyPrinter;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil; using Mono.Cecil.Cil;
namespace Decompiler namespace Decompiler
{ {
public class CodeDomBuilder public class ASTBuilder
{ {
CodeCompileUnit codeCompileUnit = new CodeCompileUnit(); CompilationUnit astCompileUnit = new CompilationUnit();
Dictionary<string, CodeNamespace> codeNamespaces = new Dictionary<string, CodeNamespace>(); Dictionary<string, NamespaceDeclaration> astNamespaces = new Dictionary<string, NamespaceDeclaration>();
public string GenerateCode() public string GenerateCode()
{ {
CSharpCodeProvider provider = new CSharpCodeProvider(); CSharpOutputVisitor csOutVisitor = new CSharpOutputVisitor();
TextWriter stringWriter = new StringWriter();
CodeGeneratorOptions options = new CodeGeneratorOptions(); astCompileUnit.AcceptVisitor(csOutVisitor, null);
options.BlankLinesBetweenMembers = true;
options.BracingStyle = "C";
options.ElseOnClosing = true;
options.IndentString = " ";
options.VerbatimOrder = true;
provider.GenerateCodeFromCompileUnit(codeCompileUnit, stringWriter, options); string code = csOutVisitor.Text.Replace("\t", " ");
// 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);
}
// Post processing commands // Post processing commands
while(true) { while(true) {
@ -77,142 +66,152 @@ namespace Decompiler
} }
} }
CodeNamespace GetCodeNamespace(string name) NamespaceDeclaration GetCodeNamespace(string name)
{ {
if (codeNamespaces.ContainsKey(name)) { if (astNamespaces.ContainsKey(name)) {
return codeNamespaces[name]; return astNamespaces[name];
} else { } else {
// Create the namespace // Create the namespace
CodeNamespace codeNamespace = new CodeNamespace(name); NamespaceDeclaration astNamespace = new NamespaceDeclaration(name);
codeCompileUnit.Namespaces.Add(codeNamespace); astCompileUnit.Children.Add(astNamespace);
codeNamespaces[name] = codeNamespace; astNamespaces[name] = astNamespace;
return codeNamespace; return astNamespace;
} }
} }
public void AddType(TypeDefinition typeDef) public void AddType(TypeDefinition typeDef)
{ {
CodeTypeDeclaration codeType = CreateType(typeDef); TypeDeclaration astType = CreateType(typeDef);
GetCodeNamespace(typeDef.Namespace).Types.Add(codeType); GetCodeNamespace(typeDef.Namespace).Children.Add(astType);
} }
public CodeTypeDeclaration CreateType(TypeDefinition typeDef) public TypeDeclaration CreateType(TypeDefinition typeDef)
{ {
CodeTypeDeclaration codeType = new CodeTypeDeclaration(); TypeDeclaration astType = new TypeDeclaration(ConvertModifiers(typeDef), new List<AttributeSection>());
codeType.Name = typeDef.Name; astType.Name = typeDef.Name;
// Copy modifiers across (includes 'is interface' attribute) if (typeDef.IsEnum) { // NB: Enum is value type
codeType.TypeAttributes = (System.Reflection.TypeAttributes)typeDef.Attributes; astType.Type = ClassType.Enum;
} else if (typeDef.IsValueType) {
// Is struct or enum? astType.Type = ClassType.Struct;
if (typeDef.IsValueType) { } else if (typeDef.IsInterface) {
if (typeDef.IsEnum) { // NB: Enum is value type astType.Type = ClassType.Interface;
codeType.IsEnum = true; } else {
} else { astType.Type = ClassType.Class;
codeType.IsStruct = true;
}
} }
// Nested types // Nested types
foreach(TypeDefinition nestedTypeDef in typeDef.NestedTypes) { foreach(TypeDefinition nestedTypeDef in typeDef.NestedTypes) {
codeType.Members.Add(CreateType(nestedTypeDef)); astType.Children.Add(CreateType(nestedTypeDef));
} }
// Base type // Base type
if (typeDef.BaseType != null && !typeDef.IsValueType && typeDef.BaseType.FullName != Constants.Object) { 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 return
// Access modifiers (typeDef.IsNestedPrivate ? Modifiers.Private : Modifiers.None) |
(methodDef.IsCompilerControlled ? noAttribs : noAttribs) | (typeDef.IsNestedFamilyAndAssembly ? Modifiers.Protected : Modifiers.None) | // TODO: Extended access
(methodDef.IsPrivate ? MemberAttributes.Private : noAttribs) | (typeDef.IsNestedAssembly ? Modifiers.Internal : Modifiers.None) |
(methodDef.IsFamilyAndAssembly ? MemberAttributes.FamilyAndAssembly : noAttribs) | (typeDef.IsNestedFamily ? Modifiers.Protected : Modifiers.None) |
(methodDef.IsAssembly ? MemberAttributes.Assembly : noAttribs) | (typeDef.IsNestedFamilyOrAssembly ? Modifiers.Protected | Modifiers.Internal : Modifiers.None) |
(methodDef.IsFamily ? MemberAttributes.Family : noAttribs) | (typeDef.IsPublic ? Modifiers.Public : Modifiers.None) |
(methodDef.IsFamilyOrAssembly ? MemberAttributes.FamilyOrAssembly : noAttribs) | (typeDef.IsAbstract ? Modifiers.Abstract : Modifiers.None);
(methodDef.IsPublic ? MemberAttributes.Public : noAttribs) |
// Others
(methodDef.IsStatic ? MemberAttributes.Static : noAttribs) |
// Method specific
(methodDef.IsFinal ? MemberAttributes.Final : noAttribs) |
(methodDef.IsAbstract ? MemberAttributes.Abstract : noAttribs);
} }
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 // Add fields
foreach(FieldDefinition fieldDef in typeDef.Fields) { foreach(FieldDefinition fieldDef in typeDef.Fields) {
CodeMemberField codeField = new CodeMemberField(); Ast.FieldDeclaration astField = new Ast.FieldDeclaration(new List<AttributeSection>());
codeField.Name = fieldDef.Name; astField.Fields.Add(new Ast.VariableDeclaration(fieldDef.Name));
codeField.Type = new CodeTypeReference(fieldDef.FieldType.FullName); astField.TypeReference = new Ast.TypeReference(fieldDef.FieldType.FullName);
codeField.Attributes = astField.Modifier = ConvertModifiers(fieldDef);
// 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);
codeType.Members.Add(codeField); astType.Children.Add(astField);
} }
// Add properties // Add properties
foreach(PropertyDefinition propDef in typeDef.Properties) { foreach(PropertyDefinition propDef in typeDef.Properties) {
CodeMemberProperty codeProp = new CodeMemberProperty(); Ast.PropertyDeclaration astProp = new Ast.PropertyDeclaration(
codeProp.Name = propDef.Name; ConvertModifiers(propDef.GetMethod),
codeProp.Type = new CodeTypeReference(propDef.PropertyType.FullName); new List<AttributeSection>(),
codeProp.Attributes = GetMethodAttributes(propDef.GetMethod); propDef.Name,
new List<ParameterDeclarationExpression>()
codeType.Members.Add(codeProp); );
astProp.TypeReference = new Ast.TypeReference(propDef.PropertyType.FullName);
astType.Children.Add(astProp);
} }
foreach(EventDefinition eventDef in typeDef.Events) { foreach(EventDefinition eventDef in typeDef.Events) {
CodeMemberEvent codeEvent = new CodeMemberEvent(); Ast.EventDeclaration astEvent = new Ast.EventDeclaration();
codeEvent.Name = eventDef.Name; astEvent.Name = eventDef.Name;
codeEvent.Type = new CodeTypeReference(eventDef.EventType.FullName); astEvent.TypeReference = new Ast.TypeReference(eventDef.EventType.FullName);
codeEvent.Attributes = GetMethodAttributes(eventDef.AddMethod); astEvent.Modifier = ConvertModifiers(eventDef.AddMethod);
codeType.Members.Add(codeEvent); astType.Children.Add(astEvent);
} }
foreach(MethodDefinition methodDef in typeDef.Methods) { foreach(MethodDefinition methodDef in typeDef.Methods) {
if (methodDef.IsSpecialName) continue; if (methodDef.IsSpecialName) continue;
CodeMemberMethod codeMethod = new CodeMemberMethod(); Ast.MethodDeclaration astMethod = new Ast.MethodDeclaration();
codeMethod.Name = methodDef.Name; astMethod.Name = methodDef.Name;
codeMethod.ReturnType = new CodeTypeReference(methodDef.ReturnType.ReturnType.FullName); astMethod.TypeReference = new Ast.TypeReference(methodDef.ReturnType.ReturnType.FullName);
codeMethod.Attributes = GetMethodAttributes(methodDef); astMethod.Modifier = ConvertModifiers(methodDef);
foreach(ParameterDefinition paramDef in methodDef.Parameters) { foreach(ParameterDefinition paramDef in methodDef.Parameters) {
CodeParameterDeclarationExpression codeParam = new CodeParameterDeclarationExpression(); Ast.ParameterDeclarationExpression astParam = new Ast.ParameterDeclarationExpression(
codeParam.Name = paramDef.Name; new Ast.TypeReference(paramDef.ParameterType.FullName),
codeParam.Type = new CodeTypeReference(paramDef.ParameterType.FullName); paramDef.Name
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; 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);
} }
} }
} }

9
src/CodeDomMetodBodyBuilder.cs

@ -1,14 +1,15 @@
using System; using System;
using System.CodeDom;
using ICSharpCode.NRefactory.Ast;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil; using Mono.Cecil.Cil;
namespace Decompiler namespace Decompiler
{ {
public class CodeDomMetodBodyBuilder public class ASTMetodBodyBuilder
{ {
public static CodeStatementCollection CreateMetodBody(MethodDefinition methodDef) public static BlockStatement CreateMetodBody(MethodDefinition methodDef)
{ {
CodeStatementCollection codeStmtCol = new CodeStatementCollection(); 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; OpCode opCode = inst.OpCode;
object operand = inst.Operand; object operand = inst.Operand;

2
src/Program.cs

@ -33,7 +33,7 @@ namespace Decompiler
static string Decompile(string filename) static string Decompile(string filename)
{ {
AssemblyDefinition assembly = AssemblyFactory.GetAssembly(filename); AssemblyDefinition assembly = AssemblyFactory.GetAssembly(filename);
CodeDomBuilder codeDomBuilder = new CodeDomBuilder(); ASTBuilder codeDomBuilder = new ASTBuilder();
codeDomBuilder.AddAssembly(assembly); codeDomBuilder.AddAssembly(assembly);
return codeDomBuilder.GenerateCode(); return codeDomBuilder.GenerateCode();
} }

Loading…
Cancel
Save