You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2019/10/03 21:20:49 UTC

[groovy] branch GROOVY-9237 created (now 1f99c07)

This is an automated email from the ASF dual-hosted git repository.

emilles pushed a change to branch GROOVY-9237
in repository https://gitbox.apache.org/repos/asf/groovy.git.


      at 1f99c07  Normalize the AST visitation of EmptyStatement and EmptyExpression

This branch includes the following new commits:

     new f461b95  GROOVY-9237: restore constructors for EmptyExpression and EmptyStatement
     new 1f99c07  Normalize the AST visitation of EmptyStatement and EmptyExpression

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[groovy] 01/02: GROOVY-9237: restore constructors for EmptyExpression and EmptyStatement

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY-9237
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit f461b95ffb4c5160ddae13a14cf414680ff7d2bc
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Oct 3 14:53:08 2019 -0500

    GROOVY-9237: restore constructors for EmptyExpression and EmptyStatement
---
 .../codehaus/groovy/antlr/AntlrParserPlugin.java   |   4 +-
 .../codehaus/groovy/ast/expr/EmptyExpression.java  | 147 ++++++++++-----------
 .../codehaus/groovy/ast/stmt/EmptyStatement.java   | 133 +++++++++----------
 .../groovy/classgen/AsmClassGenerator.java         |   2 +-
 .../groovy/classgen/FinalVariableAnalyzer.java     |   3 +-
 .../groovy/classgen/asm/StatementWriter.java       |   2 +-
 .../groovy/ast/CodeVisitorSupportTest.groovy       |   4 +-
 .../codehaus/groovy/ast/builder/AstAssert.groovy   |  19 +--
 .../apache/groovy/parser/antlr4/AstBuilder.java    |   2 +-
 .../antlr4/TryWithResourcesASTTransformation.java  |   4 +-
 10 files changed, 149 insertions(+), 171 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/antlr/AntlrParserPlugin.java b/src/main/java/org/codehaus/groovy/antlr/AntlrParserPlugin.java
index a228da2..b25f451 100644
--- a/src/main/java/org/codehaus/groovy/antlr/AntlrParserPlugin.java
+++ b/src/main/java/org/codehaus/groovy/antlr/AntlrParserPlugin.java
@@ -1620,8 +1620,8 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
             } else {
                 tmpDefaultStatement = statement(child.getNextSibling());
             }
-            if (tmpDefaultStatement != EmptyStatement.INSTANCE) {
-                if (defaultStatement == EmptyStatement.INSTANCE) {
+            if (!(tmpDefaultStatement instanceof EmptyStatement)) {
+                if (defaultStatement instanceof EmptyStatement) {
                     defaultStatement = tmpDefaultStatement;
                 } else {
                     throw new ASTRuntimeException(switchNode, "The default case is already defined.");
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 ce9a65c..5f86d45 100644
--- a/src/main/java/org/codehaus/groovy/ast/expr/EmptyExpression.java
+++ b/src/main/java/org/codehaus/groovy/ast/expr/EmptyExpression.java
@@ -22,114 +22,105 @@ import org.codehaus.groovy.ast.ASTNode;
 import org.codehaus.groovy.ast.AnnotationNode;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.GroovyCodeVisitor;
-import org.codehaus.groovy.ast.NodeMetaDataHandler;
 
-import java.util.List;
 import java.util.Map;
 
 /**
- * This class is a place holder for an empty expression. 
- * Empty expression are used in closures lists like (;). During
- * class Generation this expression should be either ignored or
- * replace with a null value.
- *   
+ * Placeholder for an empty expression. Empty expressions are used in closures
+ * lists like (;). During class generation empty expressions should be ignored
+ * or replaced with a null value.
+ *
  * @see org.codehaus.groovy.ast.stmt.EmptyStatement
  */
-
 public class EmptyExpression extends Expression {
-    public static final EmptyExpression INSTANCE = new EmptyExpression();
 
-    private EmptyExpression() {}
+    /**
+     * @see EmptyExpression#INSTANCE
+     */
+    public EmptyExpression() {
+        super();
+    }
 
+    @Override
     public Expression transformExpression(ExpressionTransformer transformer) {
         return this;
     }
 
+    @Override
     public void visit(GroovyCodeVisitor visitor) {
     }
 
+    //--------------------------------------------------------------------------
 
-    @Override
-    public void setType(ClassNode t) {
-        throw createUnsupportedOperationException();
-    }
+    /**
+     * Immutable singleton that is recommended for use when source range or any
+     * other occurrence-specific metadata is not needed.
+     */
+    public static final EmptyExpression INSTANCE = new EmptyExpression() {
 
-    @Override
-    public void addAnnotation(AnnotationNode value) {
-        throw createUnsupportedOperationException();
-    }
+        private void throwUnsupportedOperationException() {
+            throw new UnsupportedOperationException("EmptyExpression.INSTANCE is immutable");
+        }
 
-    @Override
-    public void addAnnotations(List<AnnotationNode> annotations) {
-        throw createUnsupportedOperationException();
-    }
+        // ASTNode overrides:
 
-    @Override
-    public void setSynthetic(boolean synthetic) {
-        throw createUnsupportedOperationException();
-    }
+        @Override
+        public void setColumnNumber(int n) {
+            throwUnsupportedOperationException();
+        }
 
-    @Override
-    public void setDeclaringClass(ClassNode declaringClass) {
-        throw createUnsupportedOperationException();
-    }
+        @Override
+        public void setLastColumnNumber(int n) {
+            throwUnsupportedOperationException();
+        }
 
-    @Override
-    public void setHasNoRealSourcePosition(boolean value) {
-        throw createUnsupportedOperationException();
-    }
+        @Override
+        public void setLastLineNumber(int n) {
+            throwUnsupportedOperationException();
+        }
 
-    @Override
-    public void setLineNumber(int lineNumber) {
-        throw createUnsupportedOperationException();
-    }
+        @Override
+        public void setLineNumber(int n) {
+            throwUnsupportedOperationException();
+        }
 
-    @Override
-    public void setColumnNumber(int columnNumber) {
-        throw createUnsupportedOperationException();
-    }
+        @Override
+        public void setMetaDataMap(Map<?, ?> meta) {
+            throwUnsupportedOperationException();
+        }
 
-    @Override
-    public void setLastLineNumber(int lastLineNumber) {
-        throw createUnsupportedOperationException();
-    }
+        @Override
+        public void setSourcePosition(ASTNode node) {
+            throwUnsupportedOperationException();
+        }
 
-    @Override
-    public void setLastColumnNumber(int lastColumnNumber) {
-        throw createUnsupportedOperationException();
-    }
+        // AnnotatedNode overrides:
 
-    @Override
-    public void setSourcePosition(ASTNode node) {
-        throw createUnsupportedOperationException();
-    }
+        @Override
+        public void addAnnotation(AnnotationNode node) {
+            throwUnsupportedOperationException();
+        }
 
-    @Override
-    public void copyNodeMetaData(NodeMetaDataHandler other) {
-        throw createUnsupportedOperationException();
-    }
+        @Override
+        public void setDeclaringClass(ClassNode node) {
+            throwUnsupportedOperationException();
+        }
 
-    @Override
-    public void setNodeMetaData(Object key, Object value) {
-        throw createUnsupportedOperationException();
-    }
+        @Override
+        public void setHasNoRealSourcePosition(boolean b) {
+            throwUnsupportedOperationException();
+        }
 
-    @Override
-    public Object putNodeMetaData(Object key, Object value) {
-        throw createUnsupportedOperationException();
-    }
+        @Override
+        public void setSynthetic(boolean b) {
+            throwUnsupportedOperationException();
+        }
 
-    @Override
-    public void removeNodeMetaData(Object key) {
-        throw createUnsupportedOperationException();
-    }
+        // Expression overrides:
 
-    @Override
-    public void setMetaDataMap(Map<?, ?> metaDataMap) {
-        throw createUnsupportedOperationException();
-    }
-
-    private UnsupportedOperationException createUnsupportedOperationException() {
-        return new UnsupportedOperationException("EmptyExpression.INSTANCE is immutable");
-    }
+        @Override
+        public void setType(ClassNode node) {
+            throwUnsupportedOperationException();
+        }
+    };
 }
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 a6ba347..1e6682d 100644
--- a/src/main/java/org/codehaus/groovy/ast/stmt/EmptyStatement.java
+++ b/src/main/java/org/codehaus/groovy/ast/stmt/EmptyStatement.java
@@ -20,94 +20,81 @@ package org.codehaus.groovy.ast.stmt;
 
 import org.codehaus.groovy.ast.ASTNode;
 import org.codehaus.groovy.ast.GroovyCodeVisitor;
-import org.codehaus.groovy.ast.NodeMetaDataHandler;
 
 import java.util.Map;
 
-/**
- * Represents an empty statement
- */
-
 public class EmptyStatement extends Statement {
-    public static final EmptyStatement INSTANCE = new EmptyStatement();
 
     /**
-     * use EmptyStatement.INSTANCE instead
+     * @see EmptyStatement#INSTANCE
      */
-//    @Deprecated
-    private EmptyStatement() {
-        // org.spockframework.compiler.ConditionRewriter will create EmptyStatement via calling the constructor
-        // so we keep the constructor for the time being, but it will be removed finally.
-    }
-    
-    public void visit(GroovyCodeVisitor visitor) {
+    public EmptyStatement() {
+        super();
     }
 
+    @Override
     public boolean isEmpty() {
         return true;
     }
 
     @Override
-    public void setStatementLabel(String label) {
-        throw createUnsupportedOperationException();
-    }
-
-    @Override
-    public void addStatementLabel(String label) {
-        throw createUnsupportedOperationException();
-    }
-
-    @Override
-    public void setLineNumber(int lineNumber) {
-        throw createUnsupportedOperationException();
-    }
-
-    @Override
-    public void setColumnNumber(int columnNumber) {
-        throw createUnsupportedOperationException();
-    }
-
-    @Override
-    public void setLastLineNumber(int lastLineNumber) {
-        throw createUnsupportedOperationException();
-    }
-
-    @Override
-    public void setLastColumnNumber(int lastColumnNumber) {
-        throw createUnsupportedOperationException();
-    }
-
-    @Override
-    public void setSourcePosition(ASTNode node) {
-        throw createUnsupportedOperationException();
-    }
-
-    @Override
-    public void copyNodeMetaData(NodeMetaDataHandler other) {
-        throw createUnsupportedOperationException();
-    }
-
-    @Override
-    public void setNodeMetaData(Object key, Object value) {
-        throw createUnsupportedOperationException();
-    }
-
-    @Override
-    public Object putNodeMetaData(Object key, Object value) {
-        throw createUnsupportedOperationException();
-    }
-
-    @Override
-    public void removeNodeMetaData(Object key) {
-        throw createUnsupportedOperationException();
+    public void visit(GroovyCodeVisitor visitor) {
     }
 
-    @Override
-    public void setMetaDataMap(Map<?, ?> metaDataMap) {
-        throw createUnsupportedOperationException();
-    }
+    //--------------------------------------------------------------------------
 
-    private UnsupportedOperationException createUnsupportedOperationException() {
-        return new UnsupportedOperationException("EmptyStatement.INSTANCE is immutable");
-    }
+    /**
+     * Immutable singleton that is recommended for use when source range or any
+     * other occurrence-specific metadata is not needed.
+     */
+    public static final EmptyStatement INSTANCE = new EmptyStatement() {
+
+        private void throwUnsupportedOperationException() {
+            throw new UnsupportedOperationException("EmptyStatement.INSTANCE is immutable");
+        }
+
+        // ASTNode overrides:
+
+        @Override
+        public void setColumnNumber(int n) {
+            throwUnsupportedOperationException();
+        }
+
+        @Override
+        public void setLastColumnNumber(int n) {
+            throwUnsupportedOperationException();
+        }
+
+        @Override
+        public void setLastLineNumber(int n) {
+            throwUnsupportedOperationException();
+        }
+
+        @Override
+        public void setLineNumber(int n) {
+            throwUnsupportedOperationException();
+        }
+
+        @Override
+        public void setMetaDataMap(Map<?, ?> meta) {
+            throwUnsupportedOperationException();
+        }
+
+        @Override
+        public void setSourcePosition(ASTNode node) {
+            throwUnsupportedOperationException();
+        }
+
+        // Statement overrides:
+
+        @Override
+        public void addStatementLabel(String label) {
+            throwUnsupportedOperationException();
+        }
+
+        @Override
+        public void setStatementLabel(String label) {
+            throwUnsupportedOperationException();
+        }
+    };
 }
diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index 9fecc0f..069e198 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -1910,7 +1910,7 @@ public class AsmClassGenerator extends ClassGenerator {
         int mark = controller.getOperandStack().getStackLength();
         for (Iterator iterator = instructions.iterator(); iterator.hasNext();) {
             Object part = iterator.next();
-            if (part == EmptyExpression.INSTANCE) {
+            if (part instanceof EmptyExpression) {
                 mv.visitInsn(ACONST_NULL);
             } else if (part instanceof Expression) {
                 ((Expression) part).visit(this);
diff --git a/src/main/java/org/codehaus/groovy/classgen/FinalVariableAnalyzer.java b/src/main/java/org/codehaus/groovy/classgen/FinalVariableAnalyzer.java
index 84c9546..38f850d 100644
--- a/src/main/java/org/codehaus/groovy/classgen/FinalVariableAnalyzer.java
+++ b/src/main/java/org/codehaus/groovy/classgen/FinalVariableAnalyzer.java
@@ -172,8 +172,7 @@ public class FinalVariableAnalyzer extends ClassCodeVisitorSupport {
 
     private void recordAssignments(BinaryExpression expression, boolean isDeclaration, Expression leftExpression, Expression rightExpression) {
         if (leftExpression instanceof Variable) {
-            boolean uninitialized =
-                    isDeclaration && rightExpression == EmptyExpression.INSTANCE;
+            boolean uninitialized = isDeclaration && rightExpression instanceof EmptyExpression;
             recordAssignment((Variable) leftExpression, isDeclaration, uninitialized, false, expression);
         } else if (leftExpression instanceof TupleExpression) {
             TupleExpression te = (TupleExpression) leftExpression;
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/StatementWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/StatementWriter.java
index 3ea30be..3a1f712 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/StatementWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/StatementWriter.java
@@ -230,7 +230,7 @@ public class StatementWriter {
     }
 
     private void visitExpressionOrStatement(Object o) {
-        if (o == EmptyExpression.INSTANCE) return;
+        if (o instanceof EmptyExpression) return;
         if (o instanceof Expression) {
             Expression expr = (Expression) o;
             int mark = controller.getOperandStack().getStackLength();
diff --git a/src/test/org/codehaus/groovy/ast/CodeVisitorSupportTest.groovy b/src/test/org/codehaus/groovy/ast/CodeVisitorSupportTest.groovy
index 230b38d..ea235a4 100644
--- a/src/test/org/codehaus/groovy/ast/CodeVisitorSupportTest.groovy
+++ b/src/test/org/codehaus/groovy/ast/CodeVisitorSupportTest.groovy
@@ -128,7 +128,7 @@ class RecordingCodeVisitorSupport extends CodeVisitorSupport implements GroovyIn
     }
 
     protected void visitEmptyStatement(EmptyStatement node) {
-        history << node.getClass()
+        history << EmptyStatement
         super.visitEmptyStatement(node)
     }
 
@@ -141,6 +141,4 @@ class RecordingCodeVisitorSupport extends CodeVisitorSupport implements GroovyIn
         history << node.getClass()
         super.visitCatchStatement(node);
     }
-
 }
-
diff --git a/src/test/org/codehaus/groovy/ast/builder/AstAssert.groovy b/src/test/org/codehaus/groovy/ast/builder/AstAssert.groovy
index 32dc5ef..cfbdedc 100644
--- a/src/test/org/codehaus/groovy/ast/builder/AstAssert.groovy
+++ b/src/test/org/codehaus/groovy/ast/builder/AstAssert.groovy
@@ -26,11 +26,11 @@ import org.junit.Assert
 class AstAssert {
 
     /**
-    * Support for new assertion types can be added by adding a Map<String, Closure> entry. 
-    */ 
+     * Support for new assertion types can be added by adding a Map<String, Closure> entry.
+     */
     private static Map<Object, Closure> ASSERTION_MAP = [
             BlockStatement : { expected, actual ->
-                assertSyntaxTree(expected.statements, actual.statements) 
+                assertSyntaxTree(expected.statements, actual.statements)
             },
             AttributeExpression : { expected, actual ->
                 assertSyntaxTree([expected.objectExpression], [actual.objectExpression])
@@ -133,7 +133,6 @@ class AstAssert {
                 assertSyntaxTree([expected.defaultValue], [actual.defaultValue])
                 Assert.assertEquals("Wrong parameter name", expected.name, actual.name)
                 Assert.assertEquals("Wrong 'hasDefaultValue'", expected.hasDefaultValue, actual.hasDefaultValue)
-                
             },
             ConstructorCallExpression : { expected, actual ->
                 assertSyntaxTree([expected.arguments], [actual.arguments])
@@ -355,7 +354,7 @@ class AstAssert {
      */
     static void assertSyntaxTree(expected, actual) {
         if (expected == null && actual == null) return
-        
+
         if (actual == null || expected == null || expected.size() != actual?.size()) {
             Assert.fail("AST comparison failure. \nExpected $expected \nReceived $actual")
         }
@@ -365,11 +364,15 @@ class AstAssert {
             } else {
                 Assert.assertEquals("Wrong type in AST Node", item.getClass(), actual[index].getClass())
 
-                if (ASSERTION_MAP.containsKey(item.getClass().getSimpleName())) {
-                    Closure assertion = ASSERTION_MAP.get(item.getClass().getSimpleName())
+                Class itemType = item.getClass()
+                if (itemType.isAnonymousClass()) {
+                    itemType = itemType.getSuperclass()
+                }
+                if (ASSERTION_MAP.containsKey(itemType.getSimpleName())) {
+                    Closure assertion = ASSERTION_MAP.get(itemType.getSimpleName())
                     assertion(item, actual[index])
                 } else {
-                    Assert.fail("Unexpected type: ${item.getClass()} Update the unit test!")
+                    Assert.fail("Unexpected type: ${itemType} Update the unit test!")
                 }
             }
         }
diff --git a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
index f102184..c1eb396 100644
--- a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -1879,7 +1879,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
 
             int modifiers = modifierManager.getClassMemberModifiersOpValue();
 
-            Expression initialValue = EmptyExpression.INSTANCE.equals(declarationExpression.getRightExpression()) ? null : declarationExpression.getRightExpression();
+            Expression initialValue = declarationExpression.getRightExpression() instanceof EmptyExpression ? null : declarationExpression.getRightExpression();
             Object defaultValue = findDefaultValueByType(variableType);
 
             if (classNode.isInterface()) {
diff --git a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/TryWithResourcesASTTransformation.java b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/TryWithResourcesASTTransformation.java
index 04fba60..b22df09 100644
--- a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/TryWithResourcesASTTransformation.java
+++ b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/TryWithResourcesASTTransformation.java
@@ -77,8 +77,8 @@ public class TryWithResourcesASTTransformation {
     }
 
     private boolean isBasicTryWithResourcesStatement(TryCatchStatement tryCatchStatement) {
-        if (EmptyStatement.INSTANCE.equals(tryCatchStatement.getFinallyStatement())
-                && !asBoolean(tryCatchStatement.getCatchStatements())) {
+        if (tryCatchStatement.getFinallyStatement() instanceof EmptyStatement &&
+                !asBoolean(tryCatchStatement.getCatchStatements())) {
             return true;
         }
 


[groovy] 02/02: Normalize the AST visitation of EmptyStatement and EmptyExpression

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY-9237
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 1f99c0776f59e50262592bb68e74ec4cee0e3252
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Oct 3 16:19:11 2019 -0500

    Normalize the AST visitation of EmptyStatement and EmptyExpression
---
 .../codehaus/groovy/ast/CodeVisitorSupport.java    | 87 +++++++++++++++-------
 .../org/codehaus/groovy/ast/GroovyCodeVisitor.java | 35 +++++----
 .../codehaus/groovy/ast/expr/EmptyExpression.java  |  1 +
 .../codehaus/groovy/ast/stmt/EmptyStatement.java   |  1 +
 .../groovy/classgen/FinalVariableAnalyzer.java     | 22 ++----
 .../control/customizers/SecureASTCustomizer.java   | 77 ++++++++++++++-----
 .../transform/stc/StaticTypeCheckingVisitor.java   | 12 +--
 .../groovy/ast/CodeVisitorSupportTest.groovy       | 17 +++--
 .../console/ui/ScriptToTreeNodeAdapter.groovy      |  2 +-
 .../codehaus/groovy/macro/matcher/ASTFinder.java   |  2 +-
 .../macro/matcher/ContextualClassCodeVisitor.java  |  2 +-
 11 files changed, 162 insertions(+), 96 deletions(-)

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 @@ import org.codehaus.groovy.classgen.BytecodeExpression;
  */
 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 @@ public abstract class CodeVisitorSupport implements GroovyCodeVisitor {
         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.ConstantExpression;
 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.CaseStatement;
 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 org.codehaus.groovy.classgen.BytecodeExpression;
 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 @@ public interface GroovyCodeVisitor {
 
     void visitAssertStatement(AssertStatement statement);
 
-    void visitTryCatchFinally(TryCatchStatement finally1);
+    void visitTryCatchFinally(TryCatchStatement statement);
 
     void visitSwitch(SwitchStatement statement);
 
@@ -113,21 +114,22 @@ public interface GroovyCodeVisitor {
     void visitThrowStatement(ThrowStatement statement);
 
     void visitSynchronizedStatement(SynchronizedStatement statement);
-    
+
     void visitCatchStatement(CatchStatement statement);
 
-    // expressions
+    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 @@ public interface GroovyCodeVisitor {
 
     void visitPropertyExpression(PropertyExpression expression);
 
-    void visitAttributeExpression(AttributeExpression attributeExpression);
+    void visitAttributeExpression(AttributeExpression expression);
 
     void visitFieldExpression(FieldExpression expression);
 
@@ -190,10 +192,12 @@ public interface GroovyCodeVisitor {
 
     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 @@ public interface GroovyCodeVisitor {
         }
     }
 }
-
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 @@ public class EmptyExpression extends Expression {
 
     @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 @@ public class EmptyStatement extends Statement {
 
     @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.TupleExpression;
 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 @@ public class FinalVariableAnalyzer extends ClassCodeVisitorSupport {
         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 @@ public class FinalVariableAnalyzer extends ClassCodeVisitorSupport {
         }
     }
 
-    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 @@ public class FinalVariableAnalyzer extends ClassCodeVisitorSupport {
         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 @@ public class FinalVariableAnalyzer extends ClassCodeVisitorSupport {
         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 @@ public class SecureASTCustomizer extends CompilationCustomizer {
             }
         }
 
+        @Override
         public void visitBlockStatement(final BlockStatement block) {
             assertStatementAuthorized(block);
             for (Statement statement : block.getStatements()) {
@@ -810,76 +811,70 @@ public class SecureASTCustomizer extends CompilationCustomizer {
             }
         }
 
-
+        @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 @@ public class SecureASTCustomizer extends CompilationCustomizer {
             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 @@ public class SecureASTCustomizer extends CompilationCustomizer {
             call.getArguments().visit(this);
         }
 
+        @Override
         public void visitStaticMethodCallExpression(final StaticMethodCallExpression call) {
             assertExpressionAuthorized(call);
             final String typeName = call.getOwnerType().getName();
@@ -945,11 +948,13 @@ public class SecureASTCustomizer extends CompilationCustomizer {
             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 @@ public class SecureASTCustomizer extends CompilationCustomizer {
             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 @@ public class SecureASTCustomizer extends CompilationCustomizer {
             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 @@ public class SecureASTCustomizer extends CompilationCustomizer {
             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 @@ public class SecureASTCustomizer extends CompilationCustomizer {
             }
         }
 
+        @Override
         public void visitAttributeExpression(final AttributeExpression expression) {
             assertExpressionAuthorized(expression);
             Expression receiver = expression.getObjectExpression();
@@ -1062,10 +1080,12 @@ public class SecureASTCustomizer extends CompilationCustomizer {
             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 @@ public class SecureASTCustomizer extends CompilationCustomizer {
             visitMethodPointerExpression(expression);
         }
 
+        @Override
         public void visitConstantExpression(final ConstantExpression expression) {
             assertExpressionAuthorized(expression);
             final String type = expression.getType().getName();
@@ -1088,10 +1109,12 @@ public class SecureASTCustomizer extends CompilationCustomizer {
             }
         }
 
+        @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 @@ public class SecureASTCustomizer extends CompilationCustomizer {
             }
         }
 
+        @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 @@ public class SecureASTCustomizer extends CompilationCustomizer {
      * 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 @@ public class SecureASTCustomizer extends CompilationCustomizer {
      * 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 37a3c58..79feaf5 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 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     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 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return ext;
     }
 
-    //        @Override
+    @Override
     protected SourceUnit getSourceUnit() {
         return typeCheckingContext.source;
     }
@@ -3923,14 +3924,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             // 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.EmptyStatement
 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 @@ class CodeVisitorSupportTest extends GroovyTestCase {
         assert visitor.history.size() == 5
     }
 
+    @Test
     void testEmptyStatementsOnIfElse() {
         def ast = new AstBuilder().buildFromCode(CompilePhase.SEMANTIC_ANALYSIS, true, {
             if (true) { 1 }
@@ -61,12 +64,13 @@ class CodeVisitorSupportTest extends GroovyTestCase {
         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 @@ class CodeVisitorSupportTest extends GroovyTestCase {
         assert visitor.history[4] == BlockStatement
     }
 
+    @Test
     void testEmptyStatementsOnTryCatch() {
         def ast = new AstBuilder().buildFromCode {
             def x
@@ -108,7 +113,7 @@ class CodeVisitorSupportTest extends GroovyTestCase {
  * 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 @@ class RecordingCodeVisitorSupport extends CodeVisitorSupport implements GroovyIn
         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 @@ class TreeNodeBuildingVisitor extends CodeVisitorSupport {
     }
 
     @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 @@ class ASTFinder extends ContextualClassCodeVisitor {
     }
 
     @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 @@ public abstract class ContextualClassCodeVisitor extends ClassCodeVisitorSupport
     }
 
     @Override
-    protected void visitEmptyStatement(final EmptyStatement statement) {
+    public void visitEmptyStatement(final EmptyStatement statement) {
         pushContext(statement);
         super.visitEmptyStatement(statement);
         popContext();