Skip to content

AddOrUpdateAnnotationAttribute: Handle fully qualified enum values#6719

Merged
Jenson3210 merged 18 commits intomainfrom
Jenson3210/enum-import-annotation
Feb 12, 2026
Merged

AddOrUpdateAnnotationAttribute: Handle fully qualified enum values#6719
Jenson3210 merged 18 commits intomainfrom
Jenson3210/enum-import-annotation

Conversation

@Jenson3210
Copy link
Copy Markdown
Contributor

@Jenson3210 Jenson3210 commented Feb 12, 2026

New functionalities

  • Import and shorten fully qualified enum values

    // Before
    @Foo
    // After (with attributeValue="org.example.Values.ONE")
    import org.example.Values;
    @Foo(Values.ONE)
  • Append class values to existing single-class annotations

    // Before
    @Foo(Integer.class)
    // After (with attributeValue="Long.class", appendArray=true)
    @Foo({Integer.class, Long.class})

Bug fixes

  • Empty array handling with appendArray=true

    // Before
    @Foo(value = {})
    // Was producing: @Foo({, "hello"})
    // Now correctly: @Foo("hello")
  • Attribute name vs value check in array updates

    // Was checking attributeValue instead of attributeName when updating arrays
  • Comma-separated class values incorrectly matched as FQ class

    // "Integer.class,Long.class" was incorrectly treated as a single FQ class
    // Now correctly parsed as multiple class values
  • Missing type info when appending FQ class values

    // Before
    @Foo(Integer.class)
    // After (with attributeValue="com.example.MyClass.class", appendArray=true)
    import com.example.MyClass;
    @Foo({Integer.class, MyClass.class})  // MyClass.class now has proper type info

When adding an enum value to an annotation attribute using a fully qualified
name like org.example.Values.ONE, the recipe now:
- Adds an import for the enum class (org.example.Values)
- Uses the shortened form in the annotation (Values.ONE)

This matches the existing behavior for fully qualified class references
ending in .class.
The isFullyQualifiedEnumValue check now also verifies that the attribute
type is not a String. This prevents dotted string values like
"some.dotted.value" from being incorrectly treated as fully qualified
enum references.
Without type information, we cannot reliably distinguish between a dotted
string value and a fully qualified enum reference. This change ensures we
only treat values as enums when we have the annotation method's return
type available.
Added regex check to ensure the value only contains valid Java identifier
characters (letters, digits, underscores, dollar signs, and dots). Values
containing spaces, quotes, or other special characters are not valid enum
references.
@Jenson3210 Jenson3210 force-pushed the Jenson3210/enum-import-annotation branch from c318962 to 0db57f2 Compare February 12, 2026 08:41
@Jenson3210 Jenson3210 requested a review from timtebeek February 12, 2026 08:45
@Jenson3210 Jenson3210 marked this pull request as ready for review February 12, 2026 08:45
When appendArray=true and the annotation attribute is a Class<?>[] array
type with an existing single class value (e.g. @foo(Integer.class)),
the recipe now properly converts it to an array containing both the
existing and new values (e.g. @foo({Integer.class, Long.class})).

This works for both implicit value attributes (@foo(Integer.class)) and
named attributes (@foo(classes = Integer.class)).
@Jenson3210 Jenson3210 marked this pull request as draft February 12, 2026 09:11
When appendArray=true and the existing annotation has an empty array
initializer (e.g. @foo(value = {})), the J.Empty element should be
filtered out before appending new values. This prevents invalid output
like @foo({, "hello"}).
- Add test for appending string to existing value array
- Add test for replacing string in existing value array without append
- Fix ImportResource mock to include all attributes (value, locations, reader)
The condition was incorrectly checking attributeValue against "value"
when it should check attributeName. This bug could cause incorrect
behavior when updating array values for non-value attributes.
- isFullyQualifiedClass() now excludes comma-separated values to prevent
  incorrectly treating "Integer.class,Long.class" as a single FQ class
- Reuse isFullyQualifiedClass() instead of duplicating the check
- Add getAttributeValuesAsArray() for non-string array values (no quotes)
- Wrap comma-separated values in braces for array-typed value attributes
When appending a fully qualified class (like com.example.MyClass.class)
to an existing class array annotation attribute:

1. Use JavaTemplate.builder() with dependsOn to provide a class stub
   so the created expression has proper type information
2. Use the FQ class name in the template so it can resolve against
   the stub
3. Add ShortenFullyQualifiedTypeReferences as doAfterVisit to shorten
   the FQ name to the simple name (MyClass.class)
4. Fix attributeNameOrValIsAlreadyPresent to handle FQ class names
   when checking for duplicates by comparing both the full string
   and the simplified class name
5. Fix maybeAddImport to use onlyIfReferenced=false for FQ classes
   (same as we did for enums)
@Jenson3210 Jenson3210 marked this pull request as ready for review February 12, 2026 10:49
- Replace attributeIsString check with attributeIsEnum for FQ enum detection
- Add comments explaining why onlyIfReferenced=false is needed
Copy link
Copy Markdown
Member

@timtebeek timtebeek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat addition, thanks! Good to get more mileage out of this recipe with some bugs squashed to boot.

@github-project-automation github-project-automation Bot moved this from In Progress to Ready to Review in OpenRewrite Feb 12, 2026
Restore ShortenFullyQualifiedTypeReferences which is needed when the
FQ class is in the same package as the current file.
@Jenson3210 Jenson3210 merged commit f495718 into main Feb 12, 2026
1 check passed
@Jenson3210 Jenson3210 deleted the Jenson3210/enum-import-annotation branch February 12, 2026 14:35
@github-project-automation github-project-automation Bot moved this from Ready to Review to Done in OpenRewrite Feb 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

2 participants