Normalize the AST visitation of EmptyStatement and EmptyExpression
diff --git a/src/main/java/org/codehaus/groovy/ast/CodeVisitorSupport.java b/src/main/java/org/codehaus/groovy/ast/CodeVisitorSupport.java
index 03ef8b8..f220d54 100644
--- a/src/main/java/org/codehaus/groovy/ast/CodeVisitorSupport.java
+++ b/src/main/java/org/codehaus/groovy/ast/CodeVisitorSupport.java
@@ -80,73 +80,69 @@
  */
 public abstract class CodeVisitorSupport implements GroovyCodeVisitor {
 
+    @Override
     public void visitBlockStatement(BlockStatement block) {
         for (Statement statement : block.getStatements()) {
             statement.visit(this);
         }
     }
 
+    @Override
     public void visitForLoop(ForStatement forLoop) {
         forLoop.getCollectionExpression().visit(this);
         forLoop.getLoopBlock().visit(this);
     }
 
+    @Override
     public void visitWhileLoop(WhileStatement loop) {
         loop.getBooleanExpression().visit(this);
         loop.getLoopBlock().visit(this);
     }
 
+    @Override
     public void visitDoWhileLoop(DoWhileStatement loop) {
         loop.getLoopBlock().visit(this);
         loop.getBooleanExpression().visit(this);
     }
 
+    @Override
     public void visitIfElse(IfStatement ifElse) {
         ifElse.getBooleanExpression().visit(this);
         ifElse.getIfBlock().visit(this);
-
-        Statement elseBlock = ifElse.getElseBlock();
-        if (elseBlock instanceof EmptyStatement) {
-            // dispatching to EmptyStatement will not call back visitor, 
-            // must call our visitEmptyStatement explicitly
-            visitEmptyStatement((EmptyStatement) elseBlock);
-        } else {
-            elseBlock.visit(this);
-        }
+        ifElse.getElseBlock().visit(this);
     }
 
+    @Override
     public void visitExpressionStatement(ExpressionStatement statement) {
         statement.getExpression().visit(this);
     }
 
+    @Override
     public void visitReturnStatement(ReturnStatement statement) {
         statement.getExpression().visit(this);
     }
 
+    @Override
     public void visitAssertStatement(AssertStatement statement) {
         statement.getBooleanExpression().visit(this);
         statement.getMessageExpression().visit(this);
     }
 
+    @Override
     public void visitTryCatchFinally(TryCatchStatement statement) {
         statement.getTryStatement().visit(this);
         for (CatchStatement catchStatement : statement.getCatchStatements()) {
             catchStatement.visit(this);
         }
-        Statement finallyStatement = statement.getFinallyStatement();
-        if (finallyStatement instanceof EmptyStatement) {
-            // dispatching to EmptyStatement will not call back visitor, 
-            // must call our visitEmptyStatement explicitly
-            visitEmptyStatement((EmptyStatement) finallyStatement);
-        } else {
-            finallyStatement.visit(this);
-        }
+        statement.getFinallyStatement().visit(this);
     }
 
-    protected void visitEmptyStatement(EmptyStatement statement) {
+    @Override
+    public void visitEmptyStatement(EmptyStatement statement) {
         // noop
     }
 
+    @Override
     public void visitSwitch(SwitchStatement statement) {
         statement.getExpression().visit(this);
         for (CaseStatement caseStatement : statement.getCaseStatements()) {
@@ -155,184 +151,225 @@
         statement.getDefaultStatement().visit(this);
     }
 
+    @Override
     public void visitCaseStatement(CaseStatement statement) {
         statement.getExpression().visit(this);
         statement.getCode().visit(this);
     }
 
+    @Override
     public void visitBreakStatement(BreakStatement statement) {
     }
 
+    @Override
     public void visitContinueStatement(ContinueStatement statement) {
     }
 
+    @Override
     public void visitSynchronizedStatement(SynchronizedStatement statement) {
         statement.getExpression().visit(this);
         statement.getCode().visit(this);
     }
 
+    @Override
     public void visitThrowStatement(ThrowStatement statement) {
         statement.getExpression().visit(this);
     }
 
+    @Override
     public void visitMethodCallExpression(MethodCallExpression call) {
         call.getObjectExpression().visit(this);
         call.getMethod().visit(this);
         call.getArguments().visit(this);
     }
 
+    @Override
     public void visitStaticMethodCallExpression(StaticMethodCallExpression call) {
         call.getArguments().visit(this);
     }
 
+    @Override
     public void visitConstructorCallExpression(ConstructorCallExpression call) {
         call.getArguments().visit(this);
     }
 
+    @Override
     public void visitBinaryExpression(BinaryExpression expression) {
         expression.getLeftExpression().visit(this);
         expression.getRightExpression().visit(this);
     }
 
+    @Override
     public void visitTernaryExpression(TernaryExpression expression) {
         expression.getBooleanExpression().visit(this);
         expression.getTrueExpression().visit(this);
         expression.getFalseExpression().visit(this);
     }
 
+    @Override
     public void visitShortTernaryExpression(ElvisOperatorExpression expression) {
         visitTernaryExpression(expression);
     }
 
+    @Override
     public void visitPostfixExpression(PostfixExpression expression) {
         expression.getExpression().visit(this);
     }
 
+    @Override
     public void visitPrefixExpression(PrefixExpression expression) {
         expression.getExpression().visit(this);
     }
 
+    @Override
     public void visitBooleanExpression(BooleanExpression expression) {
         expression.getExpression().visit(this);
     }
 
+    @Override
     public void visitNotExpression(NotExpression expression) {
         expression.getExpression().visit(this);
     }
 
+    @Override
     public void visitClosureExpression(ClosureExpression expression) {
         expression.getCode().visit(this);
     }
 
+    @Override
     public void visitLambdaExpression(LambdaExpression expression) {
         visitClosureExpression(expression);
     }
 
+    @Override
     public void visitTupleExpression(TupleExpression expression) {
         visitListOfExpressions(expression.getExpressions());
     }
 
+    @Override
     public void visitListExpression(ListExpression expression) {
         visitListOfExpressions(expression.getExpressions());
     }
 
+    @Override
     public void visitArrayExpression(ArrayExpression expression) {
         visitListOfExpressions(expression.getExpressions());
         visitListOfExpressions(expression.getSizeExpression());
     }
 
+    @Override
     public void visitMapExpression(MapExpression expression) {
         visitListOfExpressions(expression.getMapEntryExpressions());
-
     }
 
+    @Override
     public void visitMapEntryExpression(MapEntryExpression expression) {
         expression.getKeyExpression().visit(this);
         expression.getValueExpression().visit(this);
-
     }
 
+    @Override
     public void visitRangeExpression(RangeExpression expression) {
         expression.getFrom().visit(this);
         expression.getTo().visit(this);
     }
 
+    @Override
     public void visitSpreadExpression(SpreadExpression expression) {
         expression.getExpression().visit(this);
     }
 
+    @Override
     public void visitSpreadMapExpression(SpreadMapExpression expression) {
         expression.getExpression().visit(this);
     }
 
+    @Override
     public void visitMethodPointerExpression(MethodPointerExpression expression) {
         expression.getExpression().visit(this);
         expression.getMethodName().visit(this);
     }
 
+    @Override
     public void visitMethodReferenceExpression(MethodReferenceExpression expression) {
         visitMethodPointerExpression(expression);
     }
 
+    @Override
     public void visitUnaryMinusExpression(UnaryMinusExpression expression) {
         expression.getExpression().visit(this);
     }
 
+    @Override
     public void visitUnaryPlusExpression(UnaryPlusExpression expression) {
         expression.getExpression().visit(this);
     }
 
+    @Override
     public void visitBitwiseNegationExpression(BitwiseNegationExpression expression) {
         expression.getExpression().visit(this);
     }
 
+    @Override
     public void visitCastExpression(CastExpression expression) {
         expression.getExpression().visit(this);
     }
 
+    @Override
     public void visitConstantExpression(ConstantExpression expression) {
     }
 
+    @Override
     public void visitClassExpression(ClassExpression expression) {
     }
 
+    @Override
     public void visitVariableExpression(VariableExpression expression) {
     }
 
+    @Override
     public void visitDeclarationExpression(DeclarationExpression expression) {
         visitBinaryExpression(expression);
     }
 
+    @Override
     public void visitPropertyExpression(PropertyExpression expression) {
         expression.getObjectExpression().visit(this);
         expression.getProperty().visit(this);
     }
 
+    @Override
     public void visitAttributeExpression(AttributeExpression expression) {
         expression.getObjectExpression().visit(this);
         expression.getProperty().visit(this);
     }
 
+    @Override
     public void visitFieldExpression(FieldExpression expression) {
     }
 
+    @Override
     public void visitGStringExpression(GStringExpression expression) {
         visitListOfExpressions(expression.getStrings());
         visitListOfExpressions(expression.getValues());
     }
 
+    @Override
     public void visitCatchStatement(CatchStatement statement) {
         statement.getCode().visit(this);
     }
 
-    public void visitArgumentlistExpression(ArgumentListExpression ale) {
-        visitTupleExpression(ale);
+    @Override
+    public void visitArgumentlistExpression(ArgumentListExpression expression) {
+        visitTupleExpression(expression);
     }
 
-    public void visitClosureListExpression(ClosureListExpression cle) {
-        visitListOfExpressions(cle.getExpressions());
+    @Override
+    public void visitClosureListExpression(ClosureListExpression expression) {
+        visitListOfExpressions(expression.getExpressions());
     }
 
-    public void visitBytecodeExpression(BytecodeExpression cle) {
+    @Override
+    public void visitBytecodeExpression(BytecodeExpression expression) {
     }
 }
diff --git a/src/main/java/org/codehaus/groovy/ast/GroovyCodeVisitor.java b/src/main/java/org/codehaus/groovy/ast/GroovyCodeVisitor.java
index 9d39f0c..d807e60 100644
--- a/src/main/java/org/codehaus/groovy/ast/GroovyCodeVisitor.java
+++ b/src/main/java/org/codehaus/groovy/ast/GroovyCodeVisitor.java
@@ -32,6 +32,7 @@
 import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
 import org.codehaus.groovy.ast.expr.DeclarationExpression;
 import org.codehaus.groovy.ast.expr.ElvisOperatorExpression;
+import org.codehaus.groovy.ast.expr.EmptyExpression;
 import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.ast.expr.FieldExpression;
 import org.codehaus.groovy.ast.expr.GStringExpression;
@@ -62,6 +63,7 @@
 import org.codehaus.groovy.ast.stmt.CatchStatement;
 import org.codehaus.groovy.ast.stmt.ContinueStatement;
 import org.codehaus.groovy.ast.stmt.DoWhileStatement;
+import org.codehaus.groovy.ast.stmt.EmptyStatement;
 import org.codehaus.groovy.ast.stmt.ExpressionStatement;
 import org.codehaus.groovy.ast.stmt.ForStatement;
 import org.codehaus.groovy.ast.stmt.IfStatement;
@@ -76,23 +78,22 @@
 import java.util.List;
 
 /**
- * An implementation of the visitor pattern for working with ASTNodes
+ * An implementation of the visitor pattern for working with ASTNodes.
  */
 public interface GroovyCodeVisitor {
 
+    //--------------------------------------------------------------------------
     // statements
 
-    //-------------------------------------------------------------------------
-
     void visitBlockStatement(BlockStatement statement);
 
-    void visitForLoop(ForStatement forLoop);
+    void visitForLoop(ForStatement statement);
 
-    void visitWhileLoop(WhileStatement loop);
+    void visitWhileLoop(WhileStatement statement);
 
-    void visitDoWhileLoop(DoWhileStatement loop);
+    void visitDoWhileLoop(DoWhileStatement statement);
 
-    void visitIfElse(IfStatement ifElse);
+    void visitIfElse(IfStatement statement);
 
     void visitExpressionStatement(ExpressionStatement statement);
 
@@ -100,7 +101,7 @@
 
     void visitAssertStatement(AssertStatement statement);
 
-    void visitTryCatchFinally(TryCatchStatement finally1);
+    void visitTryCatchFinally(TryCatchStatement statement);
 
     void visitSwitch(SwitchStatement statement);
 
@@ -113,21 +114,22 @@
     void visitThrowStatement(ThrowStatement statement);
 
     void visitSynchronizedStatement(SynchronizedStatement statement);
-    
+
     void visitCatchStatement(CatchStatement statement);
 
+    default void visitEmptyStatement(EmptyStatement statement) {}
+
+    //--------------------------------------------------------------------------
     // expressions
 
-    //-------------------------------------------------------------------------
-
-    void visitMethodCallExpression(MethodCallExpression call);
+    void visitMethodCallExpression(MethodCallExpression expression);
 
     void visitStaticMethodCallExpression(StaticMethodCallExpression expression);
 
     void visitConstructorCallExpression(ConstructorCallExpression expression);
 
     void visitTernaryExpression(TernaryExpression expression);
-    
+
     void visitShortTernaryExpression(ElvisOperatorExpression expression);
 
     void visitBinaryExpression(BinaryExpression expression);
@@ -154,7 +156,7 @@
 
     void visitPropertyExpression(PropertyExpression expression);
 
-    void visitAttributeExpression(AttributeExpression attributeExpression);
+    void visitAttributeExpression(AttributeExpression expression);
 
     void visitFieldExpression(FieldExpression expression);
 
@@ -190,10 +192,12 @@
 
     void visitArgumentlistExpression(ArgumentListExpression expression);
 
-    void visitClosureListExpression(ClosureListExpression closureListExpression);
+    void visitClosureListExpression(ClosureListExpression expression);
 
     void visitBytecodeExpression(BytecodeExpression expression);
 
+    default void visitEmptyExpression(EmptyExpression expression) {}
+
     default void visitListOfExpressions(List<? extends Expression> list) {
         if (list == null) return;
         for (Expression expression : list) {
@@ -206,4 +210,3 @@
         }
     }
 }
-
diff --git a/src/main/java/org/codehaus/groovy/ast/expr/EmptyExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/EmptyExpression.java
index 5f86d45..c877f56 100644
--- a/src/main/java/org/codehaus/groovy/ast/expr/EmptyExpression.java
+++ b/src/main/java/org/codehaus/groovy/ast/expr/EmptyExpression.java
@@ -48,6 +48,7 @@
 
     @Override
     public void visit(GroovyCodeVisitor visitor) {
+        visitor.visitEmptyExpression(this);
     }
 
     //--------------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/stmt/EmptyStatement.java b/src/main/java/org/codehaus/groovy/ast/stmt/EmptyStatement.java
index 1e6682d..5365b88 100644
--- a/src/main/java/org/codehaus/groovy/ast/stmt/EmptyStatement.java
+++ b/src/main/java/org/codehaus/groovy/ast/stmt/EmptyStatement.java
@@ -39,6 +39,7 @@
 
     @Override
     public void visit(GroovyCodeVisitor visitor) {
+        visitor.visitEmptyStatement(this);
     }
 
     //--------------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/classgen/FinalVariableAnalyzer.java b/src/main/java/org/codehaus/groovy/classgen/FinalVariableAnalyzer.java
index 38f850d..bcd81e5 100644
--- a/src/main/java/org/codehaus/groovy/classgen/FinalVariableAnalyzer.java
+++ b/src/main/java/org/codehaus/groovy/classgen/FinalVariableAnalyzer.java
@@ -33,7 +33,6 @@
 import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.ast.stmt.BlockStatement;
 import org.codehaus.groovy.ast.stmt.CatchStatement;
-import org.codehaus.groovy.ast.stmt.EmptyStatement;
 import org.codehaus.groovy.ast.stmt.IfStatement;
 import org.codehaus.groovy.ast.stmt.ReturnStatement;
 import org.codehaus.groovy.ast.stmt.Statement;
@@ -275,9 +274,8 @@
         Map<Variable, VariableState> ifState = pushState();
         ifElse.getIfBlock().visit(this);
         popState();
-        Statement elseBlock = ifElse.getElseBlock();
         Map<Variable, VariableState> elseState = pushState();
-        visitPossiblyEmptyStatement(elseBlock);
+        ifElse.getElseBlock().visit(this);
         popState();
 
         // merge if/else branches
@@ -299,16 +297,6 @@
         }
     }
 
-    private void visitPossiblyEmptyStatement(Statement block) {
-        if (block instanceof EmptyStatement) {
-            // dispatching to EmptyStatement will not call back visitor,
-            // must call our visitEmptyStatement explicitly
-            visitEmptyStatement((EmptyStatement) block);
-        } else {
-            block.visit(this);
-        }
-    }
-
     private boolean isFinal(VariableState value) {
         return value != null && value.isFinal;
     }
@@ -324,14 +312,14 @@
         Statement finallyStatement = statement.getFinallyStatement();
         List<Map<Variable, VariableState>> afterStates = new ArrayList<>();
         // the try finally case
-        visitPossiblyEmptyStatement(finallyStatement);
+        finallyStatement.visit(this);
         if (!returningBlock(tryStatement)) {
             afterStates.add(new HashMap<Variable, VariableState>(getState()));
         }
         popState();
         // now the finally only case but only if no catches
         if (statement.getCatchStatements().isEmpty()) {
-            visitPossiblyEmptyStatement(finallyStatement);
+            finallyStatement.visit(this);
             if (!returningBlock(tryStatement)) {
                 afterStates.add(new HashMap<Variable, VariableState>(getState()));
             }
@@ -373,9 +361,9 @@
         getState().putAll(initialVarState);
         Statement code = catchStatement.getCode();
         catchStatement.visit(this);
-        visitPossiblyEmptyStatement(finallyStatement);
+        finallyStatement.visit(this);
         if (code == null || !returningBlock(code)) {
-            afterTryCatchStates.add(new HashMap<Variable, VariableState>(getState()));
+            afterTryCatchStates.add(new HashMap<>(getState()));
         }
         popState();
     }
diff --git a/src/main/java/org/codehaus/groovy/control/customizers/SecureASTCustomizer.java b/src/main/java/org/codehaus/groovy/control/customizers/SecureASTCustomizer.java
index 6d7290d..5f2c2c4 100644
--- a/src/main/java/org/codehaus/groovy/control/customizers/SecureASTCustomizer.java
+++ b/src/main/java/org/codehaus/groovy/control/customizers/SecureASTCustomizer.java
@@ -803,6 +803,7 @@
             }
         }
 
+        @Override
         public void visitBlockStatement(final BlockStatement block) {
             assertStatementAuthorized(block);
             for (Statement statement : block.getStatements()) {
@@ -810,76 +811,70 @@
             }
         }
 
-
+        @Override
         public void visitForLoop(final ForStatement forLoop) {
             assertStatementAuthorized(forLoop);
             forLoop.getCollectionExpression().visit(this);
             forLoop.getLoopBlock().visit(this);
         }
 
+        @Override
         public void visitWhileLoop(final WhileStatement loop) {
             assertStatementAuthorized(loop);
             loop.getBooleanExpression().visit(this);
             loop.getLoopBlock().visit(this);
         }
 
+        @Override
         public void visitDoWhileLoop(final DoWhileStatement loop) {
             assertStatementAuthorized(loop);
             loop.getBooleanExpression().visit(this);
             loop.getLoopBlock().visit(this);
         }
 
+        @Override
         public void visitIfElse(final IfStatement ifElse) {
             assertStatementAuthorized(ifElse);
             ifElse.getBooleanExpression().visit(this);
             ifElse.getIfBlock().visit(this);
-
-            Statement elseBlock = ifElse.getElseBlock();
-            if (elseBlock instanceof EmptyStatement) {
-                // dispatching to EmptyStatement will not call back visitor,
-                // must call our visitEmptyStatement explicitly
-                visitEmptyStatement((EmptyStatement) elseBlock);
-            } else {
-                elseBlock.visit(this);
-            }
+            ifElse.getElseBlock().visit(this);
         }
 
+        @Override
         public void visitExpressionStatement(final ExpressionStatement statement) {
             assertStatementAuthorized(statement);
             statement.getExpression().visit(this);
         }
 
+        @Override
         public void visitReturnStatement(final ReturnStatement statement) {
             assertStatementAuthorized(statement);
             statement.getExpression().visit(this);
         }
 
+        @Override
         public void visitAssertStatement(final AssertStatement statement) {
             assertStatementAuthorized(statement);
             statement.getBooleanExpression().visit(this);
             statement.getMessageExpression().visit(this);
         }
 
+        @Override
         public void visitTryCatchFinally(final TryCatchStatement statement) {
             assertStatementAuthorized(statement);
             statement.getTryStatement().visit(this);
             for (CatchStatement catchStatement : statement.getCatchStatements()) {
                 catchStatement.visit(this);
             }
-            Statement finallyStatement = statement.getFinallyStatement();
-            if (finallyStatement instanceof EmptyStatement) {
-                // dispatching to EmptyStatement will not call back visitor,
-                // must call our visitEmptyStatement explicitly
-                visitEmptyStatement((EmptyStatement) finallyStatement);
-            } else {
-                finallyStatement.visit(this);
-            }
+            statement.getFinallyStatement().visit(this);
         }
 
-        protected void visitEmptyStatement(EmptyStatement statement) {
+        @Override
+        public void visitEmptyStatement(EmptyStatement statement) {
             // noop
         }
 
+        @Override
         public void visitSwitch(final SwitchStatement statement) {
             assertStatementAuthorized(statement);
             statement.getExpression().visit(this);
@@ -889,36 +884,43 @@
             statement.getDefaultStatement().visit(this);
         }
 
+        @Override
         public void visitCaseStatement(final CaseStatement statement) {
             assertStatementAuthorized(statement);
             statement.getExpression().visit(this);
             statement.getCode().visit(this);
         }
 
+        @Override
         public void visitBreakStatement(final BreakStatement statement) {
             assertStatementAuthorized(statement);
         }
 
+        @Override
         public void visitContinueStatement(final ContinueStatement statement) {
             assertStatementAuthorized(statement);
         }
 
+        @Override
         public void visitThrowStatement(final ThrowStatement statement) {
             assertStatementAuthorized(statement);
             statement.getExpression().visit(this);
         }
 
+        @Override
         public void visitSynchronizedStatement(final SynchronizedStatement statement) {
             assertStatementAuthorized(statement);
             statement.getExpression().visit(this);
             statement.getCode().visit(this);
         }
 
+        @Override
         public void visitCatchStatement(final CatchStatement statement) {
             assertStatementAuthorized(statement);
             statement.getCode().visit(this);
         }
 
+        @Override
         public void visitMethodCallExpression(final MethodCallExpression call) {
             assertExpressionAuthorized(call);
             Expression receiver = call.getObjectExpression();
@@ -934,6 +936,7 @@
             call.getArguments().visit(this);
         }
 
+        @Override
         public void visitStaticMethodCallExpression(final StaticMethodCallExpression call) {
             assertExpressionAuthorized(call);
             final String typeName = call.getOwnerType().getName();
@@ -945,11 +948,13 @@
             call.getArguments().visit(this);
         }
 
+        @Override
         public void visitConstructorCallExpression(final ConstructorCallExpression call) {
             assertExpressionAuthorized(call);
             call.getArguments().visit(this);
         }
 
+        @Override
         public void visitTernaryExpression(final TernaryExpression expression) {
             assertExpressionAuthorized(expression);
             expression.getBooleanExpression().visit(this);
@@ -957,11 +962,13 @@
             expression.getFalseExpression().visit(this);
         }
 
+        @Override
         public void visitShortTernaryExpression(final ElvisOperatorExpression expression) {
             assertExpressionAuthorized(expression);
             visitTernaryExpression(expression);
         }
 
+        @Override
         public void visitBinaryExpression(final BinaryExpression expression) {
             assertExpressionAuthorized(expression);
             assertTokenAuthorized(expression.getOperation());
@@ -969,23 +976,27 @@
             expression.getRightExpression().visit(this);
         }
 
+        @Override
         public void visitPrefixExpression(final PrefixExpression expression) {
             assertExpressionAuthorized(expression);
             assertTokenAuthorized(expression.getOperation());
             expression.getExpression().visit(this);
         }
 
+        @Override
         public void visitPostfixExpression(final PostfixExpression expression) {
             assertExpressionAuthorized(expression);
             assertTokenAuthorized(expression.getOperation());
             expression.getExpression().visit(this);
         }
 
+        @Override
         public void visitBooleanExpression(final BooleanExpression expression) {
             assertExpressionAuthorized(expression);
             expression.getExpression().visit(this);
         }
 
+        @Override
         public void visitClosureExpression(final ClosureExpression expression) {
             assertExpressionAuthorized(expression);
             if (!isClosuresAllowed) throw new SecurityException("Closures are not allowed");
@@ -997,33 +1008,39 @@
             visitClosureExpression(expression);
         }
 
+        @Override
         public void visitTupleExpression(final TupleExpression expression) {
             assertExpressionAuthorized(expression);
             visitListOfExpressions(expression.getExpressions());
         }
 
+        @Override
         public void visitMapExpression(final MapExpression expression) {
             assertExpressionAuthorized(expression);
             visitListOfExpressions(expression.getMapEntryExpressions());
         }
 
+        @Override
         public void visitMapEntryExpression(final MapEntryExpression expression) {
             assertExpressionAuthorized(expression);
             expression.getKeyExpression().visit(this);
             expression.getValueExpression().visit(this);
         }
 
+        @Override
         public void visitListExpression(final ListExpression expression) {
             assertExpressionAuthorized(expression);
             visitListOfExpressions(expression.getExpressions());
         }
 
+        @Override
         public void visitRangeExpression(final RangeExpression expression) {
             assertExpressionAuthorized(expression);
             expression.getFrom().visit(this);
             expression.getTo().visit(this);
         }
 
+        @Override
         public void visitPropertyExpression(final PropertyExpression expression) {
             assertExpressionAuthorized(expression);
             Expression receiver = expression.getObjectExpression();
@@ -1048,6 +1065,7 @@
             }
         }
 
+        @Override
         public void visitAttributeExpression(final AttributeExpression expression) {
             assertExpressionAuthorized(expression);
             Expression receiver = expression.getObjectExpression();
@@ -1062,10 +1080,12 @@
             checkConstantTypeIfNotMethodNameOrProperty(property);
         }
 
+        @Override
         public void visitFieldExpression(final FieldExpression expression) {
             assertExpressionAuthorized(expression);
         }
 
+        @Override
         public void visitMethodPointerExpression(final MethodPointerExpression expression) {
             assertExpressionAuthorized(expression);
             expression.getExpression().visit(this);
@@ -1077,6 +1097,7 @@
             visitMethodPointerExpression(expression);
         }
 
+        @Override
         public void visitConstantExpression(final ConstantExpression expression) {
             assertExpressionAuthorized(expression);
             final String type = expression.getType().getName();
@@ -1088,10 +1109,12 @@
             }
         }
 
+        @Override
         public void visitClassExpression(final ClassExpression expression) {
             assertExpressionAuthorized(expression);
         }
 
+        @Override
         public void visitVariableExpression(final VariableExpression expression) {
             assertExpressionAuthorized(expression);
             final String type = expression.getType().getName();
@@ -1103,69 +1126,82 @@
             }
         }
 
+        @Override
         public void visitDeclarationExpression(final DeclarationExpression expression) {
             assertExpressionAuthorized(expression);
             visitBinaryExpression(expression);
         }
 
+        @Override
         public void visitGStringExpression(final GStringExpression expression) {
             assertExpressionAuthorized(expression);
             visitListOfExpressions(expression.getStrings());
             visitListOfExpressions(expression.getValues());
         }
 
+        @Override
         public void visitArrayExpression(final ArrayExpression expression) {
             assertExpressionAuthorized(expression);
             visitListOfExpressions(expression.getExpressions());
             visitListOfExpressions(expression.getSizeExpression());
         }
 
+        @Override
         public void visitSpreadExpression(final SpreadExpression expression) {
             assertExpressionAuthorized(expression);
             expression.getExpression().visit(this);
         }
 
+        @Override
         public void visitSpreadMapExpression(final SpreadMapExpression expression) {
             assertExpressionAuthorized(expression);
             expression.getExpression().visit(this);
         }
 
+        @Override
         public void visitNotExpression(final NotExpression expression) {
             assertExpressionAuthorized(expression);
             expression.getExpression().visit(this);
         }
 
+        @Override
         public void visitUnaryMinusExpression(final UnaryMinusExpression expression) {
             assertExpressionAuthorized(expression);
             expression.getExpression().visit(this);
         }
 
+        @Override
         public void visitUnaryPlusExpression(final UnaryPlusExpression expression) {
             assertExpressionAuthorized(expression);
             expression.getExpression().visit(this);
         }
 
+        @Override
         public void visitBitwiseNegationExpression(final BitwiseNegationExpression expression) {
             assertExpressionAuthorized(expression);
             expression.getExpression().visit(this);
         }
 
+        @Override
         public void visitCastExpression(final CastExpression expression) {
             assertExpressionAuthorized(expression);
             expression.getExpression().visit(this);
         }
 
+        @Override
         public void visitArgumentlistExpression(final ArgumentListExpression expression) {
             assertExpressionAuthorized(expression);
             visitTupleExpression(expression);
         }
 
+        @Override
         public void visitClosureListExpression(final ClosureListExpression closureListExpression) {
             assertExpressionAuthorized(closureListExpression);
             if (!isClosuresAllowed) throw new SecurityException("Closures are not allowed");
             visitListOfExpressions(closureListExpression.getExpressions());
         }
 
+        @Override
         public void visitBytecodeExpression(final BytecodeExpression expression) {
             assertExpressionAuthorized(expression);
         }
@@ -1175,6 +1211,7 @@
      * This interface allows the user to plugin custom expression checkers if expression blacklist or whitelist are not
      * sufficient
      */
+    @FunctionalInterface
     public interface ExpressionChecker {
         boolean isAuthorized(Expression expression);
     }
@@ -1183,8 +1220,8 @@
      * This interface allows the user to plugin custom statement checkers if statement blacklist or whitelist are not
      * sufficient
      */
+    @FunctionalInterface
     public interface StatementChecker {
         boolean isAuthorized(Statement expression);
     }
-
 }
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index 6e493a0..f0472b1 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -324,6 +324,7 @@
     private static final String[] EMPTY_STRING_ARRAY = new String[0];
 
     protected final ReturnAdder.ReturnStatementListener returnListener = new ReturnAdder.ReturnStatementListener() {
+        @Override
         public void returnStatementAdded(final ReturnStatement returnStatement) {
             if (isNullConstant(returnStatement.getExpression())) return;
             checkReturnType(returnStatement);
@@ -360,7 +361,7 @@
         return ext;
     }
 
-    //        @Override
+    @Override
     protected SourceUnit getSourceUnit() {
         return typeCheckingContext.source;
     }
@@ -3912,14 +3913,7 @@
             // GROOVY-6099: restore assignment info as before the if branch
             restoreTypeBeforeConditional();
 
-            Statement elseBlock = ifElse.getElseBlock();
-            if (elseBlock instanceof EmptyStatement) {
-                // dispatching to EmptyStatement will not call back visitor,
-                // must call our visitEmptyStatement explicitly
-                visitEmptyStatement((EmptyStatement) elseBlock);
-            } else {
-                elseBlock.visit(this);
-            }
+            ifElse.getElseBlock().visit(this);
         } finally {
             popAssignmentTracking(oldTracker);
         }
diff --git a/src/test/org/codehaus/groovy/ast/CodeVisitorSupportTest.groovy b/src/test/org/codehaus/groovy/ast/CodeVisitorSupportTest.groovy
index ea235a4..8a57ffd 100644
--- a/src/test/org/codehaus/groovy/ast/CodeVisitorSupportTest.groovy
+++ b/src/test/org/codehaus/groovy/ast/CodeVisitorSupportTest.groovy
@@ -18,7 +18,7 @@
  */
 package org.codehaus.groovy.ast
 
-import groovy.test.GroovyTestCase
+import groovy.transform.PackageScope
 import org.codehaus.groovy.ast.builder.AstBuilder
 import org.codehaus.groovy.ast.expr.BooleanExpression
 import org.codehaus.groovy.ast.stmt.BlockStatement
@@ -27,14 +27,16 @@
 import org.codehaus.groovy.ast.stmt.IfStatement
 import org.codehaus.groovy.ast.stmt.TryCatchStatement
 import org.codehaus.groovy.control.CompilePhase
+import org.junit.Test
 
 /**
  * Tests the CodeVisitorSupport.
  */
-class CodeVisitorSupportTest extends GroovyTestCase {
+final class CodeVisitorSupportTest {
 
+    @Test
     void testIfElse() {
-        def ast = new AstBuilder().buildFromCode { if (true) { 1 } else  { 2 } }
+        def ast = new AstBuilder().buildFromCode { if (true) { 1 } else { 2 } }
         def visitor = new RecordingCodeVisitorSupport()
         visitor.visitBlockStatement(ast[0]) // first element is always BlockStatement
 
@@ -46,6 +48,7 @@
         assert visitor.history.size() == 5
     }
 
+    @Test
     void testEmptyStatementsOnIfElse() {
         def ast = new AstBuilder().buildFromCode(CompilePhase.SEMANTIC_ANALYSIS, true, {
             if (true) { 1 }
@@ -61,12 +64,13 @@
         assert visitor.history.size() == 5
     }
 
+    @Test
     void testTryCatchFinally() {
         def ast = new AstBuilder().buildFromCode {
             def x
             try {
                 x = 1
-            } catch (IOException ei) {
+            } catch (IOException e) {
                 x = 2
             } finally {
                 x = 4
@@ -82,6 +86,7 @@
         assert visitor.history[4] == BlockStatement
     }
 
+    @Test
     void testEmptyStatementsOnTryCatch() {
         def ast = new AstBuilder().buildFromCode {
             def x
@@ -108,7 +113,7 @@
  * This would be better implemented using invokeMethod but it is called from Java so it
  * won't dispatch correctly.
  */
-@groovy.transform.PackageScope
+@PackageScope
 class RecordingCodeVisitorSupport extends CodeVisitorSupport implements GroovyInterceptable {
     def history = []
 
@@ -127,7 +132,7 @@
         super.visitBooleanExpression(node)
     }
 
-    protected void visitEmptyStatement(EmptyStatement node) {
+    void visitEmptyStatement(EmptyStatement node) {
         history << EmptyStatement
         super.visitEmptyStatement(node)
     }
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ScriptToTreeNodeAdapter.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ScriptToTreeNodeAdapter.groovy
index 1ea7e99..c184a5d 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ScriptToTreeNodeAdapter.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/ScriptToTreeNodeAdapter.groovy
@@ -560,7 +560,7 @@
     }
 
     @Override
-    protected void visitEmptyStatement(EmptyStatement node) {
+    void visitEmptyStatement(EmptyStatement node) {
         addNode(node, EmptyStatement, { super.visitEmptyStatement(it) })
     }
 
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ASTFinder.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ASTFinder.java
index b22e116..ccf864e 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ASTFinder.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ASTFinder.java
@@ -245,7 +245,7 @@
     }
 
     @Override
-    protected void visitEmptyStatement(final EmptyStatement statement) {
+    public void visitEmptyStatement(final EmptyStatement statement) {
         super.visitEmptyStatement(statement);
         tryFind(EmptyStatement.class, statement);
     }
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ContextualClassCodeVisitor.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ContextualClassCodeVisitor.java
index 64a2f66..2c2cf4d 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ContextualClassCodeVisitor.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ContextualClassCodeVisitor.java
@@ -545,7 +545,7 @@
     }
 
     @Override
-    protected void visitEmptyStatement(final EmptyStatement statement) {
+    public void visitEmptyStatement(final EmptyStatement statement) {
         pushContext(statement);
         super.visitEmptyStatement(statement);
         popContext();