Skip to content

Commit

Permalink
Merge branch 'main' into demo/collapse-miss
Browse files Browse the repository at this point in the history
  • Loading branch information
timtebeek authored Dec 13, 2024
2 parents f46416b + 8d07aec commit a1a6a02
Show file tree
Hide file tree
Showing 123 changed files with 10,385 additions and 2,423 deletions.
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
root = true

[*]
insert_final_newline = true
trim_trailing_whitespace = true

[src/test*/java/**.java]
indent_size = 4
ij_continuation_indent_size = 2
10 changes: 6 additions & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ recipeDependencies {
parserClasspath("com.github.tomakehurst:wiremock-jre8:2.35.0")
parserClasspath("org.mockito:mockito-all:1.10.19")
parserClasspath("org.mockito:mockito-core:3.+")
parserClasspath("org.mockito:mockito-core:5.+")
parserClasspath("org.jmockit:jmockit:1.49")
parserClasspath("org.jmockit:jmockit:1.22") // last version with NonStrictExpectations
parserClasspath("org.mockito:mockito-junit-jupiter:3.+")
parserClasspath("org.powermock:powermock-api-mockito:1.7.+")
parserClasspath("org.powermock:powermock-core:1.7.+")
parserClasspath("com.squareup.okhttp3:mockwebserver:4.10.0")
parserClasspath("org.springframework:spring-test:6.1.12")
parserClasspath("com.github.database-rider:rider-junit5:1.44.0")
}

val rewriteVersion = rewriteRecipe.rewriteVersion.get()
Expand All @@ -48,12 +50,13 @@ dependencies {

testImplementation("org.openrewrite:rewrite-java-17")
testImplementation("org.openrewrite:rewrite-groovy")
testImplementation("org.openrewrite:rewrite-test")
testImplementation("org.openrewrite:rewrite-kotlin:$rewriteVersion")
testImplementation("org.openrewrite.gradle.tooling:model:$rewriteVersion")

annotationProcessor("org.openrewrite:rewrite-templating:${rewriteVersion}")
implementation("org.openrewrite:rewrite-templating:${rewriteVersion}")
compileOnly("com.google.errorprone:error_prone_core:2.19.1:with-dependencies") {
compileOnly("com.google.errorprone:error_prone_core:2.+:with-dependencies") {
exclude("com.google.auto.service", "auto-service-annotations")
}

Expand All @@ -66,10 +69,9 @@ dependencies {
testRuntimeOnly("net.datafaker:datafaker:latest.release") {
exclude(group = "org.yaml", module = "snakeyaml")
}
testRuntimeOnly("org.easymock:easymock:latest.release")
testRuntimeOnly("org.testng:testng:latest.release")
testRuntimeOnly("org.mockito.kotlin:mockito-kotlin:latest.release")
testRuntimeOnly("org.testcontainers:testcontainers:latest.release")
testRuntimeOnly("org.testcontainers:nginx:latest.release")

// testImplementation("org.hamcrest:hamcrest:latest.release")
// testImplementation("org.assertj:assertj-core:latest.release")
}
4 changes: 2 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionSha256Sum=1541fa36599e12857140465f3c91a97409b4512501c26f9631fb113e392c5bd1
distributionSha256Sum=f397b287023acdba1e9f6fc5ea72d22dd63669d59ed4a289a29b1a76eee151c6

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import org.openrewrite.java.JavaParser;
import org.openrewrite.java.JavaTemplate;
import org.openrewrite.java.MethodMatcher;
import org.openrewrite.java.search.UsesType;
import org.openrewrite.java.search.UsesMethod;
import org.openrewrite.java.tree.Expression;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.JavaType;
Expand All @@ -32,11 +32,14 @@
import java.util.List;

public class JUnitAssertArrayEqualsToAssertThat extends Recipe {
private static final String JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME = "org.junit.jupiter.api.Assertions";

private static final String JUNIT = "org.junit.jupiter.api.Assertions";
private static final String ASSERTJ = "org.assertj.core.api.Assertions";
private static final MethodMatcher ASSERT_ARRAY_EQUALS_MATCHER = new MethodMatcher(JUNIT + " assertArrayEquals(..)", true);

@Override
public String getDisplayName() {
return "JUnit `assertArrayEquals` To AssertJ";
return "JUnit `assertArrayEquals` to assertJ";
}

@Override
Expand All @@ -46,93 +49,72 @@ public String getDescription() {

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
return Preconditions.check(new UsesType<>(JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME, false), new AssertArrayEqualsToAssertThatVisitor());
}

public static class AssertArrayEqualsToAssertThatVisitor extends JavaIsoVisitor<ExecutionContext> {
private static final MethodMatcher JUNIT_ASSERT_EQUALS = new MethodMatcher(JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME + " assertArrayEquals(..)");

private JavaParser.Builder<?, ?> assertionsParser;

private JavaParser.Builder<?, ?> assertionsParser(ExecutionContext ctx) {
if (assertionsParser == null) {
assertionsParser = JavaParser.fromJavaVersion()
.classpathFromResources(ctx, "assertj-core-3.24");
}
return assertionsParser;
}


@Override
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
if (!JUNIT_ASSERT_EQUALS.matches(method)) {
return method;
}

List<Expression> args = method.getArguments();
Expression expected = args.get(0);
Expression actual = args.get(1);

// Make sure there is a static import for "org.assertj.core.api.Assertions.assertThat" (even if not referenced)
maybeAddImport("org.assertj.core.api.Assertions", "assertThat", false);
maybeRemoveImport(JUNIT_QUALIFIED_ASSERTIONS_CLASS_NAME);

if (args.size() == 2) {
return JavaTemplate.builder("assertThat(#{anyArray()}).containsExactly(#{anyArray()});")
.staticImports("org.assertj.core.api.Assertions.assertThat")
.javaParser(assertionsParser(ctx))
.build()
.apply(getCursor(), method.getCoordinates().replace(), actual, expected);
} else if (args.size() == 3 && !isFloatingPointType(args.get(2))) {
Expression message = args.get(2);
JavaTemplate.Builder template = TypeUtils.isString(message.getType()) ?
JavaTemplate.builder("assertThat(#{anyArray()}).as(#{any(String)}).containsExactly(#{anyArray()});") :
JavaTemplate.builder("assertThat(#{anyArray()}).as(#{any(java.util.function.Supplier)}).containsExactly(#{anyArray()});");
return template
.staticImports("org.assertj.core.api.Assertions.assertThat")
.javaParser(assertionsParser(ctx))
.build()
.apply(getCursor(), method.getCoordinates().replace(), actual, message, expected);
} else if (args.size() == 3) {
maybeAddImport("org.assertj.core.api.Assertions", "within", false);
// assert is using floating points with a delta and no message.
return JavaTemplate.builder("assertThat(#{anyArray()}).containsExactly(#{anyArray()}, within(#{any()}));")
.staticImports("org.assertj.core.api.Assertions.assertThat", "org.assertj.core.api.Assertions.within")
.javaParser(assertionsParser(ctx))
return Preconditions.check(new UsesMethod<>(ASSERT_ARRAY_EQUALS_MATCHER), new JavaIsoVisitor<ExecutionContext>() {
@Override
public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) {
J.MethodInvocation md = super.visitMethodInvocation(method, ctx);
if (!ASSERT_ARRAY_EQUALS_MATCHER.matches(md)) {
return md;
}

maybeAddImport(ASSERTJ, "assertThat", false);
maybeRemoveImport(JUNIT);

List<Expression> args = md.getArguments();
Expression expected = args.get(0);
Expression actual = args.get(1);
if (args.size() == 2) {
return JavaTemplate.builder("assertThat(#{anyArray()}).containsExactly(#{anyArray()});")
.staticImports(ASSERTJ + ".assertThat")
.javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "assertj-core-3.24"))
.build()
.apply(getCursor(), md.getCoordinates().replace(), actual, expected);
}
if (args.size() == 3 && isFloatingPointType(args.get(2))) {
maybeAddImport(ASSERTJ, "within", false);
// assert is using floating points with a delta and no message.
return JavaTemplate.builder("assertThat(#{anyArray()}).containsExactly(#{anyArray()}, within(#{any()}));")
.staticImports(ASSERTJ + ".assertThat", ASSERTJ + ".within")
.javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "assertj-core-3.24"))
.build()
.apply(getCursor(), md.getCoordinates().replace(), actual, expected, args.get(2));
}
if (args.size() == 3) {
Expression message = args.get(2);
return JavaTemplate.builder("assertThat(#{anyArray()}).as(#{any()}).containsExactly(#{anyArray()});")
.staticImports(ASSERTJ + ".assertThat")
.javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "assertj-core-3.24"))
.build()
.apply(getCursor(), md.getCoordinates().replace(), actual, message, expected);
}

maybeAddImport(ASSERTJ, "within", false);

// The assertEquals is using a floating point with a delta argument and a message.
Expression message = args.get(3);
return JavaTemplate.builder("assertThat(#{anyArray()}).as(#{any()}).containsExactly(#{anyArray()}, within(#{}));")
.staticImports(ASSERTJ + ".assertThat", ASSERTJ + ".within")
.javaParser(JavaParser.fromJavaVersion().classpathFromResources(ctx, "assertj-core-3.24"))
.build()
.apply(getCursor(), method.getCoordinates().replace(), actual, expected, args.get(2));
.apply(getCursor(), md.getCoordinates().replace(), actual, message, expected, args.get(2));
}

// The assertEquals is using a floating point with a delta argument and a message.
Expression message = args.get(3);
maybeAddImport("org.assertj.core.api.Assertions", "within", false);

JavaTemplate.Builder template = TypeUtils.isString(message.getType()) ?
JavaTemplate.builder("assertThat(#{anyArray()}).as(#{any(String)}).containsExactly(#{anyArray()}, within(#{any()}));") :
JavaTemplate.builder("assertThat(#{anyArray()}).as(#{any(java.util.function.Supplier)}).containsExactly(#{anyArray()}, within(#{}));");
return template
.staticImports("org.assertj.core.api.Assertions.assertThat", "org.assertj.core.api.Assertions.within")
.javaParser(assertionsParser(ctx))
.build()
.apply(getCursor(), method.getCoordinates().replace(), actual, message, expected, args.get(2));
}

/**
* Returns true if the expression's type is either a primitive float/double or their object forms Float/Double
*
* @param expression The expression parsed from the original AST.
* @return true if the type is a floating point number.
*/
private static boolean isFloatingPointType(Expression expression) {

JavaType.FullyQualified fullyQualified = TypeUtils.asFullyQualified(expression.getType());
if (fullyQualified != null) {
String typeName = fullyQualified.getFullyQualifiedName();
return "java.lang.Double".equals(typeName) || "java.lang.Float".equals(typeName);
/**
* Returns true if the expression's type is either a primitive float/double or their object forms Float/Double
*
* @param expression The expression parsed from the original AST.
* @return true if the type is a floating point number.
*/
private boolean isFloatingPointType(Expression expression) {
JavaType.FullyQualified fullyQualified = TypeUtils.asFullyQualified(expression.getType());
if (fullyQualified != null) {
String typeName = fullyQualified.getFullyQualifiedName();
return "java.lang.Double".equals(typeName) || "java.lang.Float".equals(typeName);
}

JavaType.Primitive parameterType = TypeUtils.asPrimitive(expression.getType());
return parameterType == JavaType.Primitive.Double || parameterType == JavaType.Primitive.Float;
}

JavaType.Primitive parameterType = TypeUtils.asPrimitive(expression.getType());
return parameterType == JavaType.Primitive.Double || parameterType == JavaType.Primitive.Float;
}
});
}
}
Loading

0 comments on commit a1a6a02

Please sign in to comment.