GROOVY-9237: restore constructors for EmptyExpression and EmptyStatement
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 @@
             } 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.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 @@
 
 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();
+    public void visit(GroovyCodeVisitor visitor) {
     }
 
-    @Override
-    public void addStatementLabel(String label) {
-        throw createUnsupportedOperationException();
-    }
+    //--------------------------------------------------------------------------
 
-    @Override
-    public void setLineNumber(int lineNumber) {
-        throw createUnsupportedOperationException();
-    }
+    /**
+     * 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() {
 
-    @Override
-    public void setColumnNumber(int columnNumber) {
-        throw createUnsupportedOperationException();
-    }
+        private void throwUnsupportedOperationException() {
+            throw new UnsupportedOperationException("EmptyStatement.INSTANCE is immutable");
+        }
 
-    @Override
-    public void setLastLineNumber(int lastLineNumber) {
-        throw createUnsupportedOperationException();
-    }
+        // ASTNode overrides:
 
-    @Override
-    public void setLastColumnNumber(int lastColumnNumber) {
-        throw createUnsupportedOperationException();
-    }
+        @Override
+        public void setColumnNumber(int n) {
+            throwUnsupportedOperationException();
+        }
 
-    @Override
-    public void setSourcePosition(ASTNode node) {
-        throw createUnsupportedOperationException();
-    }
+        @Override
+        public void setLastColumnNumber(int n) {
+            throwUnsupportedOperationException();
+        }
 
-    @Override
-    public void copyNodeMetaData(NodeMetaDataHandler other) {
-        throw createUnsupportedOperationException();
-    }
+        @Override
+        public void setLastLineNumber(int n) {
+            throwUnsupportedOperationException();
+        }
 
-    @Override
-    public void setNodeMetaData(Object key, Object value) {
-        throw createUnsupportedOperationException();
-    }
+        @Override
+        public void setLineNumber(int n) {
+            throwUnsupportedOperationException();
+        }
 
-    @Override
-    public Object putNodeMetaData(Object key, Object value) {
-        throw createUnsupportedOperationException();
-    }
+        @Override
+        public void setMetaDataMap(Map<?, ?> meta) {
+            throwUnsupportedOperationException();
+        }
 
-    @Override
-    public void removeNodeMetaData(Object key) {
-        throw createUnsupportedOperationException();
-    }
+        @Override
+        public void setSourcePosition(ASTNode node) {
+            throwUnsupportedOperationException();
+        }
 
-    @Override
-    public void setMetaDataMap(Map<?, ?> metaDataMap) {
-        throw createUnsupportedOperationException();
-    }
+        // Statement overrides:
 
-    private UnsupportedOperationException createUnsupportedOperationException() {
-        return new UnsupportedOperationException("EmptyStatement.INSTANCE is immutable");
-    }
+        @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 @@
         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 @@
 
     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 @@
     }
 
     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 @@
     }
 
     protected void visitEmptyStatement(EmptyStatement node) {
-        history << node.getClass()
+        history << EmptyStatement
         super.visitEmptyStatement(node)
     }
 
@@ -141,6 +141,4 @@
         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 @@
 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 @@
                 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 @@
      */
     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 @@
             } 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 @@
 
             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 @@
     }
 
     private boolean isBasicTryWithResourcesStatement(TryCatchStatement tryCatchStatement) {
-        if (EmptyStatement.INSTANCE.equals(tryCatchStatement.getFinallyStatement())
-                && !asBoolean(tryCatchStatement.getCatchStatements())) {
+        if (tryCatchStatement.getFinallyStatement() instanceof EmptyStatement &&
+                !asBoolean(tryCatchStatement.getCatchStatements())) {
             return true;
         }