Browse Source

WIP on #945: Add Decompile*AsString overloads and DecompileType(FullTypeName).

pull/940/merge
Siegfried Pammer 8 years ago
parent
commit
484567b472
  1. 115
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

115
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -31,6 +31,7 @@ using ICSharpCode.Decompiler.IL.ControlFlow;
using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.IL.Transforms;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using System.IO;
namespace ICSharpCode.Decompiler.CSharp namespace ICSharpCode.Decompiler.CSharp
{ {
@ -185,7 +186,7 @@ namespace ICSharpCode.Decompiler.CSharp
this.typeSystem = typeSystem; this.typeSystem = typeSystem;
this.settings = settings; this.settings = settings;
} }
#region MemberIsHidden #region MemberIsHidden
public static bool MemberIsHidden(MemberReference member, DecompilerSettings settings) public static bool MemberIsHidden(MemberReference member, DecompilerSettings settings)
{ {
@ -213,7 +214,7 @@ namespace ICSharpCode.Decompiler.CSharp
return true; return true;
} }
} }
FieldDefinition field = member as FieldDefinition; FieldDefinition field = member as FieldDefinition;
if (field != null) { if (field != null) {
if (field.IsCompilerGenerated()) { if (field.IsCompilerGenerated()) {
@ -235,10 +236,10 @@ namespace ICSharpCode.Decompiler.CSharp
return true; return true;
} }
} }
return false; return false;
} }
static bool IsSwitchOnStringCache(FieldDefinition field) static bool IsSwitchOnStringCache(FieldDefinition field)
{ {
return field.Name.StartsWith("<>f__switch", StringComparison.Ordinal); return field.Name.StartsWith("<>f__switch", StringComparison.Ordinal);
@ -263,7 +264,7 @@ namespace ICSharpCode.Decompiler.CSharp
return type.BaseType.FullName == "System.Object" && !type.HasInterfaces; return type.BaseType.FullName == "System.Object" && !type.HasInterfaces;
} }
#endregion #endregion
TypeSystemAstBuilder CreateAstBuilder(ITypeResolveContext decompilationContext) TypeSystemAstBuilder CreateAstBuilder(ITypeResolveContext decompilationContext)
{ {
var typeSystemAstBuilder = new TypeSystemAstBuilder(); var typeSystemAstBuilder = new TypeSystemAstBuilder();
@ -272,7 +273,7 @@ namespace ICSharpCode.Decompiler.CSharp
typeSystemAstBuilder.AddResolveResultAnnotations = true; typeSystemAstBuilder.AddResolveResultAnnotations = true;
return typeSystemAstBuilder; return typeSystemAstBuilder;
} }
void RunTransforms(AstNode rootNode, ITypeResolveContext decompilationContext) void RunTransforms(AstNode rootNode, ITypeResolveContext decompilationContext)
{ {
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
@ -283,7 +284,14 @@ namespace ICSharpCode.Decompiler.CSharp
} }
rootNode.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true }); rootNode.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true });
} }
string SyntaxTreeToString(SyntaxTree syntaxTree)
{
StringWriter w = new StringWriter();
syntaxTree.AcceptVisitor(new CSharpOutputVisitor(w, settings.CSharpFormattingOptions));
return w.ToString();
}
/// <summary> /// <summary>
/// Decompile assembly and module attributes. /// Decompile assembly and module attributes.
/// </summary> /// </summary>
@ -297,6 +305,14 @@ namespace ICSharpCode.Decompiler.CSharp
return syntaxTree; return syntaxTree;
} }
/// <summary>
/// Decompile assembly and module attributes.
/// </summary>
public string DecompileModuleAndAssemblyAttributesToString()
{
return SyntaxTreeToString(DecompileModuleAndAssemblyAttributes());
}
void DoDecompileModuleAndAssemblyAttributes(ITypeResolveContext decompilationContext, SyntaxTree syntaxTree) void DoDecompileModuleAndAssemblyAttributes(ITypeResolveContext decompilationContext, SyntaxTree syntaxTree)
{ {
foreach (var a in typeSystem.Compilation.MainAssembly.AssemblyAttributes) { foreach (var a in typeSystem.Compilation.MainAssembly.AssemblyAttributes) {
@ -330,7 +346,7 @@ namespace ICSharpCode.Decompiler.CSharp
groupNode.AddChild(typeDecl, SyntaxTree.MemberRole); groupNode.AddChild(typeDecl, SyntaxTree.MemberRole);
} }
} }
/// <summary> /// <summary>
/// Decompiles the whole module into a single syntax tree. /// Decompiles the whole module into a single syntax tree.
/// </summary> /// </summary>
@ -344,7 +360,15 @@ namespace ICSharpCode.Decompiler.CSharp
RunTransforms(syntaxTree, decompilationContext); RunTransforms(syntaxTree, decompilationContext);
return syntaxTree; return syntaxTree;
} }
/// <summary>
/// Decompiles the whole module into a single string.
/// </summary>
public string DecompileWholeModuleAsString()
{
return SyntaxTreeToString(DecompileWholeModuleAsSingleFile());
}
/// <summary> /// <summary>
/// Decompile the given types. /// Decompile the given types.
/// </summary> /// </summary>
@ -363,6 +387,47 @@ namespace ICSharpCode.Decompiler.CSharp
return syntaxTree; return syntaxTree;
} }
/// <summary>
/// Decompile the given types.
/// </summary>
/// <remarks>
/// Unlike Decompile(IMemberDefinition[]), this method will add namespace declarations around the type definitions.
/// </remarks>
public string DecompileTypesAsString(IEnumerable<TypeDefinition> types)
{
return SyntaxTreeToString(DecompileTypes(types));
}
/// <summary>
/// Decompile the given type.
/// </summary>
/// <remarks>
/// Unlike Decompile(IMemberDefinition[]), this method will add namespace declarations around the type definition.
/// </remarks>
public SyntaxTree DecompileType(FullTypeName fullTypeName)
{
var type = typeSystem.Compilation.FindType(fullTypeName).GetDefinition();
if (type == null)
throw new InvalidOperationException($"Could not find type definition {fullTypeName} in type system.");
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainAssembly);
syntaxTree = new SyntaxTree();
definedSymbols = new HashSet<string>();
DoDecompileTypes(new[] { typeSystem.GetCecil(type) }, decompilationContext, syntaxTree);
RunTransforms(syntaxTree, decompilationContext);
return syntaxTree;
}
/// <summary>
/// Decompile the given type.
/// </summary>
/// <remarks>
/// Unlike Decompile(IMemberDefinition[]), this method will add namespace declarations around the type definition.
/// </remarks>
public string DecompileTypeAsString(FullTypeName fullTypeName)
{
return SyntaxTreeToString(DecompileType(fullTypeName));
}
/// <summary> /// <summary>
/// Decompile the specified types and/or members. /// Decompile the specified types and/or members.
/// </summary> /// </summary>
@ -427,6 +492,22 @@ namespace ICSharpCode.Decompiler.CSharp
return syntaxTree; return syntaxTree;
} }
/// <summary>
/// Decompile the specified types and/or members.
/// </summary>
public string DecompileAsString(params IMemberDefinition[] definitions)
{
return SyntaxTreeToString(Decompile(definitions));
}
/// <summary>
/// Decompile the specified types and/or members.
/// </summary>
public string DecompileAsString(IList<IMemberDefinition> definitions)
{
return SyntaxTreeToString(Decompile(definitions));
}
IEnumerable<EntityDeclaration> AddInterfaceImplHelpers(EntityDeclaration memberDecl, MethodDefinition methodDef, IEnumerable<EntityDeclaration> AddInterfaceImplHelpers(EntityDeclaration memberDecl, MethodDefinition methodDef,
TypeSystemAstBuilder astBuilder) TypeSystemAstBuilder astBuilder)
{ {
@ -446,7 +527,7 @@ namespace ICSharpCode.Decompiler.CSharp
methodDecl.Parameters.AddRange(memberDecl.GetChildrenByRole(Roles.Parameter).Select(n => n.Clone())); methodDecl.Parameters.AddRange(memberDecl.GetChildrenByRole(Roles.Parameter).Select(n => n.Clone()));
methodDecl.Constraints.AddRange(memberDecl.GetChildrenByRole(Roles.Constraint) methodDecl.Constraints.AddRange(memberDecl.GetChildrenByRole(Roles.Constraint)
.Select(n => (Constraint)n.Clone())); .Select(n => (Constraint)n.Clone()));
methodDecl.Body = new BlockStatement(); methodDecl.Body = new BlockStatement();
methodDecl.Body.AddChild(new Comment( methodDecl.Body.AddChild(new Comment(
"ILSpy generated this explicit interface implementation from .override directive in " + memberDecl.Name), "ILSpy generated this explicit interface implementation from .override directive in " + memberDecl.Name),
@ -463,7 +544,7 @@ namespace ICSharpCode.Decompiler.CSharp
yield return methodDecl; yield return methodDecl;
} }
} }
Expression ForwardParameter(ParameterDeclaration p) Expression ForwardParameter(ParameterDeclaration p)
{ {
switch (p.ParameterModifier) { switch (p.ParameterModifier) {
@ -475,7 +556,7 @@ namespace ICSharpCode.Decompiler.CSharp
return new IdentifierExpression(p.Name); return new IdentifierExpression(p.Name);
} }
} }
/// <summary> /// <summary>
/// Sets new modifier if the member hides some other member from a base type. /// Sets new modifier if the member hides some other member from a base type.
/// </summary> /// </summary>
@ -485,7 +566,7 @@ namespace ICSharpCode.Decompiler.CSharp
bool addNewModifier = false; bool addNewModifier = false;
var entity = (IEntity)member.GetSymbol(); var entity = (IEntity)member.GetSymbol();
var lookup = new MemberLookup(entity.DeclaringTypeDefinition, entity.ParentAssembly); var lookup = new MemberLookup(entity.DeclaringTypeDefinition, entity.ParentAssembly);
var baseTypes = entity.DeclaringType.GetNonInterfaceBaseTypes().Where(t => entity.DeclaringType != t); var baseTypes = entity.DeclaringType.GetNonInterfaceBaseTypes().Where(t => entity.DeclaringType != t);
if (entity is ITypeDefinition) { if (entity is ITypeDefinition) {
addNewModifier = baseTypes.SelectMany(b => b.GetNestedTypes(t => t.Name == entity.Name && lookup.IsAccessible(t, true))).Any(); addNewModifier = baseTypes.SelectMany(b => b.GetNestedTypes(t => t.Name == entity.Name && lookup.IsAccessible(t, true))).Any();
@ -523,7 +604,7 @@ namespace ICSharpCode.Decompiler.CSharp
i++; i++;
} }
} }
EntityDeclaration DoDecompile(ITypeDefinition typeDef, ITypeResolveContext decompilationContext) EntityDeclaration DoDecompile(ITypeDefinition typeDef, ITypeResolveContext decompilationContext)
{ {
Debug.Assert(decompilationContext.CurrentTypeDefinition == typeDef); Debug.Assert(decompilationContext.CurrentTypeDefinition == typeDef);
@ -622,7 +703,7 @@ namespace ICSharpCode.Decompiler.CSharp
}; };
return method; return method;
} }
EntityDeclaration DoDecompile(MethodDefinition methodDefinition, IMethod method, ITypeResolveContext decompilationContext) EntityDeclaration DoDecompile(MethodDefinition methodDefinition, IMethod method, ITypeResolveContext decompilationContext)
{ {
Debug.Assert(decompilationContext.CurrentMember == method); Debug.Assert(decompilationContext.CurrentMember == method);
@ -661,7 +742,7 @@ namespace ICSharpCode.Decompiler.CSharp
i++; i++;
} }
} }
var context = new ILTransformContext(function, specializingTypeSystem, settings) { var context = new ILTransformContext(function, specializingTypeSystem, settings) {
CancellationToken = CancellationToken CancellationToken = CancellationToken
}; };
@ -773,7 +854,7 @@ namespace ICSharpCode.Decompiler.CSharp
SetNewModifier(propertyDecl); SetNewModifier(propertyDecl);
return propertyDecl; return propertyDecl;
} }
EntityDeclaration DoDecompile(EventDefinition eventDefinition, IEvent ev, ITypeResolveContext decompilationContext) EntityDeclaration DoDecompile(EventDefinition eventDefinition, IEvent ev, ITypeResolveContext decompilationContext)
{ {
Debug.Assert(decompilationContext.CurrentMember == ev); Debug.Assert(decompilationContext.CurrentMember == ev);

Loading…
Cancel
Save