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 2022/07/06 22:50:52 UTC

[groovy] 01/02: GROOVY-6025, GROOVY-7252, GROOVY-9206, GROOVY-9366: attribute value type

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

commit 5fe6fbc7dfef4df52fff6cf96a95b6d46d4fbf3c
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Jul 6 17:12:19 2022 -0500

    GROOVY-6025, GROOVY-7252, GROOVY-9206, GROOVY-9366: attribute value type
---
 .../apache/groovy/ast/tools/ExpressionUtils.java   |  72 ++++++++---
 .../groovy/classgen/AnnotationVisitor.java         | 140 ++++++++++-----------
 .../groovy/control/AnnotationConstantsVisitor.java |  80 +-----------
 src/test/gls/annotations/AnnotationTest.groovy     |  57 ++++++++-
 .../groovy/tools/stubgenerator/Groovy10611.groovy  |   2 +-
 5 files changed, 174 insertions(+), 177 deletions(-)

diff --git a/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java b/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java
index aaf4d3e7a0..f43646e485 100644
--- a/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java
+++ b/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java
@@ -22,6 +22,7 @@ import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.FieldNode;
 import org.codehaus.groovy.ast.expr.BinaryExpression;
+import org.codehaus.groovy.ast.expr.CastExpression;
 import org.codehaus.groovy.ast.expr.ClassExpression;
 import org.codehaus.groovy.ast.expr.ConstantExpression;
 import org.codehaus.groovy.ast.expr.Expression;
@@ -33,17 +34,11 @@ import org.codehaus.groovy.runtime.typehandling.NumberMath;
 
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
+import java.math.BigDecimal;
 import java.util.Arrays;
 import java.util.List;
 import java.util.ListIterator;
 
-import static org.codehaus.groovy.ast.ClassHelper.isWrapperByte;
-import static org.codehaus.groovy.ast.ClassHelper.isWrapperCharacter;
-import static org.codehaus.groovy.ast.ClassHelper.isWrapperDouble;
-import static org.codehaus.groovy.ast.ClassHelper.isWrapperFloat;
-import static org.codehaus.groovy.ast.ClassHelper.isWrapperInteger;
-import static org.codehaus.groovy.ast.ClassHelper.isWrapperLong;
-import static org.codehaus.groovy.ast.ClassHelper.isWrapperShort;
 import static org.codehaus.groovy.syntax.Types.BITWISE_AND;
 import static org.codehaus.groovy.syntax.Types.BITWISE_OR;
 import static org.codehaus.groovy.syntax.Types.BITWISE_XOR;
@@ -55,6 +50,7 @@ import static org.codehaus.groovy.syntax.Types.PLUS;
 import static org.codehaus.groovy.syntax.Types.POWER;
 import static org.codehaus.groovy.syntax.Types.RIGHT_SHIFT;
 import static org.codehaus.groovy.syntax.Types.RIGHT_SHIFT_UNSIGNED;
+import static org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor.inferLoopElementType;
 
 public final class ExpressionUtils {
 
@@ -181,24 +177,27 @@ public final class ExpressionUtils {
                             break;
                     }
                     if (result != null) {
-                        if (isWrapperByte(wrapperType)) {
-                            return configure(be, new ConstantExpression(result.byteValue(), true));
+                        if (ClassHelper.isWrapperInteger(wrapperType)) {
+                            return configure(be, new ConstantExpression(result.intValue(), true));
                         }
-                        if (isWrapperShort(wrapperType)) {
-                            return configure(be, new ConstantExpression(result.shortValue(), true));
+                        if (ClassHelper.isWrapperByte(wrapperType)) {
+                            return configure(be, new ConstantExpression(result.byteValue(), true));
                         }
-                        if (isWrapperLong(wrapperType)) {
+                        if (ClassHelper.isWrapperLong(wrapperType)) {
                             return configure(be, new ConstantExpression(result.longValue(), true));
                         }
-                        if (isWrapperInteger(wrapperType) || isWrapperCharacter(wrapperType)) {
-                            return configure(be, new ConstantExpression(result.intValue(), true));
+                        if (ClassHelper.isWrapperShort(wrapperType)) {
+                            return configure(be, new ConstantExpression(result.shortValue(), true));
                         }
-                        if (isWrapperFloat(wrapperType)) {
+                        if (ClassHelper.isWrapperFloat(wrapperType)) {
                             return configure(be, new ConstantExpression(result.floatValue(), true));
                         }
-                        if (isWrapperDouble(wrapperType)) {
+                        if (ClassHelper.isWrapperDouble(wrapperType)) {
                             return configure(be, new ConstantExpression(result.doubleValue(), true));
                         }
+                        if (ClassHelper.isWrapperCharacter(wrapperType)) {
+                            return configure(be, new ConstantExpression((char) result.intValue(), true));
+                        }
                         return configure(be, new ConstantExpression(result, true));
                     }
                 }
@@ -266,9 +265,10 @@ public final class ExpressionUtils {
      * Handles:
      * <ul>
      *     <li>Property expressions - referencing constants</li>
-     *     <li>Simple binary expressions - String concatenation and numeric +, -, /, *</li>
-     *     <li>List expressions - list of constants</li>
      *     <li>Variable expressions - referencing constants</li>
+     *     <li>Typecast expressions - referencing constants</li>
+     *     <li>Binary expressions - string concatenation and numeric +, -, /, *</li>
+     *     <li>List expressions - list of constants</li>
      * </ul>
      * @param exp the original expression
      * @param attrType the type that the final constant should be
@@ -311,6 +311,39 @@ public final class ExpressionUtils {
                     }
                 }
             }
+        } else if (exp instanceof ConstantExpression) {
+            Object value = ((ConstantExpression) exp).getValue();
+            ClassNode targetType = ClassHelper.getWrapper(attrType);
+            if (value instanceof Integer) {
+                Integer integer = (Integer) value;
+                if (ClassHelper.isWrapperByte(targetType)) {
+                    return configure(exp, new ConstantExpression(integer.byteValue(), true));
+                }
+                if (ClassHelper.isWrapperShort(targetType)) {
+                    return configure(exp, new ConstantExpression(integer.shortValue(), true));
+                }
+                if (ClassHelper.isWrapperCharacter(targetType)) {
+                    return configure(exp, new ConstantExpression((char) integer.intValue(), true));
+                }
+            } else if (value instanceof BigDecimal) {
+                BigDecimal decimal = (BigDecimal) value;
+                if (ClassHelper.isWrapperFloat(targetType)) {
+                    return configure(exp, new ConstantExpression(decimal.floatValue(), true));
+                }
+                if (ClassHelper.isWrapperDouble(targetType)) {
+                    return configure(exp, new ConstantExpression(decimal.doubleValue(), true));
+                }
+            } else if (value instanceof String) {
+                String string = (String) value;
+                if (ClassHelper.isWrapperCharacter(targetType) && string.length() == 1) {
+                    return configure(exp, new ConstantExpression(string.charAt(0), true));
+                }
+            }
+        } else if (exp instanceof CastExpression) {
+            Expression e = transformInlineConstants(((CastExpression) exp).getExpression(), exp.getType());
+            if (ClassHelper.getWrapper(e.getType()).isDerivedFrom(ClassHelper.getWrapper(attrType))) {
+                return e;
+            }
         } else if (exp instanceof BinaryExpression) {
             ConstantExpression ce = transformBinaryConstantExpression((BinaryExpression) exp, attrType);
             if (ce != null) {
@@ -329,8 +362,9 @@ public final class ExpressionUtils {
      * @param attrType the target type
      * @return the transformed list or the original if nothing was changed
      */
-    public static Expression transformListOfConstants(final ListExpression origList, final ClassNode attrType) {
+    public static Expression transformListOfConstants(final ListExpression origList, ClassNode attrType) {
         ListExpression newList = new ListExpression();
+        attrType = inferLoopElementType(attrType);
         boolean changed = false;
         for (Expression e : origList.getExpressions()) {
             try {
diff --git a/src/main/java/org/codehaus/groovy/classgen/AnnotationVisitor.java b/src/main/java/org/codehaus/groovy/classgen/AnnotationVisitor.java
index de0d332dcb..875c588587 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AnnotationVisitor.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AnnotationVisitor.java
@@ -35,16 +35,12 @@ import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.ast.stmt.ReturnStatement;
 import org.codehaus.groovy.control.ErrorCollector;
 import org.codehaus.groovy.control.SourceUnit;
-import org.codehaus.groovy.control.messages.SyntaxErrorMessage;
-import org.codehaus.groovy.syntax.SyntaxException;
 import org.codehaus.groovy.vmplugin.VMPluginFactory;
 
 import java.util.List;
 import java.util.Map;
 
 import static org.apache.groovy.ast.tools.ExpressionUtils.transformInlineConstants;
-import static org.codehaus.groovy.ast.ClassHelper.isClassType;
-import static org.codehaus.groovy.ast.ClassHelper.isStringType;
 
 /**
  * An Annotation visitor responsible for:
@@ -55,23 +51,25 @@ import static org.codehaus.groovy.ast.ClassHelper.isStringType;
  * </ul>
  */
 public class AnnotationVisitor {
+
     private final SourceUnit source;
     private final ErrorCollector errorCollector;
+
     private AnnotationNode annotation;
     private ClassNode reportClass;
 
-    public AnnotationVisitor(SourceUnit source, ErrorCollector errorCollector) {
+    public AnnotationVisitor(final SourceUnit source, final ErrorCollector errorCollector) {
         this.source = source;
         this.errorCollector = errorCollector;
     }
 
-    public void setReportClass(ClassNode cn) {
-        reportClass = cn;
+    public void setReportClass(final ClassNode node) {
+        this.reportClass = node;
     }
 
-    public AnnotationNode visit(AnnotationNode node) {
+    public AnnotationNode visit(final AnnotationNode node) {
         this.annotation = node;
-        this.reportClass = node.getClassNode();
+        setReportClass(node.getClassNode());
 
         if (!isValidAnnotationClass(node.getClassNode())) {
             addError("class " + node.getClassNode().getName() + " is not an annotation");
@@ -88,8 +86,7 @@ public class AnnotationVisitor {
             return node;
         }
 
-        Map<String, Expression> attributes = node.getMembers();
-        for (Map.Entry<String, Expression> entry : attributes.entrySet()) {
+        for (Map.Entry<String, Expression> entry : node.getMembers().entrySet()) {
             String attrName = entry.getKey();
             ClassNode attrType = getAttributeType(node, attrName);
             Expression attrExpr = transformInlineConstants(entry.getValue(), attrType);
@@ -100,7 +97,7 @@ public class AnnotationVisitor {
         return this.annotation;
     }
 
-    private boolean checkIfValidEnumConstsAreUsed(AnnotationNode node) {
+    private boolean checkIfValidEnumConstsAreUsed(final AnnotationNode node) {
         Map<String, Expression> attributes = node.getMembers();
         for (Map.Entry<String, Expression> entry : attributes.entrySet()) {
             if (!validateEnumConstant(entry.getValue()))
@@ -109,7 +106,7 @@ public class AnnotationVisitor {
         return true;
     }
 
-    private boolean validateEnumConstant(Expression exp) {
+    private boolean validateEnumConstant(final Expression exp) {
         if (exp instanceof PropertyExpression) {
             PropertyExpression pe = (PropertyExpression) exp;
             String name = pe.getPropertyAsString();
@@ -134,14 +131,13 @@ public class AnnotationVisitor {
         return true;
     }
 
-    private boolean checkIfMandatoryAnnotationValuesPassed(AnnotationNode node) {
+    private boolean checkIfMandatoryAnnotationValuesPassed(final AnnotationNode node) {
         boolean ok = true;
-        Map attributes = node.getMembers();
         ClassNode classNode = node.getClassNode();
         for (MethodNode mn : classNode.getMethods()) {
             String methodName = mn.getName();
             // if the annotation attribute has a default, getCode() returns a ReturnStatement with the default value
-            if (mn.getCode() == null && !attributes.containsKey(methodName)) {
+            if (mn.getCode() == null && !node.getMembers().containsKey(methodName)) {
                 addError("No explicit/default value found for annotation attribute '" + methodName + "'", node);
                 ok = false;
             }
@@ -149,74 +145,71 @@ public class AnnotationVisitor {
         return ok;
     }
 
-    private ClassNode getAttributeType(AnnotationNode node, String attrName) {
+    private ClassNode getAttributeType(final AnnotationNode node, final String attrName) {
         ClassNode classNode = node.getClassNode();
-        List methods = classNode.getMethods(attrName);
+        List<MethodNode> methods = classNode.getMethods(attrName);
         // if size is >1, then the method was overwritten or something, we ignore that
         // if it is an error, we have to test it at another place. But size==0 is
         // an error, because it means that no such attribute exists.
         if (methods.isEmpty()) {
-            addError("'" + attrName + "'is not part of the annotation " + classNode.getNameWithoutPackage(), node);
+            addError("'" + attrName + "' is not part of the annotation " + classNode.getNameWithoutPackage(), node);
             return ClassHelper.OBJECT_TYPE;
         }
-        MethodNode method = (MethodNode) methods.get(0);
-        return method.getReturnType();
+        return methods.get(0).getReturnType();
     }
 
-    private static boolean isValidAnnotationClass(ClassNode node) {
-        return node.implementsInterface(ClassHelper.Annotation_TYPE);
+    private static boolean isValidAnnotationClass(final ClassNode type) {
+        return type.implementsInterface(ClassHelper.Annotation_TYPE);
     }
 
-    protected void visitExpression(String attrName, Expression attrExp, ClassNode attrType) {
+    protected void visitExpression(final String attrName, final Expression valueExpr, final ClassNode attrType) {
         if (attrType.isArray()) {
             // check needed as @Test(attr = {"elem"}) passes through the parser
-            if (attrExp instanceof ListExpression) {
-                ListExpression le = (ListExpression) attrExp;
+            if (valueExpr instanceof ListExpression) {
+                ListExpression le = (ListExpression) valueExpr;
                 visitListExpression(attrName, le, attrType.getComponentType());
-            } else if (attrExp instanceof ClosureExpression) {
-                addError("Annotation list attributes must use Groovy notation [el1, el2]", attrExp);
+            } else if (valueExpr instanceof ClosureExpression) {
+                addError("Annotation list attributes must use Groovy notation [el1, el2]", valueExpr);
             } else {
                 // treat like a singleton list as per Java
                 ListExpression listExp = new ListExpression();
-                listExp.addExpression(attrExp);
+                listExp.addExpression(valueExpr);
                 if (annotation != null) {
                     annotation.setMember(attrName, listExp);
                 }
                 visitExpression(attrName, listExp, attrType);
             }
-        } else if (ClassHelper.isPrimitiveType(attrType)) {
-            visitConstantExpression(attrName, getConstantExpression(attrExp, attrType), ClassHelper.getWrapper(attrType));
-        } else if (isStringType(attrType)) {
-            visitConstantExpression(attrName, getConstantExpression(attrExp, attrType), ClassHelper.STRING_TYPE);
-        } else if (isClassType(attrType)) {
-            if (!(attrExp instanceof ClassExpression || attrExp instanceof ClosureExpression)) {
-                addError("Only classes and closures can be used for attribute '" + attrName + "'", attrExp);
+        } else if (ClassHelper.isPrimitiveType(attrType) || ClassHelper.isStringType(attrType)) {
+            visitConstantExpression(attrName, getConstantExpression(valueExpr, attrType), ClassHelper.getWrapper(attrType));
+        } else if (ClassHelper.isClassType(attrType)) {
+            if (!(valueExpr instanceof ClassExpression || valueExpr instanceof ClosureExpression)) {
+                addError("Only classes and closures can be used for attribute '" + attrName + "'", valueExpr);
             }
         } else if (attrType.isDerivedFrom(ClassHelper.Enum_Type)) {
-            if (attrExp instanceof PropertyExpression) {
-                visitEnumExpression(attrName, (PropertyExpression) attrExp, attrType);
-            } else if (attrExp instanceof ConstantExpression) {
-                visitConstantExpression(attrName, getConstantExpression(attrExp, attrType), attrType);
+            if (valueExpr instanceof PropertyExpression) {
+                visitEnumExpression(attrName, (PropertyExpression) valueExpr, attrType);
+            } else if (valueExpr instanceof ConstantExpression) {
+                visitConstantExpression(attrName, getConstantExpression(valueExpr, attrType), attrType);
             } else {
-                addError("Expected enum value for attribute " + attrName, attrExp);
+                addError("Expected enum value for attribute " + attrName, valueExpr);
             }
         } else if (isValidAnnotationClass(attrType)) {
-            if (attrExp instanceof AnnotationConstantExpression) {
-                visitAnnotationExpression(attrName, (AnnotationConstantExpression) attrExp, attrType);
+            if (valueExpr instanceof AnnotationConstantExpression) {
+                visitAnnotationExpression(attrName, (AnnotationConstantExpression) valueExpr, attrType);
             } else {
-                addError("Expected annotation of type '" + attrType.getName() + "' for attribute " + attrName, attrExp);
+                addError("Expected annotation of type '" + attrType.getName() + "' for attribute " + attrName, valueExpr);
             }
         } else {
-            addError("Unexpected type " + attrType.getName(), attrExp);
+            addError("Unexpected type " + attrType.getName(), valueExpr);
         }
     }
 
-    public void checkReturnType(ClassNode attrType, ASTNode node) {
+    public void checkReturnType(final ClassNode attrType, final ASTNode node) {
         if (attrType.isArray()) {
             checkReturnType(attrType.getComponentType(), node);
         } else if (ClassHelper.isPrimitiveType(attrType)) {
-        } else if (isStringType(attrType)) {
-        } else if (isClassType(attrType)) {
+        } else if (ClassHelper.isStringType(attrType)) {
+        } else if (ClassHelper.isClassType(attrType)) {
         } else if (attrType.isDerivedFrom(ClassHelper.Enum_Type)) {
         } else if (isValidAnnotationClass(attrType)) {
         } else {
@@ -224,7 +217,7 @@ public class AnnotationVisitor {
         }
     }
 
-    private ConstantExpression getConstantExpression(Expression exp, ClassNode attrType) {
+    private ConstantExpression getConstantExpression(final Expression exp, final ClassNode attrType) {
         Expression result = exp;
         if (!(result instanceof ConstantExpression)) {
             result = transformInlineConstants(result, attrType);
@@ -232,6 +225,7 @@ public class AnnotationVisitor {
         if (result instanceof ConstantExpression) {
             return (ConstantExpression) result;
         }
+
         String base = "Expected '" + exp.getText() + "' to be an inline constant of type " + attrType.getName();
         if (exp instanceof PropertyExpression) {
             addError(base + " not a property expression", exp);
@@ -240,56 +234,48 @@ public class AnnotationVisitor {
         } else {
             addError(base, exp);
         }
+
         ConstantExpression ret = new ConstantExpression(null);
         ret.setSourcePosition(exp);
         return ret;
     }
 
-    protected void visitAnnotationExpression(String attrName, AnnotationConstantExpression expression, ClassNode attrType) {
-        AnnotationNode annotationNode = (AnnotationNode) expression.getValue();
-        AnnotationVisitor visitor = new AnnotationVisitor(this.source, this.errorCollector);
-        // TODO track Deprecated usage and give a warning?
-        visitor.visit(annotationNode);
-    }
-
-    protected void visitListExpression(String attrName, ListExpression listExpr, ClassNode elementType) {
+    protected void visitListExpression(final String attrName, final ListExpression listExpr, final ClassNode elementType) {
         for (Expression expression : listExpr.getExpressions()) {
             visitExpression(attrName, expression, elementType);
         }
     }
 
-    protected void visitConstantExpression(String attrName, ConstantExpression constExpr, ClassNode attrType) {
-        ClassNode constType = constExpr.getType();
-        ClassNode wrapperType = ClassHelper.getWrapper(constType);
-        if (!hasCompatibleType(attrType, wrapperType)) {
-            addError("Attribute '" + attrName + "' should have type '" + attrType.getName()
-                    + "'; but found type '" + constType.getName() + "'", constExpr);
+    protected void visitEnumExpression(final String attrName, final PropertyExpression valueExpr, final ClassNode attrType) {
+        ClassNode valueType = valueExpr.getObjectExpression().getType();
+        if (!valueType.isDerivedFrom(attrType)) {
+            addError("Attribute '" + attrName + "' should have type '" + attrType.getName() + "' (Enum), but found " + valueType.getName(), valueExpr);
         }
     }
 
-    private static boolean hasCompatibleType(ClassNode attrType, ClassNode wrapperType) {
-        return wrapperType.isDerivedFrom(ClassHelper.getWrapper(attrType));
+    protected void visitConstantExpression(final String attrName, final ConstantExpression valueExpr, final ClassNode attrType) {
+        ClassNode valueType = valueExpr.getType();
+        if (!ClassHelper.getWrapper(valueType).isDerivedFrom(ClassHelper.getWrapper(attrType))) {
+            addError("Attribute '" + attrName + "' should have type '" + attrType.getName() + "'; but found type '" + valueType.getName() + "'", valueExpr);
+        }
     }
 
-    protected void visitEnumExpression(String attrName, PropertyExpression propExpr, ClassNode attrType) {
-        if (!propExpr.getObjectExpression().getType().isDerivedFrom(attrType)) {
-            addError("Attribute '" + attrName + "' should have type '" + attrType.getName() + "' (Enum), but found "
-                    + propExpr.getObjectExpression().getType().getName(),
-                    propExpr);
-        }
+    protected void visitAnnotationExpression(final String attrName, final AnnotationConstantExpression valueExpr, final ClassNode attrType) {
+        AnnotationNode annotationNode = (AnnotationNode) valueExpr.getValue();
+        AnnotationVisitor visitor = new AnnotationVisitor(this.source, this.errorCollector);
+        // TODO: Track @Deprecated usage and give a warning?
+        visitor.visit(annotationNode);
     }
 
-    protected void addError(String msg) {
+    protected void addError(final String msg) {
         addError(msg, this.annotation);
     }
 
-    protected void addError(String msg, ASTNode expr) {
-        this.errorCollector.addErrorAndContinue(
-                new SyntaxErrorMessage(new SyntaxException(msg + " in @" + this.reportClass.getName() + '\n', expr.getLineNumber(), expr.getColumnNumber(), expr.getLastLineNumber(), expr.getLastColumnNumber()), this.source)
-        );
+    protected void addError(final String msg, final ASTNode node) {
+        this.errorCollector.addErrorAndContinue(msg + " in @" + this.reportClass.getName() + '\n', node, this.source);
     }
 
-    public void checkCircularReference(ClassNode searchClass, ClassNode attrType, Expression startExp) {
+    public void checkCircularReference(final ClassNode searchClass, final ClassNode attrType, final Expression startExp) {
         if (!isValidAnnotationClass(attrType)) return;
         if (!(startExp instanceof AnnotationConstantExpression)) {
             addError("Found '" + startExp.getText() + "' when expecting an Annotation Constant", startExp);
diff --git a/src/main/java/org/codehaus/groovy/control/AnnotationConstantsVisitor.java b/src/main/java/org/codehaus/groovy/control/AnnotationConstantsVisitor.java
index 7de3e635a5..bb1760ac67 100644
--- a/src/main/java/org/codehaus/groovy/control/AnnotationConstantsVisitor.java
+++ b/src/main/java/org/codehaus/groovy/control/AnnotationConstantsVisitor.java
@@ -19,28 +19,13 @@
 package org.codehaus.groovy.control;
 
 import org.codehaus.groovy.ast.ClassCodeVisitorSupport;
-import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.ast.expr.CastExpression;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
-import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.ast.stmt.ExpressionStatement;
 import org.codehaus.groovy.ast.stmt.ReturnStatement;
 import org.codehaus.groovy.ast.stmt.Statement;
-import org.codehaus.groovy.classgen.Verifier;
-
-import java.math.BigDecimal;
 
 import static org.apache.groovy.ast.tools.ExpressionUtils.transformInlineConstants;
-import static org.codehaus.groovy.ast.ClassHelper.isBigDecimalType;
-import static org.codehaus.groovy.ast.ClassHelper.isStringType;
-import static org.codehaus.groovy.ast.ClassHelper.isWrapperByte;
-import static org.codehaus.groovy.ast.ClassHelper.isWrapperCharacter;
-import static org.codehaus.groovy.ast.ClassHelper.isWrapperDouble;
-import static org.codehaus.groovy.ast.ClassHelper.isWrapperFloat;
-import static org.codehaus.groovy.ast.ClassHelper.isWrapperInteger;
-import static org.codehaus.groovy.ast.ClassHelper.isWrapperShort;
 
 /**
  * Resolves constants in annotation definitions.
@@ -68,72 +53,11 @@ public class AnnotationConstantsVisitor extends ClassCodeVisitorSupport {
             Statement statement = node.getFirstStatement();
             if (statement instanceof ReturnStatement) {
                 ReturnStatement rs = (ReturnStatement) statement;
-                rs.setExpression(transformConstantExpression(rs.getExpression(), node.getReturnType()));
+                rs.setExpression(transformInlineConstants(rs.getExpression(), node.getReturnType()));
             } else if (statement instanceof ExpressionStatement) {
                 ExpressionStatement es = (ExpressionStatement) statement;
-                es.setExpression(transformConstantExpression(es.getExpression(), node.getReturnType()));
-            }
-        }
-    }
-
-    private static Expression transformConstantExpression(Expression val, ClassNode returnType) {
-        ClassNode returnWrapperType = ClassHelper.getWrapper(returnType);
-        if (val instanceof ConstantExpression) {
-            Expression result = revertType(val, returnWrapperType);
-            if (result != null) {
-                return result;
+                es.setExpression(transformInlineConstants(es.getExpression(), node.getReturnType()));
             }
-            return val;
-        }
-        if (val instanceof CastExpression) {
-            CastExpression castExp = (CastExpression) val;
-            Expression castee = castExp.getExpression();
-            if (castee instanceof ConstantExpression) {
-                if (ClassHelper.getWrapper(castee.getType()).isDerivedFrom(returnWrapperType)) {
-                    return castee;
-                }
-                Expression result = revertType(castee, returnWrapperType);
-                if (result != null) {
-                    return result;
-                }
-                return castee;
-            }
-        }
-        return transformInlineConstants(val, returnType);
-    }
-
-    private static Expression revertType(Expression val, ClassNode returnWrapperType) {
-        ConstantExpression ce = (ConstantExpression) val;
-        if (isWrapperCharacter(returnWrapperType) && isStringType(val.getType())) {
-            return configure(val, Verifier.transformToPrimitiveConstantIfPossible((ConstantExpression) val));
         }
-        ClassNode valWrapperType = ClassHelper.getWrapper(val.getType());
-        if (isWrapperInteger(valWrapperType)) {
-            Integer i = (Integer) ce.getValue();
-            if (isWrapperCharacter(returnWrapperType)) {
-                return configure(val, new ConstantExpression((char) i.intValue(), true));
-            }
-            if (isWrapperShort(returnWrapperType)) {
-                return configure(val, new ConstantExpression(i.shortValue(), true));
-            }
-            if (isWrapperByte(returnWrapperType)) {
-                return configure(val, new ConstantExpression(i.byteValue(), true));
-            }
-        }
-        if (isBigDecimalType(valWrapperType)) {
-            BigDecimal bd = (BigDecimal) ce.getValue();
-            if (isWrapperFloat(returnWrapperType)) {
-                return configure(val, new ConstantExpression(bd.floatValue(), true));
-            }
-            if (isWrapperDouble(returnWrapperType)) {
-                return configure(val, new ConstantExpression(bd.doubleValue(), true));
-            }
-        }
-        return null;
-    }
-
-    private static Expression configure(Expression orig, Expression result) {
-        result.setSourcePosition(orig);
-        return result;
     }
 }
diff --git a/src/test/gls/annotations/AnnotationTest.groovy b/src/test/gls/annotations/AnnotationTest.groovy
index 291ec12af9..c59279a46c 100644
--- a/src/test/gls/annotations/AnnotationTest.groovy
+++ b/src/test/gls/annotations/AnnotationTest.groovy
@@ -18,6 +18,7 @@
  */
 package gls.annotations
 
+import groovy.test.NotYetImplemented
 import org.junit.Test
 
 import static groovy.test.GroovyAssert.assertScript
@@ -619,6 +620,42 @@ final class AnnotationTest {
         '''
     }
 
+    @Test // GROOVY-7252
+    void testAttributeValueConstants7() {
+        assertScript shell, '''
+            @interface A {
+                short value()
+            }
+
+            @A(12345)
+            def local
+        '''
+    }
+
+    @Test // GROOVY-9366
+    void testAttributeValueConstants8() {
+        assertScript shell, '''
+            @interface A {
+                byte value()
+            }
+
+            @A(0xFF)
+            def local
+        '''
+    }
+
+    @Test // GROOVY-9206
+    void testAttributeValueConstants9() {
+        assertScript shell, '''
+            @interface A {
+                char value()
+            }
+
+            @A( 'c' )
+            def local
+        '''
+    }
+
     @Test
     void testRuntimeRetentionAtAllLevels() {
         assertScript shell, '''
@@ -748,9 +785,9 @@ final class AnnotationTest {
                 int i1() default 0
                 int i2() default (int)1
                 short s1() default 2
-                short s2() default (byte)3
+                short s2() default (short)3
                 short s3() default (Short)4
-                short s4() default (int)5
+                short s4() default 5 as short
                 byte b() default 6
                 char c1() default 65
                 char c2() default 'B'
@@ -765,6 +802,7 @@ final class AnnotationTest {
                 double d3() default (double)2.2
                 double d4() default 2.3 as double
             }
+
             @Foo method() {}
             def string = getClass().getMethod('method').getAnnotation(Foo).toString()[5..-2].tokenize(', ').sort().join('|')
             assert string == 'b=6|c1=A|c2=B|c3=C|c4=D|d1=2.0|d2=2.1|d3=2.2|d4=2.3|f1=1.0|f2=1.1|f3=1.2|f4=1.3|i1=0|i2=1|s1=2|s2=3|s3=4|s4=5' ||
@@ -775,6 +813,21 @@ final class AnnotationTest {
         '''
     }
 
+    @NotYetImplemented @Test // GROOVY-6025
+    void testAnnotationDefinitionDefaultValues2() {
+        assertScript shell, '''
+            @interface A {
+                short s1() default (byte)1
+                short s2() default (char)2
+                short s3() default (long)3
+            }
+
+            assert A.getMethod('s1').defaultValue == 1
+            assert A.getMethod('s2').defaultValue == 2
+            assert A.getMethod('s3').defaultValue == 3
+        '''
+    }
+
     @Test // GROOVY-6093
     void testAnnotationOnEnumConstant() {
         assertScript shell, '''
diff --git a/src/test/org/codehaus/groovy/tools/stubgenerator/Groovy10611.groovy b/src/test/org/codehaus/groovy/tools/stubgenerator/Groovy10611.groovy
index f2cca7f3f6..824f338751 100644
--- a/src/test/org/codehaus/groovy/tools/stubgenerator/Groovy10611.groovy
+++ b/src/test/org/codehaus/groovy/tools/stubgenerator/Groovy10611.groovy
@@ -44,7 +44,7 @@ final class Groovy10611 extends StringSourcesStubTestCase {
     void verifyStubs() {
         String stub = stubJavaSourceFor('C')
         assert stub.contains('final long LONG = 123456;');
-        assert stub.contains('final float FLOAT = 78.90;');
+        assert stub.contains('final float FLOAT = 78.9f;');
         assert stub.contains('final java.lang.String STRING = "xy";');
     }
 }