Skip to content

Commit

Permalink
Add append functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
nielsdebruin committed Nov 14, 2024
1 parent 77e00ec commit 268f576
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

import org.junit.jupiter.api.Test;
import org.openrewrite.test.RewriteTest;
import org.openrewrite.test.SourceSpec;
import org.openrewrite.test.SourceSpecs;

import static org.openrewrite.java.Assertions.java;

Expand All @@ -25,7 +27,7 @@ class AddOrUpdateAnnotationAttributeTest implements RewriteTest {
@Test
void addValueAttribute() {
rewriteRun(
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.example.Foo", null, "hello", null)),
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.example.Foo", null, "hello", null, false)),
java(
"""
package org.example;
Expand Down Expand Up @@ -56,7 +58,7 @@ public class A {
@Test
void addValueAttributeClass() {
rewriteRun(
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.example.Foo", null, "Integer.class", null)),
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.example.Foo", null, "Integer.class", null, false)),
java(
"""
package org.example;
Expand Down Expand Up @@ -87,7 +89,7 @@ public class A {
@Test
void addValueAttributeFullyQualifiedClass() {
rewriteRun(
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.example.Foo", null, "java.math.BigDecimal.class", null)),
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.example.Foo", null, "java.math.BigDecimal.class", null, null)),
java(
"""
package org.example;
Expand Down Expand Up @@ -118,7 +120,7 @@ public class A {
@Test
void updateValueAttribute() {
rewriteRun(
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.example.Foo", null, "hello", null)),
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.example.Foo", null, "hello", null, null)),
java(
"""
package org.example;
Expand Down Expand Up @@ -150,7 +152,7 @@ public class A {
@Test
void updateValueAttributeClass() {
rewriteRun(
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.example.Foo", null, "Integer.class", null)),
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.example.Foo", null, "Integer.class", null, false)),
java(
"""
package org.example;
Expand Down Expand Up @@ -182,7 +184,7 @@ public class A {
@Test
void removeValueAttribute() {
rewriteRun(
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.example.Foo", null, null, null)),
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.example.Foo", null, null, null, null)),
java(
"""
package org.example;
Expand Down Expand Up @@ -214,7 +216,7 @@ public class A {
@Test
void removeValueAttributeClass() {
rewriteRun(
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.example.Foo", null, null, null)),
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.example.Foo", null, null, null, false)),
java(
"""
package org.example;
Expand Down Expand Up @@ -245,7 +247,7 @@ public class A {

@Test
void addNamedAttribute() {
rewriteRun(spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.junit.Test", "timeout", "500", null)),
rewriteRun(spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.junit.Test", "timeout", "500", null, false)),
java(
"""
package org.junit;
Expand Down Expand Up @@ -282,7 +284,7 @@ void foo() {
@Test
void replaceAttribute() {
rewriteRun(
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.junit.Test", "timeout", "500", null)),
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.junit.Test", "timeout", "500", null, false)),
java(
"""
package org.junit;
Expand Down Expand Up @@ -319,7 +321,7 @@ void foo() {
@Test
void removeAttribute() {
rewriteRun(
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.junit.Test", "timeout", null, null)),
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.junit.Test", "timeout", null, null, false)),
java(
"""
package org.junit;
Expand Down Expand Up @@ -356,7 +358,7 @@ void foo() {
@Test
void preserveExistingAttributes() {
rewriteRun(
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.junit.Test", "timeout", "500", null)),
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.junit.Test", "timeout", "500", null, null)),
java(
"""
package org.junit;
Expand Down Expand Up @@ -394,7 +396,7 @@ void foo() {

@Test
void implicitValueToExplicitValue() {
rewriteRun(spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.junit.Test", "other", "1", null)),
rewriteRun(spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.junit.Test", "other", "1", null, false)),
java(
"""
package org.junit;
Expand Down Expand Up @@ -431,7 +433,7 @@ void foo() {

@Test
void implicitValueToExplicitValueClass() {
rewriteRun(spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.junit.Test", "other", "1", null)),
rewriteRun(spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.junit.Test", "other", "1", null, false)),
java(
"""
package org.junit;
Expand Down Expand Up @@ -469,7 +471,7 @@ void foo() {
@Test
void dontChangeWhenSetToAddOnly() {
rewriteRun(
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.junit.Test", "other", "1", true)),
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.junit.Test", "other", "1", true, false)),
java(
"""
package org.junit;
Expand Down Expand Up @@ -500,6 +502,7 @@ void arrayInAnnotationAttribute() {
"org.example.Foo",
"array",
"newTest",
false,
false)),
java(
"""
Expand Down Expand Up @@ -535,6 +538,7 @@ void arrayInputMoreThanOneInAnnotationAttribute() {
"org.example.Foo",
"array",
"newTest1,newTest2",
false,
false)),
java(
"""
Expand Down Expand Up @@ -570,7 +574,7 @@ void addArrayInputInAnnotationAttribute() {
"org.example.Foo",
"array",
"newTest1,newTest2",
false)),
false, false)),
java(
"""
package org.example;
Expand Down Expand Up @@ -598,14 +602,49 @@ public class A {
);
}

@Test
void addArrayInputInAnnotationAttributeEmptyBrackets() {
rewriteRun(
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute(
"org.example.Foo",
"array",
"newTest1,newTest2",
false, false)),
java(
"""
package org.example;
public @interface Foo {
String[] array() default {};
}
"""
),
java(
"""
import org.example.Foo;
@Foo()
public class A {
}
""",
"""
import org.example.Foo;
@Foo(array = {"newTest1", "newTest2"})
public class A {
}
"""
)
);
}

@Test
void removeArrayInputInAnnotationAttribute() {
rewriteRun(
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute(
"org.example.Foo",
"array",
null,
null)),
null, false)),
java(
"""
package org.example;
Expand Down Expand Up @@ -640,7 +679,7 @@ void addOtherAttributeInArrayAnnotation() {
"org.example.Foo",
"string",
"test",
null)),
null, false)),
java(
"""
package org.example;
Expand Down Expand Up @@ -676,7 +715,8 @@ void appendSingleValueToExistingArrayAttribute() {
"org.example.Foo",
"array",
"b",
false)),
false,
true)),
java(
"""
package org.example;
Expand Down Expand Up @@ -711,7 +751,8 @@ void appendMultipleValuesToExistingArrayAttribute() {
"org.example.Foo",
"array",
"b,c",
false)),
false,
true)),
java(
"""
package org.example;
Expand Down Expand Up @@ -739,16 +780,15 @@ public class A {
);
}



@Test
void appendMultipleValuesToExistingArrayAttributeWithOverlap() {
rewriteRun(
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute(
"org.example.Foo",
"array",
"b,c",
false)),
false,
true)),
java(
"""
package org.example;
Expand All @@ -768,8 +808,45 @@ public class A {
"""
import org.example.Foo;
// What would be desired here????
@Foo(array = {"a", "b", "c"})
public class A {
}
"""
)
);
}

@Test
void appendMultipleValuesToExistingArrayAttributeNonSet() {
rewriteRun(
spec -> spec.recipe(new AddOrUpdateAnnotationAttribute(
"org.example.Foo",
"array",
"b,c",
true,
true)),
java(
"""
package org.example;
public @interface Foo {
String[] array() default {};
}
public class A {
}
"""
),
java(
"""
import org.example.Foo;
@Foo(array = {"a", "b"})
public class A {
}
""",
"""
import org.example.Foo;
@Foo(array = {"a", "b", "b", "c"})
public class A {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ public String getDescription() {
@Nullable
Boolean addOnly;

@Option(displayName = "Append array",
description = "If the attribute is an array, setting this option to `true` will append the value(s). " +
"In conjunction with `addOnly`, it is possible to control duplicates:" +
"`addOnly=true`, always append. " +
"`addOnly=false`, only append if the value is not already present.")
@Nullable
Boolean appendArray;

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
return Preconditions.check(new UsesType<>(annotationType, false), new JavaIsoVisitor<ExecutionContext>() {
Expand Down Expand Up @@ -127,6 +135,17 @@ public J.Annotation visitAnnotation(J.Annotation a, ExecutionContext ctx) {
List<Expression> jLiteralList = ((J.NewArray) as.getAssignment()).getInitializer();
String attributeValueCleanedUp = attributeValue.replaceAll("\\s+","").replaceAll("[\\s+{}\"]","");
List<String> attributeList = Arrays.asList(attributeValueCleanedUp.contains(",") ? attributeValueCleanedUp.split(",") : new String[]{attributeValueCleanedUp});
if (Boolean.TRUE.equals(appendArray)) {
for (int i = 0, j = jLiteralList.size(); i < attributeList.size(); j++, i++) {
String newAttributeListValue = maybeQuoteStringArgument(attributeName, attributeList.get(i), finalA);
if (Boolean.FALSE.equals(addOnly) && attributeValIsAlreadyPresentOrNull(jLiteralList, newAttributeListValue)) {
j--;
continue;
}
jLiteralList.add(j, new J.Literal(Tree.randomId(), jLiteralList.get(j - 1).getPrefix(), Markers.EMPTY, newAttributeListValue, newAttributeListValue, null, JavaType.Primitive.String));
}
return as.withAssignment(((J.NewArray) as.getAssignment()).withInitializer(jLiteralList));
}
int m = 0;
for (int i = 0; i< Objects.requireNonNull(jLiteralList).size(); i++){
if (i >= attributeList.size()){
Expand Down Expand Up @@ -255,4 +274,16 @@ private static boolean attributeIsString(@Nullable String attributeName, J.Annot
}
return false;
}

private static boolean attributeValIsAlreadyPresentOrNull(List<Expression> expression, @Nullable String attributeValue) {
for (Expression e : expression) {
if (e instanceof J.Literal) {
J.Literal literal = (J.Literal) e;
if (literal.getValueSource() != null && literal.getValueSource().equals(attributeValue)) {
return true;
}
}
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public J.Annotation visitAnnotation(J.Annotation annotation, ExecutionContext ct
}
}

AddOrUpdateAnnotationAttribute addOrUpdateAnnotationAttribute = new AddOrUpdateAnnotationAttribute(ORG_OPENREWRITE_OPTION, "example", "TODO Provide a usage example for the docs", true);
AddOrUpdateAnnotationAttribute addOrUpdateAnnotationAttribute = new AddOrUpdateAnnotationAttribute(ORG_OPENREWRITE_OPTION, "example", "TODO Provide a usage example for the docs", true, false);
return (J.Annotation) addOrUpdateAnnotationAttribute.getVisitor().visitNonNull(an, ctx, getCursor().getParent());
}
});
Expand Down

0 comments on commit 268f576

Please sign in to comment.