Skip to content

Commit 7bb2355

Browse files
committed
Implement multimodule solution
1 parent 616ec24 commit 7bb2355

File tree

2 files changed

+114
-20
lines changed

2 files changed

+114
-20
lines changed

src/main/java/org/openrewrite/java/migrate/jakarta/HasNoJakartaNullAnnotations.java

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,21 @@
1515
*/
1616
package org.openrewrite.java.migrate.jakarta;
1717

18+
import lombok.Value;
1819
import org.jspecify.annotations.Nullable;
1920
import org.openrewrite.ExecutionContext;
2021
import org.openrewrite.ScanningRecipe;
2122
import org.openrewrite.Tree;
2223
import org.openrewrite.TreeVisitor;
23-
import org.openrewrite.java.JavaIsoVisitor;
24+
import org.openrewrite.java.marker.JavaProject;
2425
import org.openrewrite.java.search.FindAnnotations;
2526
import org.openrewrite.java.tree.J;
2627
import org.openrewrite.marker.SearchResult;
2728

28-
import java.util.concurrent.atomic.AtomicBoolean;
29+
import java.util.HashSet;
30+
import java.util.Set;
2931

30-
public class HasNoJakartaNullAnnotations extends ScanningRecipe<AtomicBoolean> {
32+
public class HasNoJakartaNullAnnotations extends ScanningRecipe<HasNoJakartaNullAnnotations.Accumulator> {
3133
@Override
3234
public String getDisplayName() {
3335
return "Project has no Jakarta null annotations";
@@ -38,38 +40,43 @@ public String getDescription() {
3840
return "Search for @Nonnull and @Nullable annotations, mark all source as found if no annotations are found.";
3941
}
4042

43+
@Value
44+
public static class Accumulator {
45+
Set<JavaProject> projectsWithDependency;
46+
}
47+
4148
@Override
42-
public AtomicBoolean getInitialValue(ExecutionContext ctx) {
43-
return new AtomicBoolean();
49+
public Accumulator getInitialValue(ExecutionContext ctx) {
50+
return new Accumulator(new HashSet<>());
4451
}
4552

4653
@Override
47-
public TreeVisitor<?, ExecutionContext> getScanner(AtomicBoolean acc) {
48-
return new JavaIsoVisitor<ExecutionContext>() {
54+
public TreeVisitor<?, ExecutionContext> getScanner(HasNoJakartaNullAnnotations.Accumulator acc) {
55+
return new TreeVisitor<Tree, ExecutionContext>() {
4956
@Override
50-
public J.CompilationUnit visitCompilationUnit(J.CompilationUnit cu, ExecutionContext ctx) {
51-
J.CompilationUnit c = super.visitCompilationUnit(cu, ctx);
52-
if (!acc.get()) {
53-
if ((!FindAnnotations.find(c, "@jakarta.annotation.Nonnull", true).isEmpty()) ||
54-
(!FindAnnotations.find(c, "@jakarta.annotation.Nullable", true).isEmpty())) {
55-
acc.set(true);
56-
}
57+
public Tree visit(@Nullable Tree tree, ExecutionContext ctx) {
58+
assert tree != null;
59+
if (tree instanceof J) {
60+
tree.getMarkers().findFirst(JavaProject.class)
61+
.filter(__ ->!FindAnnotations.find((J) tree, "@jakarta.annotation.Nonnull", true).isEmpty() ||
62+
!FindAnnotations.find((J) tree, "@jakarta.annotation.Nullable", true).isEmpty())
63+
.ifPresent(it -> acc.getProjectsWithDependency().add(it));
5764
}
58-
return cu;
65+
return tree;
5966
}
6067
};
6168
}
6269

6370
@Override
64-
public TreeVisitor<?, ExecutionContext> getVisitor(AtomicBoolean acc) {
71+
public TreeVisitor<?, ExecutionContext> getVisitor(HasNoJakartaNullAnnotations.Accumulator acc) {
6572
return new TreeVisitor<Tree, ExecutionContext>() {
6673
@Override
6774
public Tree visit(@Nullable Tree tree, ExecutionContext ctx) {
6875
assert tree != null;
69-
if (!acc.get()) {
70-
return SearchResult.found(tree, "Project has no Jakarta null annotations");
71-
}
72-
return tree;
76+
return tree.getMarkers().findFirst(JavaProject.class)
77+
.filter(it -> !acc.getProjectsWithDependency().contains(it))
78+
.map(__ -> SearchResult.found(tree, "Project has no Jakarta null annotations"))
79+
.orElse(tree);
7380
}
7481
};
7582
}

src/test/java/org/openrewrite/java/migrate/jakarta/JavaxToJakartaTest.java

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
import org.openrewrite.test.RecipeSpec;
2525
import org.openrewrite.test.RewriteTest;
2626

27+
import static org.openrewrite.gradle.Assertions.buildGradle;
28+
import static org.openrewrite.gradle.Assertions.settingsGradle;
29+
import static org.openrewrite.gradle.toolingapi.Assertions.withToolingApi;
2730
import static org.openrewrite.java.Assertions.*;
2831
import static org.openrewrite.maven.Assertions.pomXml;
2932
import static org.openrewrite.xml.Assertions.xml;
@@ -702,6 +705,7 @@ void projectWithSpringBoot3StarterWebShouldNotRemoveJakartaDependencyWhenUsingNu
702705
<artifactId>demo</artifactId>
703706
<version>0.0.1-SNAPSHOT</version>
704707
<dependencies>
708+
<!--implementation 'jakarta.annotation:jakarta.annotation-api:1.3.5'-->
705709
<dependency>
706710
<groupId>jakarta.annotation</groupId>
707711
<artifactId>jakarta.annotation-api</artifactId>
@@ -734,6 +738,89 @@ public String safeUpperCase(@Nullable String input) {
734738
);
735739
}
736740

741+
@Test
742+
void multiProjectWithSpringBoot3StarterWebShouldRemoveJakartaDependencyWhenUsingNullableAnnotationWhenApplicable() {
743+
rewriteRun(
744+
spec -> spec.beforeRecipe(withToolingApi()).parser(JavaParser.fromJavaVersion().dependsOn(javaxServlet, jakartaAnnotation)),
745+
mavenProject("multi-project-build",
746+
//language=groovy
747+
settingsGradle("""
748+
include 'project-with-null-annotations'
749+
include 'project-without-null-annotations'
750+
"""),
751+
mavenProject("project-with-null-annotations",
752+
//language=groovy
753+
buildGradle(
754+
"""
755+
plugins {
756+
id 'java'
757+
id 'org.springframework.boot' version '3.2.5'
758+
id 'io.spring.dependency-management' version '1.1.4'
759+
}
760+
761+
dependencies {
762+
implementation 'jakarta.annotation:jakarta.annotation-api:1.3.5'
763+
implementation 'org.springframework.boot:spring-boot-starter-web'
764+
}
765+
""",
766+
"""
767+
plugins {
768+
id 'java'
769+
id 'org.springframework.boot' version '3.2.5'
770+
id 'io.spring.dependency-management' version '1.1.4'
771+
}
772+
773+
dependencies {
774+
implementation 'jakarta.annotation:jakarta.annotation-api:2.0.0'
775+
implementation 'org.springframework.boot:spring-boot-starter-web'
776+
}
777+
"""
778+
),
779+
srcMainJava(
780+
//language=java
781+
java(
782+
"""
783+
import jakarta.annotation.Nullable;
784+
785+
public class TestApplication {
786+
@Nullable
787+
public String safeUpperCase(@Nullable String input) {
788+
return input == null ? null : input.toUpperCase();
789+
}
790+
}
791+
"""
792+
)
793+
)
794+
),
795+
mavenProject("project-without-null-annotations",
796+
//language=groovy
797+
buildGradle(
798+
"""
799+
plugins {
800+
id 'java'
801+
id 'org.springframework.boot' version '3.2.5'
802+
id 'io.spring.dependency-management' version '1.1.4'
803+
}
804+
805+
dependencies {
806+
implementation 'jakarta.annotation:jakarta.annotation-api:1.3.5'
807+
implementation 'org.springframework.boot:spring-boot-starter-web'
808+
}
809+
"""
810+
)/*,
811+
srcMainJava(
812+
//language=java
813+
java("""
814+
import jakarta.servlet.A;
815+
public class TestApplication {
816+
}
817+
""")
818+
)*/
819+
)
820+
)
821+
);
822+
}
823+
737824
@Test
738825
void upgradeAnnotationApiFromV1ToV2() {
739826
rewriteRun(

0 commit comments

Comments
 (0)