public UsingStatement TransformUsings(ExpressionStatement node)
        {
            Match m1 = variableAssignPattern.Match(node);

            if (m1 == null)
            {
                return(null);
            }
            AstNode tryCatch = node.NextSibling;
            Match   m2       = usingTryCatchPattern.Match(tryCatch);

            if (m2 == null)
            {
                return(null);
            }
            string variableName = m1.Get <IdentifierExpression>("variable").Single().Identifier;

            if (variableName == m2.Get <IdentifierExpression>("ident").Single().Identifier)
            {
                if (m2.Has("valueType"))
                {
                    // if there's no if(x!=null), then it must be a value type
                    ILVariable v = m1.Get("variable").Single().Annotation <ILVariable>();
                    if (v == null || v.Type == null || !v.Type.IsValueType)
                    {
                        return(null);
                    }
                }
                node.Remove();
                BlockStatement body           = m2.Get <BlockStatement>("body").Single();
                UsingStatement usingStatement = new UsingStatement();
                usingStatement.ResourceAcquisition = node.Expression.Detach();
                usingStatement.EmbeddedStatement   = body.Detach();
                tryCatch.ReplaceWith(usingStatement);
                // Move the variable declaration into the resource acquisition, if possible
                // This is necessary for the foreach-pattern to work on the result of the using-pattern
                VariableDeclarationStatement varDecl = FindVariableDeclaration(usingStatement, variableName);
                if (varDecl != null && varDecl.Parent is BlockStatement)
                {
                    Statement declarationPoint;
                    if (CanMoveVariableDeclarationIntoStatement(varDecl, usingStatement, out declarationPoint))
                    {
                        Debug.Assert(declarationPoint == usingStatement);
                        // Moving the variable into the UsingStatement is allowed:
                        usingStatement.ResourceAcquisition = new VariableDeclarationStatement {
                            Type      = (AstType)varDecl.Type.Clone(),
                            Variables =
                            {
                                new VariableInitializer {
                                    Name        = variableName,
                                    Initializer = m1.Get <Expression>("initializer").Single().Detach()
                                }.CopyAnnotationsFrom(usingStatement.ResourceAcquisition)
                            }
                        }.CopyAnnotationsFrom(node);
                    }
                }
                return(usingStatement);
            }
            return(null);
        }
        public DoWhileStatement TransformDoWhile(WhileStatement whileLoop)
        {
            Match m = doWhilePattern.Match(whileLoop);

            if (m.Success)
            {
                DoWhileStatement doLoop = new DoWhileStatement();
                doLoop.Condition = new UnaryOperatorExpression(UnaryOperatorType.Not, m.Get <Expression>("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();
                doLoop.CopyAnnotationsFrom(whileLoop);
                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 <VariableDeclarationStatement>())
                {
                    VariableInitializer v = varDecl.Variables.Single();
                    if (doLoop.Condition.DescendantsAndSelf.OfType <IdentifierExpression>().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 <object>();
                        // remove varDecl with assignment; and move annotations from varDecl to the ExpressionStatement:
                        varDecl.ReplaceWith(new ExpressionStatement(assign).CopyAnnotationsFrom(varDecl));
                        varDecl.RemoveAnnotations <object>();

                        // insert the varDecl above the do-while loop:
                        doLoop.Parent.InsertChildBefore(doLoop, varDecl, BlockStatement.StatementRole);
                    }
                }
                return(doLoop);
            }
            return(null);
        }
        public SwitchStatement TransformSwitchOnString(IfElseStatement node)
        {
            Match m = switchOnStringPattern.Match(node);

            if (!m.Success)
            {
                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().IsMatch(m.Get("switchExpr").Single()))
            {
                AssignmentExpression assign = m.Get("switchExpr").Single() as AssignmentExpression;
                if (!(assign != null && m.Get("switchVar").Single().IsMatch(assign.Left)))
                {
                    return(null);
                }
            }
            FieldReference cachedDictField = m.Get <AstNode>("cachedDict").Single().Annotation <FieldReference>();

            if (cachedDictField == null)
            {
                return(null);
            }
            List <Statement> dictCreation           = m.Get <BlockStatement>("dictCreation").Single().Statements.ToList();
            List <KeyValuePair <string, int> > dict = BuildDictionary(dictCreation);
            SwitchStatement sw = m.Get <SwitchStatement>("switch").Single();

            sw.Expression = m.Get <Expression>("switchExpr").Single().Detach();
            foreach (SwitchSection section in sw.SwitchSections)
            {
                List <CaseLabel> 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)
                            });
                        }
                    }
                }
            }
            if (m.Has("nullStmt"))
            {
                SwitchSection section = new SwitchSection();
                section.CaseLabels.Add(new CaseLabel {
                    Expression = new NullReferenceExpression()
                });
                BlockStatement block = m.Get <BlockStatement>("nullStmt").Single();
                block.Statements.Add(new BreakStatement());
                section.Statements.Add(block.Detach());
                sw.SwitchSections.Add(section);
            }
            else if (m.Has("nonNullDefaultStmt"))
            {
                sw.SwitchSections.Add(
                    new SwitchSection {
                    CaseLabels = { new CaseLabel {
                                       Expression = new NullReferenceExpression()
                                   } },
                    Statements = { new BlockStatement {
                                       new BreakStatement()
                                   } }
                });
            }
            if (m.Has("nonNullDefaultStmt"))
            {
                SwitchSection section = new SwitchSection();
                section.CaseLabels.Add(new CaseLabel());
                BlockStatement block = new BlockStatement();
                block.Statements.AddRange(m.Get <Statement>("nonNullDefaultStmt").Select(s => s.Detach()));
                block.Add(new BreakStatement());
                section.Statements.Add(block);
                sw.SwitchSections.Add(section);
            }
            node.ReplaceWith(sw);
            return(sw);
        }