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

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


The following commit(s) were added to refs/heads/master by this push:
     new 6953697ca2 node meta data
6953697ca2 is described below

commit 6953697ca27d69bf03271c83cd22348dfc58ea5f
Author: Eric Milles <eric.mil...@thomsonreuters.com>
AuthorDate: Tue Aug 29 12:17:15 2023 -0500

    node meta data
---
 .../apache/groovy/parser/antlr4/AstBuilder.java    | 100 ++++++++-------------
 .../codehaus/groovy/ast/NodeMetaDataHandler.java   |  24 +++--
 .../java/org/codehaus/groovy/util/ListHashMap.java |  27 +++---
 3 files changed, 71 insertions(+), 80 deletions(-)

diff --git a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java 
b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
index d1e71e9805..62c08cd53c 100644
--- a/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ b/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -502,7 +502,7 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
         throw createParsingFailedException("Unsupported for control: " + 
ctx.getText(), ctx);
     }
 
-    @Override @SuppressWarnings("unchecked")
+    @Override
     public Expression visitForInit(final ForInitContext ctx) {
         if (!asBoolean(ctx)) {
             return EmptyExpression.INSTANCE;
@@ -548,9 +548,9 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
     @Override
     public Tuple2<Parameter, Expression> visitEnhancedForControl(final 
EnhancedForControlContext ctx) {
         Parameter parameter = new Parameter(this.visitType(ctx.type()), 
this.visitVariableDeclaratorId(ctx.variableDeclaratorId()).getName());
-        configureAST(parameter, ctx.variableDeclaratorId());
         ModifierManager modifierManager = new ModifierManager(this, 
this.visitVariableModifiersOpt(ctx.variableModifiersOpt()));
         modifierManager.processParameter(parameter);
+        configureAST(parameter, ctx.variableDeclaratorId());
         return tuple(parameter, (Expression) this.visit(ctx.expression()));
     }
 
@@ -693,16 +693,9 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
      */
     @Override
     public List<CatchStatement> visitCatchClause(final CatchClauseContext ctx) 
{
-        // FIXME Groovy will ignore variableModifier of parameter in the catch 
clause
-        // In order to make the new parser behave same with the old one, we do 
not process variableModifier*
-
         return this.visitCatchType(ctx.catchType()).stream()
                 .map(e -> configureAST(
                         new CatchStatement(
-                                // FIXME The old parser does not set location 
info for the parameter of the catch clause.
-                                // we could make it better
-                                //this.configureAST(new Parameter(e, 
this.visitIdentifier(ctx.identifier())), ctx.Identifier()),
-
                                 new Parameter(e, 
this.visitIdentifier(ctx.identifier())),
                                 this.visitBlock(ctx.block())),
                         ctx))
@@ -777,7 +770,7 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
         }
     }
 
-    @Override @SuppressWarnings("unchecked")
+    @Override
     public List<Statement> visitSwitchBlockStatementGroup(final 
SwitchBlockStatementGroupContext ctx) {
         int labelCount = ctx.switchLabel().size();
         List<Token> firstLabelHolder = new ArrayList<>(1);
@@ -800,7 +793,6 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
                         );
                         statementList.add(configureAST(statement, 
firstLabelHolder.get(0)));
                         break;
-
                       case DEFAULT:
                         statement = 
this.visitBlockStatements(ctx.blockStatements());
                         statement.putNodeMetaData(IS_SWITCH_DEFAULT, 
Boolean.TRUE);
@@ -1005,7 +997,7 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
     }
     private int switchExpressionVariableSeq;
 
-    @Override @SuppressWarnings("unchecked")
+    @Override
     public Tuple3<List<Statement>, Boolean, Boolean> 
visitSwitchBlockStatementExpressionGroup(SwitchBlockStatementExpressionGroupContext
 ctx) {
         int labelCnt = ctx.switchExpressionLabel().size();
         List<Token> firstLabelHolder = new ArrayList<>(1);
@@ -1098,14 +1090,12 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
                     }
 
                     switch (tuple.getV1().getType()) {
-                        case CASE: {
+                        case CASE:
                             if (!asBoolean(statementList)) {
                                 firstLabelHolder.add(tuple.getV1());
                             }
-
-                            for (int i = 0, n = tuple.getV2().size(); i < n; 
i++) {
+                            for (int i = 0, n = tuple.getV2().size(); i < n; i 
+= 1) {
                                 Expression expr = tuple.getV2().get(i);
-
                                 statementList.add(
                                         configureAST(
                                                 new CaseStatement(
@@ -1117,19 +1107,11 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
                                                 ),
                                                 firstLabelHolder.get(0)));
                             }
-
                             break;
-                        }
-                        case DEFAULT: {
-                            codeBlock.putNodeMetaData(IS_SWITCH_DEFAULT, true);
-
-                            statementList.add(
-                                    // this.configureAST(codeBlock, 
tuple.getKey())
-                                    codeBlock
-                            );
-
+                        case DEFAULT:
+                            codeBlock.putNodeMetaData(IS_SWITCH_DEFAULT, 
Boolean.TRUE);
+                            statementList.add(codeBlock);
                             break;
-                        }
                     }
 
                     return statementList;
@@ -1325,7 +1307,7 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
                                 .collect(Collectors.toList()));
                 sealedAnnotationNode.setMember("permittedSubclasses", 
permittedSubclassesListExpression);
                 configureAST(sealedAnnotationNode, ctx.PERMITS());
-                sealedAnnotationNode.setNodeMetaData("permits", true);
+                sealedAnnotationNode.setNodeMetaData("permits", Boolean.TRUE);
             }
             classNode.addAnnotation(sealedAnnotationNode);
         } else if (isNonSealed) {
@@ -1423,7 +1405,6 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
         }
     }
 
-    @SuppressWarnings("unchecked")
     private boolean containsDefaultMethods(final ClassDeclarationContext ctx) {
         List<MethodDeclarationContext> methodDeclarationContextList =
                 (List<MethodDeclarationContext>) 
ctx.classBody().classBodyDeclaration().stream()
@@ -2480,13 +2461,13 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
             GenericsType[] genericsTypes = 
this.visitNonWildcardTypeArguments(ctx.nonWildcardTypeArguments());
 
             if (asBoolean(ctx.DOT())) {
-                boolean isSafeChain = this.isTrue(baseExpr, 
PATH_EXPRESSION_BASE_EXPR_SAFE_CHAIN);
+                boolean isSafeChain = isTrue(baseExpr, 
PATH_EXPRESSION_BASE_EXPR_SAFE_CHAIN);
                 return this.createDotExpression(ctx, baseExpr, namePartExpr, 
genericsTypes, isSafeChain);
             } else if (asBoolean(ctx.SAFE_DOT())) {
                 return this.createDotExpression(ctx, baseExpr, namePartExpr, 
genericsTypes, true);
             } else if (asBoolean(ctx.SAFE_CHAIN_DOT())) { // e.g. obj??.a  OR 
obj??.@a
                 Expression expression = createDotExpression(ctx, baseExpr, 
namePartExpr, genericsTypes, true);
-                
expression.putNodeMetaData(PATH_EXPRESSION_BASE_EXPR_SAFE_CHAIN, true);
+                
expression.putNodeMetaData(PATH_EXPRESSION_BASE_EXPR_SAFE_CHAIN, Boolean.TRUE);
                 return expression;
             } else if (asBoolean(ctx.METHOD_POINTER())) { // e.g. obj.&m
                 return configureAST(new MethodPointerExpression(baseExpr, 
namePartExpr), ctx);
@@ -2510,7 +2491,7 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
             return configureAST(this.visitCreator(creatorContext), ctx);
         } else if (asBoolean(ctx.indexPropertyArgs())) { // e.g. list[1, 3, 5]
             Tuple2<Token, Expression> tuple = 
this.visitIndexPropertyArgs(ctx.indexPropertyArgs());
-            boolean isSafeChain = this.isTrue(baseExpr, 
PATH_EXPRESSION_BASE_EXPR_SAFE_CHAIN);
+            boolean isSafeChain = isTrue(baseExpr, 
PATH_EXPRESSION_BASE_EXPR_SAFE_CHAIN);
             return configureAST(
                     new BinaryExpression(baseExpr, 
createGroovyToken(tuple.getV1()), tuple.getV2(), isSafeChain || 
asBoolean(ctx.indexPropertyArgs().SAFE_INDEX())),
                     ctx);
@@ -2582,7 +2563,7 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
 
             if (baseExpr instanceof VariableExpression // e.g. m()
                     || baseExpr instanceof GStringExpression // e.g. "$m"()
-                    || (baseExpr instanceof ConstantExpression && 
this.isTrue(baseExpr, IS_STRING))) { // e.g. "m"()
+                    || (baseExpr instanceof ConstantExpression && 
isTrue(baseExpr, IS_STRING))) { // e.g. "m"()
                 String baseExprText = baseExpr.getText();
                 if (THIS_STR.equals(baseExprText) || 
SUPER_STR.equals(baseExprText)) { // e.g. this(...), super(...)
                     // class declaration is not allowed in the closure,
@@ -2675,7 +2656,7 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
 
             if (baseExpr instanceof VariableExpression // e.g. m { }
                     || baseExpr instanceof GStringExpression // e.g. "$m" { }
-                    || (baseExpr instanceof ConstantExpression && 
this.isTrue(baseExpr, IS_STRING))) { // e.g. "m" { }
+                    || (baseExpr instanceof ConstantExpression && 
isTrue(baseExpr, IS_STRING))) { // e.g. "m" { }
                 MethodCallExpression methodCallExpression =
                         this.createMethodCallExpression(
                                 baseExpr,
@@ -3158,7 +3139,7 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
 
     @Override
     public Expression visitConditionalExprAlt(final ConditionalExprAltContext 
ctx) {
-        ctx.fb.putNodeMetaData(IS_INSIDE_CONDITIONAL_EXPRESSION, true);
+        ctx.fb.putNodeMetaData(IS_INSIDE_CONDITIONAL_EXPRESSION, Boolean.TRUE);
 
         if (asBoolean(ctx.ELVIS())) { // e.g. a == 6 ?: 0
             return configureAST(
@@ -3166,7 +3147,7 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
                     ctx);
         }
 
-        ctx.tb.putNodeMetaData(IS_INSIDE_CONDITIONAL_EXPRESSION, true);
+        ctx.tb.putNodeMetaData(IS_INSIDE_CONDITIONAL_EXPRESSION, Boolean.TRUE);
 
         return configureAST(
                 new TernaryExpression(
@@ -3603,15 +3584,13 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
     }
 
     private void validateExpressionListElement(final 
ExpressionListElementContext ctx, final Expression expression) {
-        if (!(expression instanceof MethodCallExpression && isTrue(expression, 
IS_COMMAND_EXPRESSION))) {
-            return;
-        }
-
-        // statements like `foo(String a)` is invalid
-        MethodCallExpression methodCallExpression = (MethodCallExpression) 
expression;
-        String methodName = methodCallExpression.getMethodAsString();
-        if (methodCallExpression.isImplicitThis() && 
Character.isUpperCase(methodName.codePointAt(0)) || 
isPrimitiveType(methodName)) {
-            throw createParsingFailedException("Invalid method declaration", 
ctx);
+        if (expression instanceof MethodCallExpression && isTrue(expression, 
IS_COMMAND_EXPRESSION)) {
+            // statements like `foo(String a)` is invalid
+            MethodCallExpression methodCallExpression = (MethodCallExpression) 
expression;
+            String methodName = methodCallExpression.getMethodAsString();
+            if (methodCallExpression.isImplicitThis() && 
Character.isUpperCase(methodName.codePointAt(0)) || 
isPrimitiveType(methodName)) {
+                throw createParsingFailedException("Invalid method 
declaration", ctx);
+            }
         }
     }
 
@@ -3905,16 +3884,14 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
     private void validateParameterList(final List<Parameter> parameterList) {
         for (int n = parameterList.size(), i = n - 1; i >= 0; i -= 1) {
             Parameter parameter = parameterList.get(i);
-
             String name = parameter.getName();
-            if (name.equals("_")) {
+            if ("_".equals(name)) {
                 continue; // check this later
             }
             for (Parameter otherParameter : parameterList) {
                 if (otherParameter == parameter) {
                     continue;
                 }
-
                 if (otherParameter.getName().equals(name)) {
                     throw createParsingFailedException("Duplicated parameter 
'" + name + "' found.", parameter);
                 }
@@ -4051,7 +4028,8 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
         ClassNode classNode = null;
 
         if (asBoolean(ctx.classOrInterfaceType())) {
-            
ctx.classOrInterfaceType().putNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR, 
ctx.getNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR));
+            if (isTrue(ctx, IS_INSIDE_INSTANCEOF_EXPR))
+                
ctx.classOrInterfaceType().putNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR, 
Boolean.TRUE);
             classNode = 
this.visitClassOrInterfaceType(ctx.classOrInterfaceType());
         } else if (asBoolean(ctx.primitiveType())) {
             classNode = this.visitPrimitiveType(ctx.primitiveType());
@@ -4078,10 +4056,12 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
     public ClassNode visitClassOrInterfaceType(final 
ClassOrInterfaceTypeContext ctx) {
         ClassNode classNode;
         if (asBoolean(ctx.qualifiedClassName())) {
-            
ctx.qualifiedClassName().putNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR, 
ctx.getNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR));
+            if (isTrue(ctx, IS_INSIDE_INSTANCEOF_EXPR))
+                
ctx.qualifiedClassName().putNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR, 
Boolean.TRUE);
             classNode = this.visitQualifiedClassName(ctx.qualifiedClassName());
         } else {
-            
ctx.qualifiedStandardClassName().putNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR, 
ctx.getNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR));
+            if (isTrue(ctx, IS_INSIDE_INSTANCEOF_EXPR))
+                
ctx.qualifiedStandardClassName().putNodeMetaData(IS_INSIDE_INSTANCEOF_EXPR, 
Boolean.TRUE);
             classNode = 
this.visitQualifiedStandardClassName(ctx.qualifiedStandardClassName());
         }
 
@@ -4379,11 +4359,11 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
 
     private ClassNode createClassNode(final GroovyParserRuleContext ctx) {
         ClassNode result = makeClassNode(ctx.getText());
-
-        if (!isTrue(ctx, IS_INSIDE_INSTANCEOF_EXPR)) { // type in the 
"instanceof" expression should not have proxy to redirect to it
+        if (isTrue(ctx, IS_INSIDE_INSTANCEOF_EXPR)) {
+            // type in the "instanceof" expression shouldn't have redirect
+        } else {
             result = this.proxyClassNode(result);
         }
-
         return configureAST(result, ctx);
     }
 
@@ -4394,7 +4374,6 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
 
         ClassNode cn = ClassHelper.makeWithoutCaching(classNode.getName());
         cn.setRedirect(classNode);
-
         return cn;
     }
 
@@ -4499,12 +4478,9 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
                             PathElementContext pathElementContext = 
(PathElementContext) e;
                             
pathElementContext.putNodeMetaData(PATH_EXPRESSION_BASE_EXPR, r);
                             Expression expression = 
this.visitPathElement(pathElementContext);
-
-                            boolean isSafeChain = isTrue((Expression) r, 
PATH_EXPRESSION_BASE_EXPR_SAFE_CHAIN);
-                            if (isSafeChain) {
-                                
expression.putNodeMetaData(PATH_EXPRESSION_BASE_EXPR_SAFE_CHAIN, true);
+                            if (isTrue((Expression) r, 
PATH_EXPRESSION_BASE_EXPR_SAFE_CHAIN)) {
+                                
expression.putNodeMetaData(PATH_EXPRESSION_BASE_EXPR_SAFE_CHAIN, Boolean.TRUE);
                             }
-
                             return expression;
                         }
                 );
@@ -4691,8 +4667,8 @@ public class AstBuilder extends 
GroovyParserBaseVisitor<Object> {
         return 
lexer.getInputStream().getText(Interval.of(context.getStart().getStartIndex(), 
context.getStop().getStopIndex()));
     }
 
-    private boolean isTrue(final NodeMetaDataHandler nodeMetaDataHandler, 
final String key) {
-        return Boolean.TRUE.equals(nodeMetaDataHandler.getNodeMetaData(key));
+    private static boolean isTrue(final NodeMetaDataHandler obj, final String 
key) {
+        return Boolean.TRUE.equals(obj.getNodeMetaData(key));
     }
 
     private CompilationFailedException createParsingFailedException(final 
String msg, final GroovyParserRuleContext ctx) {
diff --git a/src/main/java/org/codehaus/groovy/ast/NodeMetaDataHandler.java 
b/src/main/java/org/codehaus/groovy/ast/NodeMetaDataHandler.java
index 95aa7a3a44..ddb485d4f1 100644
--- a/src/main/java/org/codehaus/groovy/ast/NodeMetaDataHandler.java
+++ b/src/main/java/org/codehaus/groovy/ast/NodeMetaDataHandler.java
@@ -27,9 +27,12 @@ import java.util.function.Function;
 
 /**
  * An interface to mark a node being able to handle metadata.
+ *
+ * @since 3.0.0
  */
 @SuppressWarnings({"unchecked", "rawtypes"})
 public interface NodeMetaDataHandler {
+
     /**
      * Gets the node metadata.
      *
@@ -56,7 +59,7 @@ public interface NodeMetaDataHandler {
 
         Map metaDataMap = this.getMetaDataMap();
         if (metaDataMap == null) {
-            metaDataMap = new ListHashMap();
+            metaDataMap = this.newMetaDataMap();
             this.setMetaDataMap(metaDataMap);
         }
         return (T) metaDataMap.computeIfAbsent(key, valFn);
@@ -74,7 +77,7 @@ public interface NodeMetaDataHandler {
         }
         Map metaDataMap = this.getMetaDataMap();
         if (metaDataMap == null) {
-            metaDataMap = new ListHashMap();
+            metaDataMap = this.newMetaDataMap();
             this.setMetaDataMap(metaDataMap);
         }
 
@@ -86,8 +89,7 @@ public interface NodeMetaDataHandler {
      *
      * @param key   the metadata key
      * @param value the metadata value
-     * @throws GroovyBugError if key is null or there is already meta
-     *                        data under that key
+     * @throws GroovyBugError if key is null or there is already metadata for 
key
      */
     default void setNodeMetaData(Object key, Object value) {
         Object old = putNodeMetaData(key, value);
@@ -107,8 +109,11 @@ public interface NodeMetaDataHandler {
 
         Map metaDataMap = this.getMetaDataMap();
         if (metaDataMap == null) {
-            metaDataMap = new ListHashMap();
+            if (value == null) return null;
+            metaDataMap = newMetaDataMap();
             this.setMetaDataMap(metaDataMap);
+        } else if (value == null) {
+            return metaDataMap.remove(key);
         }
         return metaDataMap.put(key, value);
     }
@@ -142,7 +147,16 @@ public interface NodeMetaDataHandler {
         return Collections.unmodifiableMap(metaDataMap);
     }
 
+    
//--------------------------------------------------------------------------
+
     Map<?, ?> getMetaDataMap();
 
+    /**
+     * @since 5.0.0
+     */
+    default Map<?, ?> newMetaDataMap() {
+        return new ListHashMap();
+    }
+
     void setMetaDataMap(Map<?, ?> metaDataMap);
 }
diff --git a/src/main/java/org/codehaus/groovy/util/ListHashMap.java 
b/src/main/java/org/codehaus/groovy/util/ListHashMap.java
index 8fe48a18d8..d40bf1df5e 100644
--- a/src/main/java/org/codehaus/groovy/util/ListHashMap.java
+++ b/src/main/java/org/codehaus/groovy/util/ListHashMap.java
@@ -127,7 +127,7 @@ public class ListHashMap<K,V> implements Map<K,V> {
             }
             if (innerMap != null) {
                 V old = innerMap.put(key, value);
-                size = innerMap.size();
+                if (old == null) size += 1;
                 return old;
             }
             for (int i = 0; i < size; i += 1) {
@@ -138,15 +138,16 @@ public class ListHashMap<K,V> implements Map<K,V> {
                 }
             }
             if (size < keys.length) {
-                values[size] = value;
-                keys[size] = key;
+                int i = (size ++);
+                values[i] = value;
+                keys[i] = key;
             } else { // evolve
                 Map<K,V> map = toMap();
                 map.put(key, value);
                 innerMap = map;
                 clearArrays();
+                size += 1;
             }
-            size += 1;
         }
         return null;
     }
@@ -168,9 +169,9 @@ public class ListHashMap<K,V> implements Map<K,V> {
                     if (size <= keys.length) { // devolve
                         size = 0; Set<Entry<K,V>> entries = 
innerMap.entrySet(); innerMap = null;
                         for (Entry<? extends K, ? extends V> entry : entries) {
-                            values[size] = entry.getValue();
-                            keys[size] = entry.getKey();
-                            size += 1;
+                            int i = size++; // not atomic
+                            values[i] = entry.getValue();
+                            keys[i] = entry.getKey();
                         }
                     }
                 }
@@ -179,14 +180,14 @@ public class ListHashMap<K,V> implements Map<K,V> {
             for (int i = 0; i < size; i += 1) {
                 if (key.equals(keys[i])) {
                     V value = values[i];
-                    size -= 1;
+                    int j = (size -= 1);
                     // if last element is not being removed, shift the last 
element into this slot
-                    if (i < size) {
-                        values[i] = values[size];
-                        keys[i] = keys[size];
+                    if (i < j) {
+                        values[i] = values[j];
+                        keys[i] = keys[j];
                     }
-                    values[size] = null;
-                    keys[size] = null;
+                    values[j] = null;
+                    keys[j] = null;
                     return value;
                 }
             }

Reply via email to