From e5500abf7529212dd4faf95696afc2248bb67486 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Srbeck=C3=BD?= Date: Sat, 3 Nov 2007 15:37:41 +0000 Subject: [PATCH] Output the skeleton code using NRefactory instead of CodeDom --- Decompiler.csproj | 4 +- src/CodeDomBuilder.cs | 211 ++++++++++++++++----------------- src/CodeDomMetodBodyBuilder.cs | 9 +- src/Program.cs | 2 +- 4 files changed, 114 insertions(+), 112 deletions(-) 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(); }