Browse Source

Add NormalizeBlockStatements transform

pull/976/head
Siegfried Pammer 8 years ago
parent
commit
ab70795a52
  1. 9
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs
  2. 1
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  3. 110
      ICSharpCode.Decompiler/CSharp/Transforms/NormalizeBlockStatements.cs
  4. 15
      ICSharpCode.Decompiler/DecompilerSettings.cs
  5. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  6. 1
      ILSpy/Options/DecompilerSettingsPanel.xaml
  7. 2
      ILSpy/Options/DecompilerSettingsPanel.xaml.cs

9
ICSharpCode.Decompiler.Tests/TestCases/Pretty/Loops.cs

@ -379,8 +379,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -379,8 +379,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
} finally {
IDisposable disposable = enumerator as IDisposable;
if (disposable != null)
if (disposable != null) {
disposable.Dispose();
}
}
Console.WriteLine("After finally!");
}
@ -527,8 +528,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -527,8 +528,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
if (this.Condition("continue")) {
continue;
}
if (!this.Condition("break"))
if (!this.Condition("break")) {
break;
}
}
Console.WriteLine("End of loop body");
}
@ -582,8 +584,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -582,8 +584,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
if (this.Condition("continue")) {
continue;
}
if (!this.Condition("not-break"))
if (!this.Condition("not-break")) {
break;
}
}
Console.WriteLine("End of loop body");
}

1
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -152,6 +152,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -152,6 +152,7 @@ namespace ICSharpCode.Decompiler.CSharp
new IntroduceExtensionMethods(), // must run after IntroduceUsingDeclarations
new IntroduceQueryExpressions(), // must run after IntroduceExtensionMethods
new CombineQueryExpressions(),
new NormalizeBlockStatements(),
new FlattenSwitchBlocks(),
new FixNameCollisions(),
new AddXmlDocumentationTransform(),

110
ICSharpCode.Decompiler/CSharp/Transforms/NormalizeBlockStatements.cs

@ -0,0 +1,110 @@ @@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ICSharpCode.Decompiler.CSharp.Syntax;
namespace ICSharpCode.Decompiler.CSharp.Transforms
{
class NormalizeBlockStatements : DepthFirstAstVisitor, IAstTransform
{
TransformContext context;
public override void VisitIfElseStatement(IfElseStatement ifElseStatement)
{
base.VisitIfElseStatement(ifElseStatement);
DoTransform(ifElseStatement.TrueStatement, ifElseStatement);
DoTransform(ifElseStatement.FalseStatement, ifElseStatement);
}
public override void VisitWhileStatement(WhileStatement whileStatement)
{
base.VisitWhileStatement(whileStatement);
InsertBlock(whileStatement.EmbeddedStatement);
}
public override void VisitDoWhileStatement(DoWhileStatement doWhileStatement)
{
base.VisitDoWhileStatement(doWhileStatement);
InsertBlock(doWhileStatement.EmbeddedStatement);
}
public override void VisitForeachStatement(ForeachStatement foreachStatement)
{
base.VisitForeachStatement(foreachStatement);
InsertBlock(foreachStatement.EmbeddedStatement);
}
public override void VisitForStatement(ForStatement forStatement)
{
base.VisitForStatement(forStatement);
InsertBlock(forStatement.EmbeddedStatement);
}
public override void VisitFixedStatement(FixedStatement fixedStatement)
{
base.VisitFixedStatement(fixedStatement);
InsertBlock(fixedStatement.EmbeddedStatement);
}
public override void VisitLockStatement(LockStatement lockStatement)
{
base.VisitLockStatement(lockStatement);
InsertBlock(lockStatement.EmbeddedStatement);
}
public override void VisitUsingStatement(UsingStatement usingStatement)
{
base.VisitUsingStatement(usingStatement);
DoTransform(usingStatement.EmbeddedStatement, usingStatement);
}
void DoTransform(Statement statement, Statement parent)
{
if (statement.IsNull) return;
if (context.Settings.AlwaysUseBraces) {
InsertBlock(statement);
} else {
if (statement is BlockStatement b && b.Statements.Count == 1 && IsAllowed(b.Statements.First(), parent)) {
statement.ReplaceWith(b.Statements.First().Detach());
}
}
}
static void InsertBlock(Statement statement)
{
if (statement.IsNull) return;
if (!(statement is BlockStatement)) {
var b = new BlockStatement();
statement.ReplaceWith(b);
b.Add(statement);
}
}
bool IsAllowed(Statement statement, Statement parent)
{
switch (statement) {
case VariableDeclarationStatement vds:
case IfElseStatement ies:
case WhileStatement ws:
case DoWhileStatement dws:
case SwitchStatement ss:
case ForeachStatement fes:
case ForStatement fs:
case LockStatement ls:
case FixedStatement fxs:
return false;
case UsingStatement us:
return parent is UsingStatement;
default:
return true;
}
}
void IAstTransform.Run(AstNode rootNode, TransformContext context)
{
this.context = context;
rootNode.AcceptVisitor(this);
}
}
}

15
ICSharpCode.Decompiler/DecompilerSettings.cs

@ -178,6 +178,21 @@ namespace ICSharpCode.Decompiler @@ -178,6 +178,21 @@ namespace ICSharpCode.Decompiler
}
}
bool alwaysUseBraces = true;
/// <summary>
/// Gets/Sets whether to use braces for single-statement-blocks.
/// </summary>
public bool AlwaysUseBraces {
get { return alwaysUseBraces; }
set {
if (alwaysUseBraces != value) {
alwaysUseBraces = value;
OnPropertyChanged();
}
}
}
bool forEachStatement = true;
/// <summary>

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -230,6 +230,7 @@ @@ -230,6 +230,7 @@
<Compile Include="CSharp\Transforms\FlattenSwitchBlocks.cs" />
<Compile Include="CSharp\Transforms\IntroduceExtensionMethods.cs" />
<Compile Include="CSharp\Transforms\IntroduceQueryExpressions.cs" />
<Compile Include="CSharp\Transforms\NormalizeBlockStatements.cs" />
<Compile Include="CSharp\Transforms\PrettifyAssignments.cs" />
<Compile Include="CSharp\Transforms\RemoveCLSCompliantAttribute.cs" />
<Compile Include="CSharp\TranslationContext.cs" />

1
ILSpy/Options/DecompilerSettingsPanel.xaml

@ -17,5 +17,6 @@ @@ -17,5 +17,6 @@
<CheckBox IsChecked="{Binding RemoveDeadCode}">Remove dead and side effect free code</CheckBox>
<CheckBox IsChecked="{Binding UsingDeclarations}">Insert using declarations</CheckBox>
<CheckBox IsChecked="{Binding FullyQualifyAmbiguousTypeNames}">Fully qualify ambiguous type names</CheckBox>
<CheckBox IsChecked="{Binding AlwaysUseBraces}">Always use braces</CheckBox>
</StackPanel>
</UserControl>

2
ILSpy/Options/DecompilerSettingsPanel.xaml.cs

@ -63,6 +63,7 @@ namespace ICSharpCode.ILSpy.Options @@ -63,6 +63,7 @@ namespace ICSharpCode.ILSpy.Options
s.FoldBraces = (bool?)e.Attribute("foldBraces") ?? s.FoldBraces;
s.UsingDeclarations = (bool?)e.Attribute("usingDeclarations") ?? s.UsingDeclarations;
s.FullyQualifyAmbiguousTypeNames = (bool?)e.Attribute("fullyQualifyAmbiguousTypeNames") ?? s.FullyQualifyAmbiguousTypeNames;
s.AlwaysUseBraces = (bool?)e.Attribute("alwaysUseBraces") ?? s.AlwaysUseBraces;
return s;
}
@ -84,6 +85,7 @@ namespace ICSharpCode.ILSpy.Options @@ -84,6 +85,7 @@ namespace ICSharpCode.ILSpy.Options
section.SetAttributeValue("foldBraces", s.RemoveDeadCode);
section.SetAttributeValue("usingDeclarations", s.UsingDeclarations);
section.SetAttributeValue("fullyQualifyAmbiguousTypeNames", s.FullyQualifyAmbiguousTypeNames);
section.SetAttributeValue("alwaysUseBraces", s.AlwaysUseBraces);
XElement existingElement = root.Element("DecompilerSettings");
if (existingElement != null)

Loading…
Cancel
Save