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. 209
      src/CodeDomBuilder.cs
  3. 9
      src/CodeDomMetodBodyBuilder.cs
  4. 2
      src/Program.cs

4
Decompiler.csproj

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

209
src/CodeDomBuilder.cs

@ -1,41 +1,30 @@ @@ -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<string, CodeNamespace> codeNamespaces = new Dictionary<string, CodeNamespace>();
CompilationUnit astCompileUnit = new CompilationUnit();
Dictionary<string, NamespaceDeclaration> astNamespaces = new Dictionary<string, NamespaceDeclaration>();
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 @@ -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;
TypeDeclaration astType = new TypeDeclaration(ConvertModifiers(typeDef), new List<AttributeSection>());
astType.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;
astType.Type = ClassType.Enum;
} else if (typeDef.IsValueType) {
astType.Type = ClassType.Struct;
} else if (typeDef.IsInterface) {
astType.Type = ClassType.Interface;
} else {
codeType.IsStruct = true;
}
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);
}
void AddTypeMembers(CodeTypeDeclaration codeType, TypeDefinition typeDef)
(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);
}
Modifiers ConvertModifiers(FieldDefinition fieldDef)
{
MemberAttributes noAttribs = (MemberAttributes)0;
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)
{
// 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);
codeType.Members.Add(codeField);
Ast.FieldDeclaration astField = new Ast.FieldDeclaration(new List<AttributeSection>());
astField.Fields.Add(new Ast.VariableDeclaration(fieldDef.Name));
astField.TypeReference = new Ast.TypeReference(fieldDef.FieldType.FullName);
astField.Modifier = ConvertModifiers(fieldDef);
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<AttributeSection>(),
propDef.Name,
new List<ParameterDeclarationExpression>()
);
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);
}
}
}

9
src/CodeDomMetodBodyBuilder.cs

@ -1,14 +1,15 @@ @@ -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 @@ -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;

2
src/Program.cs

@ -33,7 +33,7 @@ namespace Decompiler @@ -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();
}

Loading…
Cancel
Save