What's the issue?
The gaps
1. Kotlin: Flag.Enum is never set on enum entries (one-line fix)
KotlinTypeMapping.kt:1171 — variableType(FirVariable, …) computes flags via mapToFlagsBitmap(visibility, modality, isStatic) with no enum-entry branch, even though enum entries flow through this very method (:519-520) and the enum class does get the bit (:446-447, flags or (1L shl 14)). Fix: add the bit when variable is FirEnumEntry. Unblocks AttributeValue#isEnumConstant(..) on Kotlin.
2. Groovy: property-access references carry no fieldType at all
GroovyParserVisitor#visitPropertyExpression converts the property name to a J.Identifier with fieldType hard-coded null — the resolved FieldNode is never looked up, although GroovyTypeMapping.variableType(FieldNode) exists and declared enum constants get proper attribution (GroovyParserVisitor:850). Groovy's enum-constant FieldNodes carry ACC_ENUM at Phases.CANONICALIZATION (set by EnumHelper), so attaching typeMapping.variableType(classNode.getField(name)) when the receiver's static type resolves would fix enum discrimination and give getReferencedField() to all Groovy constant references, including idiomatic bare class refs (@Foo(type = String)). Needs scoping to statically unambiguous receivers (dynamic dispatch).
3. Both: no JavaType.Annotation element values → no constant fold
Neither type mapping constructs ElementValues (zero references in either module), so AttributeValue#getConstantValue() cannot resolve Constants.NAME on these sources, while javac paths fold even binary-dependency constants (ReloadableJava17TypeMapping.listAnnotations:644, Attribute.Constant fold at :704). Larger effort — possibly split per language.
4. Both: list/collection literals are opaque to array normalization
G.ListLiteral/K.ListLiteral are not J.NewArray and cannot be referenced from rewrite-java, so AttributeValue#getElements() returns them as one opaque value. This one is likely not a parser fix (mapping them to J.NewArray would break print fidelity) — it wants a trait extension seam or a shared interface in rewrite-java. Listed here for completeness; could be split out.
Expected behavior
The @ExpectedToFail test markers: ENUM_CONSTANT:isEnum=true, folded CONSTANT_REFERENCE:n, ARRAY:elements=2, and CLASS_LITERAL for Groovy bare class references.
What's the issue?
AttributeValuetrait (Annotatedtrait cannot read non-literal attribute values (class literals, enum constants, constant references) #8160), which classifies annotation attribute values syntax-first and discriminates enum constants viaFlag.Enum(JVMSACC_ENUM) on the referencedJavaType.Variable— the contract javac-attributed Java fulfills. On Kotlin and Groovy sources the same code degrades (enum constants classify asCONSTANT_REFERENCE, constant references don't fold), not because of the trait but because of parser/type-mapping gaps. The divergences are captured as@ExpectedToFailtests inrewrite-groovy/.../AttributeValueTraitTestandrewrite-kotlin/.../AttributeValueTraitTest, asserting the Java-aligned semantics — each flips red the moment its gap is fixed.The gaps
1. Kotlin:Flag.Enumis never set on enum entries (one-line fix)KotlinTypeMapping.kt:1171—variableType(FirVariable, …)computes flags viamapToFlagsBitmap(visibility, modality, isStatic)with no enum-entry branch, even though enum entries flow through this very method (:519-520) and the enum class does get the bit (:446-447,flags or (1L shl 14)). Fix: add the bit whenvariable is FirEnumEntry. UnblocksAttributeValue#isEnumConstant(..)on Kotlin.2. Groovy: property-access references carry no
fieldTypeat allGroovyParserVisitor#visitPropertyExpressionconverts the property name to aJ.IdentifierwithfieldTypehard-codednull— the resolvedFieldNodeis never looked up, althoughGroovyTypeMapping.variableType(FieldNode)exists and declared enum constants get proper attribution (GroovyParserVisitor:850). Groovy's enum-constantFieldNodes carryACC_ENUMatPhases.CANONICALIZATION(set byEnumHelper), so attachingtypeMapping.variableType(classNode.getField(name))when the receiver's static type resolves would fix enum discrimination and givegetReferencedField()to all Groovy constant references, including idiomatic bare class refs (@Foo(type = String)). Needs scoping to statically unambiguous receivers (dynamic dispatch).3. Both: no
JavaType.Annotationelement values → no constant foldNeither type mapping constructs
ElementValues (zero references in either module), soAttributeValue#getConstantValue()cannot resolveConstants.NAMEon these sources, while javac paths fold even binary-dependency constants (ReloadableJava17TypeMapping.listAnnotations:644,Attribute.Constantfold at:704). Larger effort — possibly split per language.4. Both: list/collection literals are opaque to array normalization
G.ListLiteral/K.ListLiteralare notJ.NewArrayand cannot be referenced from rewrite-java, soAttributeValue#getElements()returns them as one opaque value. This one is likely not a parser fix (mapping them toJ.NewArraywould break print fidelity) — it wants a trait extension seam or a shared interface in rewrite-java. Listed here for completeness; could be split out.Expected behavior
The
@ExpectedToFailtest markers:ENUM_CONSTANT:isEnum=true, foldedCONSTANT_REFERENCE:n,ARRAY:elements=2, andCLASS_LITERALfor Groovy bare class references.