Browse Source

Add special cases for fields and constructors back in CSharpLanguage

pull/850/head
Siegfried Pammer 8 years ago
parent
commit
cf9731b262
  1. 10
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 11
      ICSharpCode.Decompiler/CSharp/Transforms/ConvertConstructorCallIntoInitializer.cs
  3. 114
      ILSpy/Languages/CSharpLanguage.cs

10
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -345,11 +345,19 @@ namespace ICSharpCode.Decompiler.CSharp
RunTransforms(syntaxTree, decompilationContext); RunTransforms(syntaxTree, decompilationContext);
return syntaxTree; return syntaxTree;
} }
/// <summary> /// <summary>
/// Decompile the specified types and/or members. /// Decompile the specified types and/or members.
/// </summary> /// </summary>
public SyntaxTree Decompile(params IMemberDefinition[] definitions) public SyntaxTree Decompile(params IMemberDefinition[] definitions)
{
return Decompile((IList<IMemberDefinition>)definitions);
}
/// <summary>
/// Decompile the specified types and/or members.
/// </summary>
public SyntaxTree Decompile(IList<IMemberDefinition> definitions)
{ {
if (definitions == null) if (definitions == null)
throw new ArgumentNullException(nameof(definitions)); throw new ArgumentNullException(nameof(definitions));

11
ICSharpCode.Decompiler/CSharp/Transforms/ConvertConstructorCallIntoInitializer.cs

@ -41,6 +41,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
visitor.HandleStaticFieldInitializers(node.Children); visitor.HandleStaticFieldInitializers(node.Children);
node.AcceptVisitor(visitor); node.AcceptVisitor(visitor);
visitor.RemoveSingleEmptyConstructor(node.Children, context.DecompiledTypeDefinition);
} }
} }
@ -103,7 +105,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
base.VisitTypeDeclaration(typeDeclaration); base.VisitTypeDeclaration(typeDeclaration);
// Remove single empty constructor: // Remove single empty constructor:
RemoveSingleEmptyConstructor(typeDeclaration); RemoveSingleEmptyConstructor(typeDeclaration.Members, (ITypeDefinition)typeDeclaration.GetSymbol());
// Handle initializers on static fields: // Handle initializers on static fields:
HandleStaticFieldInitializers(typeDeclaration.Members); HandleStaticFieldInitializers(typeDeclaration.Members);
@ -155,12 +157,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
} }
} }
void RemoveSingleEmptyConstructor(TypeDeclaration typeDeclaration) internal void RemoveSingleEmptyConstructor(IEnumerable<AstNode> members, ITypeDefinition contextTypeDefinition)
{ {
var instanceCtors = typeDeclaration.Members.OfType<ConstructorDeclaration>().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray(); if (contextTypeDefinition == null) return;
var instanceCtors = members.OfType<ConstructorDeclaration>().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray();
if (instanceCtors.Length == 1) { if (instanceCtors.Length == 1) {
ConstructorDeclaration emptyCtor = new ConstructorDeclaration(); ConstructorDeclaration emptyCtor = new ConstructorDeclaration();
emptyCtor.Modifiers = ((typeDeclaration.Modifiers & Modifiers.Abstract) == Modifiers.Abstract ? Modifiers.Protected : Modifiers.Public); emptyCtor.Modifiers = contextTypeDefinition.IsAbstract ? Modifiers.Protected : Modifiers.Public;
emptyCtor.Body = new BlockStatement(); emptyCtor.Body = new BlockStatement();
if (emptyCtor.IsMatch(instanceCtors[0])) if (emptyCtor.IsMatch(instanceCtors[0]))
instanceCtors[0].Remove(); instanceCtors[0].Remove();

114
ILSpy/Languages/CSharpLanguage.cs

@ -34,6 +34,7 @@ using ICSharpCode.Decompiler.TypeSystem;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.Decompiler.CSharp.Transforms;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {
@ -108,36 +109,31 @@ namespace ICSharpCode.ILSpy
AddReferenceWarningMessage(method.Module.Assembly, output); AddReferenceWarningMessage(method.Module.Assembly, output);
WriteCommentLine(output, TypeToString(method.DeclaringType, includeNamespace: true)); WriteCommentLine(output, TypeToString(method.DeclaringType, includeNamespace: true));
CSharpDecompiler decompiler = CreateDecompiler(method.Module, options); CSharpDecompiler decompiler = CreateDecompiler(method.Module, options);
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(method), decompiler.TypeSystem); if (method.IsConstructor && !method.DeclaringType.IsValueType) {
/* List<IMemberDefinition> members = CollectFieldsAndCtors(method.DeclaringType, method.IsStatic);
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: method.DeclaringType, isSingleMember: true); decompiler.AstTransforms.Add(new SelectCtorTransform(decompiler.TypeSystem.Resolve(method)));
if (method.IsConstructor && !method.IsStatic && !method.DeclaringType.IsValueType) { WriteCode(output, options.DecompilerSettings, decompiler.Decompile(members), decompiler.TypeSystem);
// also fields and other ctors so that the field initializers can be shown as such
AddFieldsAndCtors(codeDomBuilder, method.DeclaringType, method.IsStatic);
RunTransformsAndGenerateCode(codeDomBuilder, output, options, new SelectCtorTransform(method));
} else { } else {
codeDomBuilder.AddMethod(method); WriteCode(output, options.DecompilerSettings, decompiler.Decompile(method), decompiler.TypeSystem);
RunTransformsAndGenerateCode(codeDomBuilder, output, options); }
}*/
} }
/*
class SelectCtorTransform : IAstTransform class SelectCtorTransform : IAstTransform
{ {
readonly MethodDefinition ctorDef; readonly IMethod ctor;
public SelectCtorTransform(MethodDefinition ctorDef) public SelectCtorTransform(IMethod ctor)
{ {
this.ctorDef = ctorDef; this.ctor = ctor;
} }
public void Run(AstNode compilationUnit) public void Run(AstNode rootNode, TransformContext context)
{ {
ConstructorDeclaration ctorDecl = null; ConstructorDeclaration ctorDecl = null;
foreach (var node in compilationUnit.Children) { foreach (var node in rootNode.Children) {
ConstructorDeclaration ctor = node as ConstructorDeclaration; ConstructorDeclaration ctor = node as ConstructorDeclaration;
if (ctor != null) { if (ctor != null) {
if (ctor.Annotation<MethodDefinition>() == ctorDef) { if (ctor.GetSymbol() == this.ctor) {
ctorDecl = ctor; ctorDecl = ctor;
} else { } else {
// remove other ctors // remove other ctors
@ -149,15 +145,14 @@ namespace ICSharpCode.ILSpy
if (fd != null && fd.Variables.All(v => v.Initializer.IsNull)) if (fd != null && fd.Variables.All(v => v.Initializer.IsNull))
fd.Remove(); fd.Remove();
} }
if (ctorDecl.Initializer.ConstructorInitializerType == ConstructorInitializerType.This) { if (ctorDecl?.Initializer.ConstructorInitializerType == ConstructorInitializerType.This) {
// remove all fields // remove all fields
foreach (var node in compilationUnit.Children) foreach (var node in rootNode.Children)
if (node is FieldDeclaration) if (node is FieldDeclaration)
node.Remove(); node.Remove();
} }
} }
} }
*/
public override void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options) public override void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options)
{ {
@ -166,56 +161,59 @@ namespace ICSharpCode.ILSpy
CSharpDecompiler decompiler = CreateDecompiler(property.Module, options); CSharpDecompiler decompiler = CreateDecompiler(property.Module, options);
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(property), decompiler.TypeSystem); WriteCode(output, options.DecompilerSettings, decompiler.Decompile(property), decompiler.TypeSystem);
} }
/*
public override void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options) public override void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options)
{ {
AddReferenceWarningMessage(output); AddReferenceWarningMessage(field.Module.Assembly, output);
WriteCommentLine(output, TypeToString(field.DeclaringType, includeNamespace: true)); WriteCommentLine(output, TypeToString(field.DeclaringType, includeNamespace: true));
AstBuilder codeDomBuilder = CreateAstBuilder(options, currentType: field.DeclaringType, isSingleMember: true); CSharpDecompiler decompiler = CreateDecompiler(field.Module, options);
if (field.IsLiteral) { if (field.IsLiteral) {
codeDomBuilder.AddField(field); WriteCode(output, options.DecompilerSettings, decompiler.Decompile(field), decompiler.TypeSystem);
} else { } else {
// also decompile ctors so that the field initializer can be shown List<IMemberDefinition> members = CollectFieldsAndCtors(field.DeclaringType, field.IsStatic);
AddFieldsAndCtors(codeDomBuilder, field.DeclaringType, field.IsStatic); decompiler.AstTransforms.Add(new SelectFieldTransform(decompiler.TypeSystem.Resolve(field)));
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(members), decompiler.TypeSystem);
} }
RunTransformsAndGenerateCode(codeDomBuilder, output, options, new SelectFieldTransform(field));
} }
private static List<IMemberDefinition> CollectFieldsAndCtors(TypeDefinition type, bool isStatic)
{
var members = new List<IMemberDefinition>();
foreach (var field in type.Fields) {
if (field.IsStatic == isStatic)
members.Add(field);
}
foreach (var ctor in type.Methods) {
if (ctor.IsConstructor && ctor.IsStatic == isStatic)
members.Add(ctor);
}
return members;
}
/// <summary> /// <summary>
/// Removes all top-level members except for the specified fields. /// Removes all top-level members except for the specified fields.
/// </summary> /// </summary>
sealed class SelectFieldTransform : IAstTransform sealed class SelectFieldTransform : IAstTransform
{ {
readonly FieldDefinition field; readonly IField field;
public SelectFieldTransform(FieldDefinition field) public SelectFieldTransform(IField field)
{ {
this.field = field; this.field = field;
} }
public void Run(AstNode compilationUnit) public void Run(AstNode rootNode, TransformContext context)
{ {
foreach (var child in compilationUnit.Children) { foreach (var child in rootNode.Children) {
if (child is EntityDeclaration) { if (child is EntityDeclaration) {
if (child.Annotation<FieldDefinition>() != field) if (child.GetSymbol() != field)
child.Remove(); child.Remove();
} }
} }
} }
} }
void AddFieldsAndCtors(AstBuilder codeDomBuilder, TypeDefinition declaringType, bool isStatic)
{
foreach (var field in declaringType.Fields) {
if (field.IsStatic == isStatic)
codeDomBuilder.AddField(field);
}
foreach (var ctor in declaringType.Methods) {
if (ctor.IsConstructor && ctor.IsStatic == isStatic)
codeDomBuilder.AddMethod(ctor);
}
}
*/
public override void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options) public override void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options)
{ {
AddReferenceWarningMessage(ev.Module.Assembly, output); AddReferenceWarningMessage(ev.Module.Assembly, output);
@ -232,26 +230,6 @@ namespace ICSharpCode.ILSpy
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(type), decompiler.TypeSystem); WriteCode(output, options.DecompilerSettings, decompiler.Decompile(type), decompiler.TypeSystem);
} }
/*
void RunTransformsAndGenerateCode(AstBuilder astBuilder, ITextOutput output, DecompilationOptions options, IAstTransform additionalTransform = null)
{
astBuilder.RunTransformations(transformAbortCondition);
if (additionalTransform != null) {
additionalTransform.Run(astBuilder.SyntaxTree);
}
if (options.DecompilerSettings.ShowXmlDocumentation) {
try {
AddXmlDocTransform.Run(astBuilder.SyntaxTree);
} catch (XmlException ex) {
string[] msg = (" Exception while reading XmlDoc: " + ex.ToString()).Split(new[]{'\r', '\n'}, StringSplitOptions.RemoveEmptyEntries);
var insertionPoint = astBuilder.SyntaxTree.FirstChild;
for (int i = 0; i < msg.Length; i++)
astBuilder.SyntaxTree.InsertChildBefore(insertionPoint, new Comment(msg[i], CommentType.Documentation), Roles.Comment);
}
}
astBuilder.GenerateCode(output);
}*/
public static string GetPlatformDisplayName(ModuleDefinition module) public static string GetPlatformDisplayName(ModuleDefinition module)
{ {
switch (module.Architecture) { switch (module.Architecture) {

Loading…
Cancel
Save