From 78a2f904c2cced918c1888fcf2d213a81f8c2839 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Tue, 15 Feb 2011 15:16:51 +0100 Subject: [PATCH] In debug builds, make intermediate transform steps available as "language". --- ICSharpCode.Decompiler/Ast/AstBuilder.cs | 7 +++- .../Ast/Transforms/DelegateConstruction.cs | 14 +------ .../Ast/Transforms/TransformationPipeline.cs | 6 +-- ICSharpCode.Decompiler/CecilExtensions.cs | 11 ++++++ ILSpy/CSharpLanguage.cs | 39 ++++++++++++++++--- ILSpy/Language.cs | 8 +++- 6 files changed, 61 insertions(+), 24 deletions(-) diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs index 8dd99fc51..f1d9fb827 100644 --- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs @@ -17,7 +17,12 @@ namespace Decompiler public void GenerateCode(ITextOutput output) { - Transforms.TransformationPipeline.RunTransformations(astCompileUnit); + GenerateCode(output, null); + } + + public void GenerateCode(ITextOutput output, Predicate> transformAbortCondition) + { + Transforms.TransformationPipeline.RunTransformationsUntil(astCompileUnit, transformAbortCondition); astCompileUnit.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true }, null); var outputFormatter = new TextOutputFormatter(output); diff --git a/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs b/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs index 245df79a1..4f3786120 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using ICSharpCode.Decompiler; using ICSharpCode.NRefactory.CSharp; using Mono.Cecil; @@ -93,7 +94,7 @@ namespace Decompiler.Transforms MethodDefinition method = methodRef as MethodDefinition; if (method == null || !method.Name.StartsWith("<", StringComparison.Ordinal)) return false; - if (!(IsCompilerGenerated(method) || IsCompilerGenerated(method.DeclaringType))) + if (!(method.IsCompilerGenerated() || method.DeclaringType.IsCompilerGenerated())) return false; TypeDefinition methodContainingType = method.DeclaringType; // check that methodContainingType is within containingType @@ -125,16 +126,5 @@ namespace Decompiler.Transforms objectCreateExpression.ReplaceWith(ame); return true; } - - bool IsCompilerGenerated(ICustomAttributeProvider provider) - { - if (provider.HasCustomAttributes) { - foreach (CustomAttribute a in provider.CustomAttributes) { - if (a.AttributeType.FullName == "System.Runtime.CompilerServices.CompilerGeneratedAttribute") - return true; - } - } - return false; - } } } diff --git a/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs b/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs index c11418dc3..8c2d5b235 100644 --- a/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs +++ b/ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs @@ -8,7 +8,7 @@ namespace Decompiler.Transforms { public static class TransformationPipeline { - static IAstVisitor[] CreatePipeline() + public static IAstVisitor[] CreatePipeline() { return new IAstVisitor[] { new DelegateConstruction(), @@ -19,7 +19,7 @@ namespace Decompiler.Transforms public static void RunTransformations(AstNode node) { - RunTransformationsUntil(node, v => false); + RunTransformationsUntil(node, null); } public static void RunTransformationsUntil(AstNode node, Predicate> abortCondition) @@ -41,7 +41,7 @@ namespace Decompiler.Transforms } foreach (var visitor in CreatePipeline()) { - if (abortCondition(visitor)) + if (abortCondition != null && abortCondition(visitor)) return; node.AcceptVisitor(visitor, null); } diff --git a/ICSharpCode.Decompiler/CecilExtensions.cs b/ICSharpCode.Decompiler/CecilExtensions.cs index 4c17373ec..a97ed2427 100644 --- a/ICSharpCode.Decompiler/CecilExtensions.cs +++ b/ICSharpCode.Decompiler/CecilExtensions.cs @@ -158,5 +158,16 @@ namespace ICSharpCode.Decompiler } return accessorMethods; } + + public static bool IsCompilerGenerated(this ICustomAttributeProvider provider) + { + if (provider.HasCustomAttributes) { + foreach (CustomAttribute a in provider.CustomAttributes) { + if (a.AttributeType.FullName == "System.Runtime.CompilerServices.CompilerGeneratedAttribute") + return true; + } + } + return false; + } } } diff --git a/ILSpy/CSharpLanguage.cs b/ILSpy/CSharpLanguage.cs index 5fdf8ea58..3368f1594 100644 --- a/ILSpy/CSharpLanguage.cs +++ b/ILSpy/CSharpLanguage.cs @@ -17,9 +17,11 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Generic; using System.IO; using System.Linq; using Decompiler; +using Decompiler.Transforms; using ICSharpCode.Decompiler; using ICSharpCode.NRefactory.CSharp; using Mono.Cecil; @@ -31,8 +33,33 @@ namespace ICSharpCode.ILSpy /// public class CSharpLanguage : Language { + string name = "C#"; + Predicate> transformAbortCondition; + + public CSharpLanguage() + { + } + + #if DEBUG + internal static IEnumerable GetDebugLanguages() + { + string lastTransformName = "no transforms"; + foreach (Type _transformType in TransformationPipeline.CreatePipeline().Select(v => v.GetType()).Distinct()) { + Type transformType = _transformType; // copy for lambda + yield return new CSharpLanguage { + transformAbortCondition = v => transformType.IsInstanceOfType(v), + name = "C# - " + lastTransformName + }; + lastTransformName = "after " + transformType.Name; + } + yield return new CSharpLanguage { + name = "C# - " + lastTransformName + }; + } + #endif + public override string Name { - get { return "C#"; } + get { return name; } } public override string FileExtension { @@ -43,35 +70,35 @@ namespace ICSharpCode.ILSpy { AstBuilder codeDomBuilder = new AstBuilder(); codeDomBuilder.AddMethod(method); - codeDomBuilder.GenerateCode(output); + codeDomBuilder.GenerateCode(output, transformAbortCondition); } public override void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options) { AstBuilder codeDomBuilder = new AstBuilder(); codeDomBuilder.AddProperty(property); - codeDomBuilder.GenerateCode(output); + codeDomBuilder.GenerateCode(output, transformAbortCondition); } public override void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options) { AstBuilder codeDomBuilder = new AstBuilder(); codeDomBuilder.AddField(field); - codeDomBuilder.GenerateCode(output); + codeDomBuilder.GenerateCode(output, transformAbortCondition); } public override void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options) { AstBuilder codeDomBuilder = new AstBuilder(); codeDomBuilder.AddEvent(ev); - codeDomBuilder.GenerateCode(output); + codeDomBuilder.GenerateCode(output, transformAbortCondition); } public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options) { AstBuilder codeDomBuilder = new AstBuilder(); codeDomBuilder.AddType(type); - codeDomBuilder.GenerateCode(output); + codeDomBuilder.GenerateCode(output, transformAbortCondition); } public override string TypeToString(TypeReference type, bool includeNamespace, ICustomAttributeProvider typeAttributes) diff --git a/ILSpy/Language.cs b/ILSpy/Language.cs index fe1b34d85..ea4306dc7 100644 --- a/ILSpy/Language.cs +++ b/ILSpy/Language.cs @@ -120,11 +120,15 @@ namespace ICSharpCode.ILSpy /// /// A list of all languages. /// - public static readonly ReadOnlyCollection AllLanguages = Array.AsReadOnly( + public static readonly ReadOnlyCollection AllLanguages = new List( new Language[] { new CSharpLanguage(), new ILLanguage(true) - }); + } + #if DEBUG + .Concat(CSharpLanguage.GetDebugLanguages()) + #endif + ).AsReadOnly(); /// /// Gets a language using its name.