diff --git a/ICSharpCode.Decompiler/Ast/Transforms/ContextTrackingVisitor.cs b/ICSharpCode.Decompiler/Ast/Transforms/ContextTrackingVisitor.cs
index a9b3f3fc6..236b95711 100644
--- a/ICSharpCode.Decompiler/Ast/Transforms/ContextTrackingVisitor.cs
+++ b/ICSharpCode.Decompiler/Ast/Transforms/ContextTrackingVisitor.cs
@@ -11,7 +11,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
///
/// Base class for AST visitors that need the current type/method context info.
///
- public abstract class ContextTrackingVisitor : DepthFirstAstVisitor, IAstTransform
+ public abstract class ContextTrackingVisitor : DepthFirstAstVisitor, IAstTransform
{
protected readonly DecompilerContext context;
@@ -22,7 +22,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
this.context = context;
}
- public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data)
+ public override TResult VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data)
{
TypeDefinition oldType = context.CurrentType;
try {
@@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}
}
- public override object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data)
+ public override TResult VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data)
{
Debug.Assert(context.CurrentMethod == null);
try {
@@ -44,7 +44,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}
}
- public override object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data)
+ public override TResult VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data)
{
Debug.Assert(context.CurrentMethod == null);
try {
@@ -55,7 +55,29 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}
}
- public override object VisitAccessor(Accessor accessor, object data)
+ public override TResult VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration, object data)
+ {
+ Debug.Assert(context.CurrentMethod == null);
+ try {
+ context.CurrentMethod = destructorDeclaration.Annotation();
+ return base.VisitDestructorDeclaration(destructorDeclaration, data);
+ } finally {
+ context.CurrentMethod = null;
+ }
+ }
+
+ public override TResult VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data)
+ {
+ Debug.Assert(context.CurrentMethod == null);
+ try {
+ context.CurrentMethod = operatorDeclaration.Annotation();
+ return base.VisitOperatorDeclaration(operatorDeclaration, data);
+ } finally {
+ context.CurrentMethod = null;
+ }
+ }
+
+ public override TResult VisitAccessor(Accessor accessor, object data)
{
Debug.Assert(context.CurrentMethod == null);
try {
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs b/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
index c44200bf3..6eb8f4d98 100644
--- a/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
+++ b/ICSharpCode.Decompiler/Ast/Transforms/DelegateConstruction.cs
@@ -18,7 +18,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
/// For anonymous methods, creates an AnonymousMethodExpression.
/// Also gets rid of any "Display Classes" left over after inlining an anonymous method.
///
- public class DelegateConstruction : ContextTrackingVisitor
+ public class DelegateConstruction : ContextTrackingVisitor
{
internal sealed class Annotation
{
diff --git a/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs b/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs
index cb9581624..e2d6536d3 100644
--- a/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs
+++ b/ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Linq;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.PatternMatching;
@@ -13,38 +14,106 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
///
/// Finds the expanded form of using statements using pattern matching and replaces it with a UsingStatement.
///
- public class PatternStatementTransform : IAstTransform
+ public sealed class PatternStatementTransform : ContextTrackingVisitor, IAstTransform
{
- DecompilerContext context;
+ public PatternStatementTransform(DecompilerContext context) : base(context)
+ {
+ }
- public PatternStatementTransform(DecompilerContext context)
+ #region Visitor Overrides
+ protected override AstNode VisitChildren(AstNode node, object data)
{
- if (context == null)
- throw new ArgumentNullException("context");
- this.context = context;
+ // Go through the children, and keep visiting a node as long as it changes.
+ // Because some transforms delete/replace nodes before and after the node being transformed, we rely
+ // on the transform's return value to know where we need to keep iterating.
+ for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
+ AstNode oldChild;
+ do {
+ oldChild = child;
+ child = child.AcceptVisitor(this, data);
+ Debug.Assert(child != null && child.Parent == node);
+ } while (child != oldChild);
+ }
+ return node;
}
- public void Run(AstNode compilationUnit)
+ public override AstNode VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement, object data)
{
- if (context.Settings.UsingStatement)
- TransformUsings(compilationUnit);
- if (context.Settings.ForEachStatement)
- TransformForeach(compilationUnit);
- TransformFor(compilationUnit);
- TransformDoWhile(compilationUnit);
- if (context.Settings.LockStatement)
- TransformLock(compilationUnit);
- if (context.Settings.SwitchStatementOnString)
- TransformSwitchOnString(compilationUnit);
- if (context.Settings.AutomaticProperties)
- TransformAutomaticProperties(compilationUnit);
- if (context.Settings.AutomaticEvents)
- TransformAutomaticEvents(compilationUnit);
-
- TransformDestructor(compilationUnit);
- TransformTryCatchFinally(compilationUnit);
+ AstNode result;
+ if (context.Settings.UsingStatement) {
+ result = TransformUsings(variableDeclarationStatement);
+ if (result != null)
+ return result;
+ }
+ result = TransformFor(variableDeclarationStatement);
+ if (result != null)
+ return result;
+ if (context.Settings.LockStatement) {
+ result = TransformLock(variableDeclarationStatement);
+ if (result != null)
+ return result;
+ }
+ return base.VisitVariableDeclarationStatement(variableDeclarationStatement, data);
+ }
+
+ public override AstNode VisitUsingStatement(UsingStatement usingStatement, object data)
+ {
+ if (context.Settings.ForEachStatement) {
+ AstNode result = TransformForeach(usingStatement);
+ if (result != null)
+ return result;
+ }
+ return base.VisitUsingStatement(usingStatement, data);
+ }
+
+ public override AstNode VisitWhileStatement(WhileStatement whileStatement, object data)
+ {
+ return TransformDoWhile(whileStatement) ?? base.VisitWhileStatement(whileStatement, data);
+ }
+
+ public override AstNode VisitIfElseStatement(IfElseStatement ifElseStatement, object data)
+ {
+ if (context.Settings.SwitchStatementOnString) {
+ AstNode result = TransformSwitchOnString(ifElseStatement);
+ if (result != null)
+ return result;
+ }
+ return base.VisitIfElseStatement(ifElseStatement, data);
+ }
+
+ public override AstNode VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data)
+ {
+ if (context.Settings.AutomaticProperties) {
+ AstNode result = TransformAutomaticProperties(propertyDeclaration);
+ if (result != null)
+ return result;
+ }
+ return base.VisitPropertyDeclaration(propertyDeclaration, data);
+ }
+
+ public override AstNode VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration, object data)
+ {
+ // first apply transforms to the accessor bodies
+ base.VisitCustomEventDeclaration(eventDeclaration, data);
+ if (context.Settings.AutomaticEvents) {
+ AstNode result = TransformAutomaticEvents(eventDeclaration);
+ if (result != null)
+ return result;
+ }
+ return eventDeclaration;
+ }
+
+ public override AstNode VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data)
+ {
+ return TransformDestructor(methodDeclaration) ?? base.VisitMethodDeclaration(methodDeclaration, data);
}
+ public override AstNode VisitTryCatchStatement(TryCatchStatement tryCatchStatement, object data)
+ {
+ return TransformTryCatchFinally(tryCatchStatement) ?? base.VisitTryCatchStatement(tryCatchStatement, data);
+ }
+ #endregion
+
///
/// $type $variable = $initializer;
///
@@ -94,31 +163,30 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}
};
- public void TransformUsings(AstNode compilationUnit)
+ public UsingStatement TransformUsings(VariableDeclarationStatement node)
{
- foreach (AstNode node in compilationUnit.Descendants.OfType().ToArray()) {
- Match m1 = variableDeclPattern.Match(node);
- if (m1 == null) continue;
- AstNode tryCatch = node.NextSibling;
- while (simpleVariableDefinition.Match(tryCatch) != null)
- tryCatch = tryCatch.NextSibling;
- Match m2 = usingTryCatchPattern.Match(tryCatch);
- if (m2 == null) continue;
- if (m1.Get("variable").Single().Name == m2.Get("ident").Single().Identifier) {
- if (m2.Has("valueType")) {
- // if there's no if(x!=null), then it must be a value type
- TypeReference tr = m1.Get("type").Single().Annotation();
- if (tr == null || !tr.IsValueType)
- continue;
- }
- BlockStatement body = m2.Get("body").Single();
- tryCatch.ReplaceWith(
- new UsingStatement {
- ResourceAcquisition = node.Detach(),
- EmbeddedStatement = body.Detach()
- });
+ Match m1 = variableDeclPattern.Match(node);
+ if (m1 == null) return null;
+ AstNode tryCatch = node.NextSibling;
+ while (simpleVariableDefinition.Match(tryCatch) != null)
+ tryCatch = tryCatch.NextSibling;
+ Match m2 = usingTryCatchPattern.Match(tryCatch);
+ if (m2 == null) return null;
+ if (m1.Get("variable").Single().Name == m2.Get("ident").Single().Identifier) {
+ if (m2.Has("valueType")) {
+ // if there's no if(x!=null), then it must be a value type
+ TypeReference tr = m1.Get("type").Single().Annotation();
+ if (tr == null || !tr.IsValueType)
+ return null;
}
+ BlockStatement body = m2.Get("body").Single();
+ UsingStatement usingStatement = new UsingStatement();
+ usingStatement.ResourceAcquisition = node.Detach();
+ usingStatement.EmbeddedStatement = body.Detach();
+ tryCatch.ReplaceWith(usingStatement);
+ return usingStatement;
}
+ return null;
}
#endregion
@@ -185,29 +253,28 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}.ToStatement()
};
- public void TransformForeach(AstNode compilationUnit)
+ public ForeachStatement TransformForeach(UsingStatement node)
{
- foreach (AstNode node in compilationUnit.Descendants.OfType().ToArray()) {
- Match m = foreachPattern.Match(node);
- if (m == null)
- continue;
- VariableInitializer enumeratorVar = m.Get("enumeratorVariable").Single();
- VariableInitializer itemVar = m.Get("itemVariable").Single();
- if (m.Has("itemVariableInsideLoop") && itemVar.Annotation() != null) {
- // cannot move captured variables out of loops
- continue;
- }
- BlockStatement newBody = new BlockStatement();
- foreach (Statement stmt in m.Get("statement"))
- newBody.Add(stmt.Detach());
- node.ReplaceWith(
- new ForeachStatement {
- VariableType = m.Get("itemType").Single().Detach(),
- VariableName = itemVar.Name,
- InExpression = m.Get("collection").Single().Detach(),
- EmbeddedStatement = newBody
- });
+ Match m = foreachPattern.Match(node);
+ if (m == null)
+ return null;
+ VariableInitializer enumeratorVar = m.Get("enumeratorVariable").Single();
+ VariableInitializer itemVar = m.Get("itemVariable").Single();
+ if (m.Has("itemVariableInsideLoop") && itemVar.Annotation() != null) {
+ // cannot move captured variables out of loops
+ return null;
}
+ BlockStatement newBody = new BlockStatement();
+ foreach (Statement stmt in m.Get("statement"))
+ newBody.Add(stmt.Detach());
+ ForeachStatement foreachStatement = new ForeachStatement {
+ VariableType = m.Get("itemType").Single().Detach(),
+ VariableName = itemVar.Name,
+ InExpression = m.Get("collection").Single().Detach(),
+ EmbeddedStatement = newBody
+ };
+ node.ReplaceWith(foreachStatement);
+ return foreachStatement;
}
#endregion
@@ -232,32 +299,30 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}
}};
- public void TransformFor(AstNode compilationUnit)
+ public ForStatement TransformFor(VariableDeclarationStatement node)
{
- foreach (AstNode node in compilationUnit.Descendants.OfType().ToArray()) {
- Match m1 = variableDeclPattern.Match(node);
- if (m1 == null) continue;
- AstNode next = node.NextSibling;
- while (simpleVariableDefinition.Match(next) != null)
- next = next.NextSibling;
- Match m2 = forPattern.Match(next);
- if (m2 == null) continue;
- // ensure the variable in the for pattern is the same as in the declaration
- if (m1.Get("variable").Single().Name != m2.Get("ident").Single().Identifier)
- continue;
- WhileStatement loop = (WhileStatement)next;
- node.Remove();
- BlockStatement newBody = new BlockStatement();
- foreach (Statement stmt in m2.Get("statement"))
- newBody.Add(stmt.Detach());
- loop.ReplaceWith(
- new ForStatement {
- Initializers = { (VariableDeclarationStatement)node },
- Condition = loop.Condition.Detach(),
- Iterators = { m2.Get("increment").Single().Detach() },
- EmbeddedStatement = newBody
- });
- }
+ Match m1 = variableDeclPattern.Match(node);
+ if (m1 == null) return null;
+ AstNode next = node.NextSibling;
+ while (simpleVariableDefinition.Match(next) != null)
+ next = next.NextSibling;
+ Match m2 = forPattern.Match(next);
+ if (m2 == null) return null;
+ // ensure the variable in the for pattern is the same as in the declaration
+ if (m1.Get("variable").Single().Name != m2.Get("ident").Single().Identifier)
+ return null;
+ WhileStatement loop = (WhileStatement)next;
+ node.Remove();
+ BlockStatement newBody = new BlockStatement();
+ foreach (Statement stmt in m2.Get("statement"))
+ newBody.Add(stmt.Detach());
+ ForStatement forStatement = new ForStatement();
+ forStatement.Initializers.Add(node);
+ forStatement.Condition = loop.Condition.Detach();
+ forStatement.Iterators.Add(m2.Get("increment").Single().Detach());
+ forStatement.EmbeddedStatement = newBody;
+ loop.ReplaceWith(forStatement);
+ return forStatement;
}
#endregion
@@ -274,37 +339,37 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}
}};
- public void TransformDoWhile(AstNode compilationUnit)
+ public DoWhileStatement TransformDoWhile(WhileStatement whileLoop)
{
- foreach (WhileStatement whileLoop in compilationUnit.Descendants.OfType().ToArray()) {
- Match m = doWhilePattern.Match(whileLoop);
- if (m != null) {
- DoWhileStatement doLoop = new DoWhileStatement();
- doLoop.Condition = new UnaryOperatorExpression(UnaryOperatorType.Not, m.Get("condition").Single().Detach());
- doLoop.Condition.AcceptVisitor(new PushNegation(), null);
- BlockStatement block = (BlockStatement)whileLoop.EmbeddedStatement;
- block.Statements.Last().Remove(); // remove if statement
- doLoop.EmbeddedStatement = block.Detach();
- whileLoop.ReplaceWith(doLoop);
-
- // we may have to extract variable definitions out of the loop if they were used in the condition:
- foreach (var varDecl in block.Statements.OfType()) {
- VariableInitializer v = varDecl.Variables.Single();
- if (doLoop.Condition.DescendantsAndSelf.OfType().Any(i => i.Identifier == v.Name)) {
- AssignmentExpression assign = new AssignmentExpression(new IdentifierExpression(v.Name), v.Initializer.Detach());
- // move annotations from v to assign:
- assign.CopyAnnotationsFrom(v);
- v.RemoveAnnotations();
- // remove varDecl with assignment; and move annotations from varDecl to the ExpressionStatement:
- varDecl.ReplaceWith(new ExpressionStatement(assign).CopyAnnotationsFrom(varDecl));
- varDecl.RemoveAnnotations();
-
- // insert the varDecl above the do-while loop:
- doLoop.Parent.InsertChildBefore(doLoop, varDecl, BlockStatement.StatementRole);
- }
+ Match m = doWhilePattern.Match(whileLoop);
+ if (m != null) {
+ DoWhileStatement doLoop = new DoWhileStatement();
+ doLoop.Condition = new UnaryOperatorExpression(UnaryOperatorType.Not, m.Get("condition").Single().Detach());
+ doLoop.Condition.AcceptVisitor(new PushNegation(), null);
+ BlockStatement block = (BlockStatement)whileLoop.EmbeddedStatement;
+ block.Statements.Last().Remove(); // remove if statement
+ doLoop.EmbeddedStatement = block.Detach();
+ whileLoop.ReplaceWith(doLoop);
+
+ // we may have to extract variable definitions out of the loop if they were used in the condition:
+ foreach (var varDecl in block.Statements.OfType()) {
+ VariableInitializer v = varDecl.Variables.Single();
+ if (doLoop.Condition.DescendantsAndSelf.OfType().Any(i => i.Identifier == v.Name)) {
+ AssignmentExpression assign = new AssignmentExpression(new IdentifierExpression(v.Name), v.Initializer.Detach());
+ // move annotations from v to assign:
+ assign.CopyAnnotationsFrom(v);
+ v.RemoveAnnotations();
+ // remove varDecl with assignment; and move annotations from varDecl to the ExpressionStatement:
+ varDecl.ReplaceWith(new ExpressionStatement(assign).CopyAnnotationsFrom(varDecl));
+ varDecl.RemoveAnnotations();
+
+ // insert the varDecl above the do-while loop:
+ doLoop.Parent.InsertChildBefore(doLoop, varDecl, BlockStatement.StatementRole);
}
}
+ return doLoop;
}
+ return null;
}
#endregion
@@ -339,49 +404,49 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}
}};
- public void TransformLock(AstNode compilationUnit)
+ public LockStatement TransformLock(VariableDeclarationStatement node)
{
- foreach (AstNode node in compilationUnit.Descendants.OfType().ToArray()) {
- Match m1 = lockFlagInitPattern.Match(node);
- if (m1 == null) continue;
- AstNode tryCatch = node.NextSibling;
- while (simpleVariableDefinition.Match(tryCatch) != null)
- tryCatch = tryCatch.NextSibling;
- Match m2 = lockTryCatchPattern.Match(tryCatch);
- if (m2 == null) continue;
- if (m1.Get("variable").Single().Name == m2.Get("flag").Single().Identifier) {
- Expression enter = m2.Get("enter").Single();
- IdentifierExpression exit = m2.Get("exit").Single();
- if (exit.Match(enter) == null) {
- // If exit and enter are not the same, then enter must be "exit = ..."
- AssignmentExpression assign = enter as AssignmentExpression;
- if (assign == null)
- continue;
- if (exit.Match(assign.Left) == null)
- continue;
- enter = assign.Right;
- // Remove 'exit' variable:
- bool ok = false;
- for (AstNode tmp = node.NextSibling; tmp != tryCatch; tmp = tmp.NextSibling) {
- VariableDeclarationStatement v = (VariableDeclarationStatement)tmp;
- if (v.Variables.Single().Name == exit.Identifier) {
- ok = true;
- v.Remove();
- break;
- }
+ Match m1 = lockFlagInitPattern.Match(node);
+ if (m1 == null) return null;
+ AstNode tryCatch = node.NextSibling;
+ while (simpleVariableDefinition.Match(tryCatch) != null)
+ tryCatch = tryCatch.NextSibling;
+ Match m2 = lockTryCatchPattern.Match(tryCatch);
+ if (m2 == null) return null;
+ if (m1.Get("variable").Single().Name == m2.Get("flag").Single().Identifier) {
+ Expression enter = m2.Get("enter").Single();
+ IdentifierExpression exit = m2.Get("exit").Single();
+ if (exit.Match(enter) == null) {
+ // If exit and enter are not the same, then enter must be "exit = ..."
+ AssignmentExpression assign = enter as AssignmentExpression;
+ if (assign == null)
+ return null;
+ if (exit.Match(assign.Left) == null)
+ return null;
+ enter = assign.Right;
+ // Remove 'exit' variable:
+ bool ok = false;
+ for (AstNode tmp = node.NextSibling; tmp != tryCatch; tmp = tmp.NextSibling) {
+ VariableDeclarationStatement v = (VariableDeclarationStatement)tmp;
+ if (v.Variables.Single().Name == exit.Identifier) {
+ ok = true;
+ v.Remove();
+ break;
}
- if (!ok)
- continue;
}
- // transform the code into a lock statement:
- LockStatement l = new LockStatement();
- l.Expression = enter.Detach();
- l.EmbeddedStatement = ((TryCatchStatement)tryCatch).TryBlock.Detach();
- ((BlockStatement)l.EmbeddedStatement).Statements.First().Remove(); // Remove 'Enter()' call
- tryCatch.ReplaceWith(l);
- node.Remove(); // remove flag variable
+ if (!ok)
+ return null;
}
+ // transform the code into a lock statement:
+ LockStatement l = new LockStatement();
+ l.Expression = enter.Detach();
+ l.EmbeddedStatement = ((TryCatchStatement)tryCatch).TryBlock.Detach();
+ ((BlockStatement)l.EmbeddedStatement).Statements.First().Remove(); // Remove 'Enter()' call
+ tryCatch.ReplaceWith(l);
+ node.Remove(); // remove flag variable
+ return l;
}
+ return null;
}
#endregion
@@ -428,60 +493,59 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
FalseStatement = new OptionalNode("nullStmt", new BlockStatement { Statements = { new Repeat(new AnyNode()) } })
};
- public void TransformSwitchOnString(AstNode compilationUnit)
+ public SwitchStatement TransformSwitchOnString(IfElseStatement node)
{
- foreach (AstNode node in compilationUnit.Descendants.OfType().ToArray()) {
- Match m = switchOnStringPattern.Match(node);
- if (m == null)
- continue;
- if (m.Has("nonNullDefaultStmt") && !m.Has("nullStmt"))
- continue;
- // switchVar must be the same as switchExpr; or switchExpr must be an assignment and switchVar the left side of that assignment
- if (m.Get("switchVar").Single().Match(m.Get("switchExpr").Single()) == null) {
- AssignmentExpression assign = m.Get("switchExpr").Single() as AssignmentExpression;
- if (m.Get("switchVar").Single().Match(assign.Left) == null)
+ Match m = switchOnStringPattern.Match(node);
+ if (m == null)
+ return null;
+ if (m.Has("nonNullDefaultStmt") && !m.Has("nullStmt"))
+ return null;
+ // switchVar must be the same as switchExpr; or switchExpr must be an assignment and switchVar the left side of that assignment
+ if (m.Get("switchVar").Single().Match(m.Get("switchExpr").Single()) == null) {
+ AssignmentExpression assign = m.Get("switchExpr").Single() as AssignmentExpression;
+ if (m.Get("switchVar").Single().Match(assign.Left) == null)
+ return null;
+ }
+ FieldReference cachedDictField = m.Get("cachedDict").Single().Annotation();
+ if (cachedDictField == null || !cachedDictField.DeclaringType.Name.StartsWith("", StringComparison.Ordinal))
+ return null;
+ List dictCreation = m.Get("dictCreation").Single().Statements.ToList();
+ List> dict = BuildDictionary(dictCreation);
+ SwitchStatement sw = m.Get("switch").Single();
+ sw.Expression = m.Get("switchExpr").Single().Detach();
+ foreach (SwitchSection section in sw.SwitchSections) {
+ List labels = section.CaseLabels.ToList();
+ section.CaseLabels.Clear();
+ foreach (CaseLabel label in labels) {
+ PrimitiveExpression expr = label.Expression as PrimitiveExpression;
+ if (expr == null || !(expr.Value is int))
continue;
- }
- FieldReference cachedDictField = m.Get("cachedDict").Single().Annotation();
- if (cachedDictField == null || !cachedDictField.DeclaringType.Name.StartsWith("", StringComparison.Ordinal))
- continue;
- List dictCreation = m.Get("dictCreation").Single().Statements.ToList();
- List> dict = BuildDictionary(dictCreation);
- SwitchStatement sw = m.Get("switch").Single();
- sw.Expression = m.Get("switchExpr").Single().Detach();
- foreach (SwitchSection section in sw.SwitchSections) {
- List labels = section.CaseLabels.ToList();
- section.CaseLabels.Clear();
- foreach (CaseLabel label in labels) {
- PrimitiveExpression expr = label.Expression as PrimitiveExpression;
- if (expr == null || !(expr.Value is int))
- continue;
- int val = (int)expr.Value;
- foreach (var pair in dict) {
- if (pair.Value == val)
- section.CaseLabels.Add(new CaseLabel { Expression = new PrimitiveExpression(pair.Key) });
- }
+ int val = (int)expr.Value;
+ foreach (var pair in dict) {
+ if (pair.Value == val)
+ section.CaseLabels.Add(new CaseLabel { Expression = new PrimitiveExpression(pair.Key) });
}
}
- if (m.Has("nullStmt")) {
- SwitchSection section = new SwitchSection();
- section.CaseLabels.Add(new CaseLabel { Expression = new NullReferenceExpression() });
- BlockStatement block = m.Get("nullStmt").Single();
- block.Statements.Add(new BreakStatement());
- section.Statements.Add(block.Detach());
+ }
+ if (m.Has("nullStmt")) {
+ SwitchSection section = new SwitchSection();
+ section.CaseLabels.Add(new CaseLabel { Expression = new NullReferenceExpression() });
+ BlockStatement block = m.Get("nullStmt").Single();
+ block.Statements.Add(new BreakStatement());
+ section.Statements.Add(block.Detach());
+ sw.SwitchSections.Add(section);
+ if (m.Has("nonNullDefaultStmt")) {
+ section = new SwitchSection();
+ section.CaseLabels.Add(new CaseLabel());
+ block = new BlockStatement();
+ block.Statements.AddRange(m.Get("nonNullDefaultStmt").Select(s => s.Detach()));
+ block.Add(new BreakStatement());
+ section.Statements.Add(block);
sw.SwitchSections.Add(section);
- if (m.Has("nonNullDefaultStmt")) {
- section = new SwitchSection();
- section.CaseLabels.Add(new CaseLabel());
- block = new BlockStatement();
- block.Statements.AddRange(m.Get("nonNullDefaultStmt").Select(s => s.Detach()));
- block.Add(new BreakStatement());
- section.Statements.Add(block);
- sw.SwitchSections.Add(section);
- }
}
- node.ReplaceWith(sw);
}
+ node.ReplaceWith(sw);
+ return sw;
}
List> BuildDictionary(List dictCreation)
@@ -527,25 +591,25 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}
}}};
- void TransformAutomaticProperties(AstNode compilationUnit)
+ PropertyDeclaration TransformAutomaticProperties(PropertyDeclaration property)
{
- foreach (var property in compilationUnit.Descendants.OfType()) {
- PropertyDefinition cecilProperty = property.Annotation();
- if (cecilProperty == null || cecilProperty.GetMethod == null || cecilProperty.SetMethod == null)
- continue;
- if (!(cecilProperty.GetMethod.IsCompilerGenerated() && cecilProperty.SetMethod.IsCompilerGenerated()))
- continue;
- Match m = automaticPropertyPattern.Match(property);
- if (m != null) {
- FieldDefinition field = m.Get("fieldReference").Single().Annotation().ResolveWithinSameModule();
- if (field.IsCompilerGenerated()) {
- RemoveCompilerGeneratedAttribute(property.Getter.Attributes);
- RemoveCompilerGeneratedAttribute(property.Setter.Attributes);
- property.Getter.Body = null;
- property.Setter.Body = null;
- }
+ PropertyDefinition cecilProperty = property.Annotation();
+ if (cecilProperty == null || cecilProperty.GetMethod == null || cecilProperty.SetMethod == null)
+ return null;
+ if (!(cecilProperty.GetMethod.IsCompilerGenerated() && cecilProperty.SetMethod.IsCompilerGenerated()))
+ return null;
+ Match m = automaticPropertyPattern.Match(property);
+ if (m != null) {
+ FieldDefinition field = m.Get("fieldReference").Single().Annotation().ResolveWithinSameModule();
+ if (field.IsCompilerGenerated()) {
+ RemoveCompilerGeneratedAttribute(property.Getter.Attributes);
+ RemoveCompilerGeneratedAttribute(property.Setter.Attributes);
+ property.Getter.Body = null;
+ property.Setter.Body = null;
}
}
+ // Since the event instance is not changed, we can continue in the visitor as usual, so return null
+ return null;
}
void RemoveCompilerGeneratedAttribute(AstNodeCollection attributeSections)
@@ -625,33 +689,32 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
return combineMethod.DeclaringType.FullName == "System.Delegate";
}
- void TransformAutomaticEvents(AstNode compilationUnit)
+ EventDeclaration TransformAutomaticEvents(CustomEventDeclaration ev)
{
- foreach (var ev in compilationUnit.Descendants.OfType().ToArray()) {
- Match m1 = automaticEventPatternV4.Match(ev.AddAccessor);
- if (!CheckAutomaticEventV4Match(m1, ev, true))
- continue;
- Match m2 = automaticEventPatternV4.Match(ev.RemoveAccessor);
- if (!CheckAutomaticEventV4Match(m2, ev, false))
- continue;
- EventDeclaration ed = new EventDeclaration();
- ev.Attributes.MoveTo(ed.Attributes);
- ed.ReturnType = ev.ReturnType.Detach();
- ed.Modifiers = ev.Modifiers;
- ed.Variables.Add(new VariableInitializer(ev.Name));
- ed.CopyAnnotationsFrom(ev);
-
- EventDefinition eventDef = ev.Annotation();
- if (eventDef != null) {
- FieldDefinition field = eventDef.DeclaringType.Fields.FirstOrDefault(f => f.Name == ev.Name);
- if (field != null) {
- ed.AddAnnotation(field);
- AstBuilder.ConvertAttributes(ed, field, AttributeTarget.Field);
- }
+ Match m1 = automaticEventPatternV4.Match(ev.AddAccessor);
+ if (!CheckAutomaticEventV4Match(m1, ev, true))
+ return null;
+ Match m2 = automaticEventPatternV4.Match(ev.RemoveAccessor);
+ if (!CheckAutomaticEventV4Match(m2, ev, false))
+ return null;
+ EventDeclaration ed = new EventDeclaration();
+ ev.Attributes.MoveTo(ed.Attributes);
+ ed.ReturnType = ev.ReturnType.Detach();
+ ed.Modifiers = ev.Modifiers;
+ ed.Variables.Add(new VariableInitializer(ev.Name));
+ ed.CopyAnnotationsFrom(ev);
+
+ EventDefinition eventDef = ev.Annotation();
+ if (eventDef != null) {
+ FieldDefinition field = eventDef.DeclaringType.Fields.FirstOrDefault(f => f.Name == ev.Name);
+ if (field != null) {
+ ed.AddAnnotation(field);
+ AstBuilder.ConvertAttributes(ed, field, AttributeTarget.Field);
}
-
- ev.ReplaceWith(ed);
}
+
+ ev.ReplaceWith(ed);
+ return ed;
}
#endregion
@@ -671,19 +734,19 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}
};
- void TransformDestructor(AstNode compilationUnit)
+ DestructorDeclaration TransformDestructor(MethodDeclaration methodDef)
{
- foreach (var methodDef in compilationUnit.Descendants.OfType()) {
- Match m = destructorPattern.Match(methodDef);
- if (m != null) {
- DestructorDeclaration dd = new DestructorDeclaration();
- methodDef.Attributes.MoveTo(dd.Attributes);
- dd.Modifiers = methodDef.Modifiers & ~(Modifiers.Protected | Modifiers.Override);
- dd.Body = m.Get("body").Single().Detach();
- dd.Name = AstBuilder.CleanName(context.CurrentType.Name);
- methodDef.ReplaceWith(dd);
- }
+ Match m = destructorPattern.Match(methodDef);
+ if (m != null) {
+ DestructorDeclaration dd = new DestructorDeclaration();
+ methodDef.Attributes.MoveTo(dd.Attributes);
+ dd.Modifiers = methodDef.Modifiers & ~(Modifiers.Protected | Modifiers.Override);
+ dd.Body = m.Get("body").Single().Detach();
+ dd.Name = AstBuilder.CleanName(context.CurrentType.Name);
+ methodDef.ReplaceWith(dd);
+ return dd;
}
+ return null;
}
#endregion
@@ -702,15 +765,15 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
/// Simplify nested 'try { try {} catch {} } finally {}'.
/// This transformation must run after the using/lock tranformations.
///
- void TransformTryCatchFinally(AstNode compilationUnit)
+ TryCatchStatement TransformTryCatchFinally(TryCatchStatement tryFinally)
{
- foreach (var tryFinally in compilationUnit.Descendants.OfType()) {
- if (tryCatchFinallyPattern.Match(tryFinally) != null) {
- TryCatchStatement tryCatch = (TryCatchStatement)tryFinally.TryBlock.Statements.Single();
- tryFinally.TryBlock = tryCatch.TryBlock.Detach();
- tryCatch.CatchClauses.MoveTo(tryFinally.CatchClauses);
- }
+ if (tryCatchFinallyPattern.Match(tryFinally) != null) {
+ TryCatchStatement tryCatch = (TryCatchStatement)tryFinally.TryBlock.Statements.Single();
+ tryFinally.TryBlock = tryCatch.TryBlock.Detach();
+ tryCatch.CatchClauses.MoveTo(tryFinally.CatchClauses);
}
+ // Since the tryFinally instance is not changed, we can continue in the visitor as usual, so return null
+ return null;
}
#endregion