From fcd91f276e6e939b86f9f6c4be367edd323ee5d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merlin=20B=C3=B6gershausen?= Date: Thu, 13 Feb 2025 11:29:15 +0100 Subject: [PATCH 01/14] Refactor `SourceFileWithReferences#getReferences` method to accept a `ClassLoader` to enable `ServiceLoader` to find `Provider`s loaded by recipe `ClassLoader`s --- .../openrewrite/SourceFileWithReferences.java | 11 +++-- .../java/org/openrewrite/text/PlainText.java | 4 +- .../openrewrite/gradle/AddDependencyTest.java | 47 ++++++++++++++++++- .../org/openrewrite/java/ChangePackage.java | 4 +- .../java/org/openrewrite/java/ChangeType.java | 2 +- .../openrewrite/java/search/FindTypes.java | 2 +- .../org/openrewrite/java/search/UsesType.java | 2 +- .../properties/tree/Properties.java | 4 +- .../trait/PropertiesReferenceTest.java | 4 +- .../java/org/openrewrite/xml/tree/Xml.java | 4 +- .../org/openrewrite/xml/XmlParserTest.java | 6 +-- .../java/org/openrewrite/yaml/tree/Yaml.java | 4 +- .../yaml/trait/YamlReferenceTest.java | 6 +-- 13 files changed, 73 insertions(+), 27 deletions(-) diff --git a/rewrite-core/src/main/java/org/openrewrite/SourceFileWithReferences.java b/rewrite-core/src/main/java/org/openrewrite/SourceFileWithReferences.java index bb1584aaabf..84757b5a7d2 100644 --- a/rewrite-core/src/main/java/org/openrewrite/SourceFileWithReferences.java +++ b/rewrite-core/src/main/java/org/openrewrite/SourceFileWithReferences.java @@ -27,12 +27,12 @@ @Incubating(since = "8.39.0") public interface SourceFileWithReferences extends SourceFile { - References getReferences(); + References getReferences(ClassLoader classLoader); - default SoftReference build(@Nullable SoftReference<@Nullable References> references) { + default SoftReference build(@Nullable SoftReference<@Nullable References> references, ClassLoader classLoader) { References cache = references == null ? null : references.get(); if (cache == null || cache.getSourceFile() != this) { - return new SoftReference<>(References.build(this)); + return new SoftReference<>(References.build(this, classLoader)); } return references; } @@ -54,9 +54,10 @@ public Collection findMatches(Reference.Matcher matcher) { return list; } - private static References build(SourceFile sourceFile) { + private static References build(SourceFile sourceFile, ClassLoader classLoader) { Set references = new HashSet<>(); - ServiceLoader loader = ServiceLoader.load(Reference.Provider.class); + ServiceLoader loader = ServiceLoader.load(Reference.Provider.class, classLoader); + loader.reload(); loader.forEach(provider -> { if (provider.isAcceptable(sourceFile)) { references.addAll(provider.getReferences(sourceFile)); diff --git a/rewrite-core/src/main/java/org/openrewrite/text/PlainText.java b/rewrite-core/src/main/java/org/openrewrite/text/PlainText.java index 623122d9921..5602948d3cf 100644 --- a/rewrite-core/src/main/java/org/openrewrite/text/PlainText.java +++ b/rewrite-core/src/main/java/org/openrewrite/text/PlainText.java @@ -104,8 +104,8 @@ public PlainText(UUID id, Path sourcePath, Markers markers, @Nullable String cha } @Override - public References getReferences() { - this.references = build(this.references); + public References getReferences(ClassLoader classLoader) { + this.references = build(this.references, getClass().getClassLoader()); return Objects.requireNonNull(this.references.get()); } diff --git a/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java b/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java index cb1da2ffe4a..debb73b7ca6 100644 --- a/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java +++ b/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java @@ -17,17 +17,22 @@ import org.intellij.lang.annotations.Language; import org.jspecify.annotations.Nullable; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import org.openrewrite.Issue; +import org.openrewrite.*; import org.openrewrite.gradle.marker.GradleDependencyConfiguration; import org.openrewrite.gradle.marker.GradleProject; +import org.openrewrite.java.JavaIsoVisitor; import org.openrewrite.java.JavaParser; +import org.openrewrite.java.JavaVisitor; +import org.openrewrite.java.tree.J; import org.openrewrite.test.RecipeSpec; import org.openrewrite.test.RewriteTest; import org.openrewrite.test.TypeValidation; +import java.util.List; import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; @@ -62,6 +67,46 @@ boolean getMap() { } """; + public static class TSTRecipe extends Recipe { + @Override + public String getDisplayName() { + return "A"; + } + + @Override + public String getDescription() { + return "B."; + } + + @Override + public TreeVisitor getVisitor() { + return new JavaVisitor<>(){ + + @Override + public J visitMethodDeclaration(J.MethodDeclaration method, ExecutionContext executionContext) { + return super.visitMethodDeclaration(method, executionContext); + } + }; + } + } + + @Disabled + @Test + void tsts() { + rewriteRun( + spec -> spec.recipe(new TSTRecipe()), + java(""" + import java.util.List; + class A { + void tst() { + List.of("A", "B"); + } + } + """ + ) + ); + } + @ParameterizedTest @ValueSource(strings = {"com.google.common.math.*", "com.google.common.math.IntMath"}) void onlyIfUsingTestScope(String onlyIfUsing) { diff --git a/rewrite-java/src/main/java/org/openrewrite/java/ChangePackage.java b/rewrite-java/src/main/java/org/openrewrite/java/ChangePackage.java index dd32bea75a5..8a3ac5c0f10 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/ChangePackage.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/ChangePackage.java @@ -118,7 +118,7 @@ public TreeVisitor getVisitor() { SourceFileWithReferences cu = (SourceFileWithReferences) tree; boolean recursive = Boolean.TRUE.equals(ChangePackage.this.recursive); String recursivePackageNamePrefix = oldPackageName + "."; - for (Reference ref : cu.getReferences().getReferences()) { + for (Reference ref : cu.getReferences(getClass().getClassLoader()).getReferences()) { if (ref.getValue().equals(oldPackageName) || recursive && ref.getValue().startsWith(recursivePackageNamePrefix)) { return SearchResult.found(cu); } @@ -141,7 +141,7 @@ public boolean isAcceptable(SourceFile sourceFile, ExecutionContext ctx) { return new JavaChangePackageVisitor().visit(tree, ctx, requireNonNull(getCursor().getParent())); } else if (tree instanceof SourceFileWithReferences) { SourceFileWithReferences sourceFile = (SourceFileWithReferences) tree; - SourceFileWithReferences.References references = sourceFile.getReferences(); + SourceFileWithReferences.References references = sourceFile.getReferences(getClass().getClassLoader()); boolean recursive = Boolean.TRUE.equals(ChangePackage.this.recursive); PackageMatcher matcher = new PackageMatcher(oldPackageName, recursive); Map matches = new HashMap<>(); diff --git a/rewrite-java/src/main/java/org/openrewrite/java/ChangeType.java b/rewrite-java/src/main/java/org/openrewrite/java/ChangeType.java index 8cdb8cf4865..04181e3d831 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/ChangeType.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/ChangeType.java @@ -111,7 +111,7 @@ public boolean isAcceptable(SourceFile sourceFile, ExecutionContext ctx) { return new JavaChangeTypeVisitor(oldFullyQualifiedTypeName, newFullyQualifiedTypeName, ignoreDefinition).visit(tree, ctx, requireNonNull(getCursor().getParent())); } else if (tree instanceof SourceFileWithReferences) { SourceFileWithReferences sourceFile = (SourceFileWithReferences) tree; - SourceFileWithReferences.References references = sourceFile.getReferences(); + SourceFileWithReferences.References references = sourceFile.getReferences(getClass().getClassLoader()); TypeMatcher matcher = new TypeMatcher(oldFullyQualifiedTypeName); Map matches = new HashMap<>(); for (Reference ref : references.findMatches(matcher)) { diff --git a/rewrite-java/src/main/java/org/openrewrite/java/search/FindTypes.java b/rewrite-java/src/main/java/org/openrewrite/java/search/FindTypes.java index 7a0dff047c5..64f08064dbc 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/search/FindTypes.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/search/FindTypes.java @@ -77,7 +77,7 @@ public boolean isAcceptable(SourceFile sourceFile, ExecutionContext ctx) { return new JavaSourceFileVisitor(fullyQualifiedType).visit(tree, ctx); } else if (tree instanceof SourceFileWithReferences) { SourceFileWithReferences sourceFile = (SourceFileWithReferences) tree; - SourceFileWithReferences.References references = sourceFile.getReferences(); + SourceFileWithReferences.References references = sourceFile.getReferences(getClass().getClassLoader()); TypeMatcher matcher = new TypeMatcher(fullyQualifiedTypeName); Set matches = references.findMatches(matcher).stream().map(Trait::getTree).collect(Collectors.toSet()); return new ReferenceVisitor(matches).visit(tree, ctx); diff --git a/rewrite-java/src/main/java/org/openrewrite/java/search/UsesType.java b/rewrite-java/src/main/java/org/openrewrite/java/search/UsesType.java index 4044dfcbc78..163f0af3e45 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/search/UsesType.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/search/UsesType.java @@ -121,7 +121,7 @@ public boolean isAcceptable(SourceFile sourceFile, P p) { } } else if (tree instanceof SourceFileWithReferences) { SourceFileWithReferences sourceFile = (SourceFileWithReferences) tree; - SourceFileWithReferences.References references = sourceFile.getReferences(); + SourceFileWithReferences.References references = sourceFile.getReferences(getClass().getClassLoader()); TypeMatcher matcher = typeMatcher != null ? typeMatcher : new TypeMatcher(fullyQualifiedType); for (Reference ignored : references.findMatches(matcher)) { return SearchResult.found(sourceFile); diff --git a/rewrite-properties/src/main/java/org/openrewrite/properties/tree/Properties.java b/rewrite-properties/src/main/java/org/openrewrite/properties/tree/Properties.java index d24b3706fa7..d8045ed1c0a 100755 --- a/rewrite-properties/src/main/java/org/openrewrite/properties/tree/Properties.java +++ b/rewrite-properties/src/main/java/org/openrewrite/properties/tree/Properties.java @@ -118,8 +118,8 @@ public

TreeVisitor> printer(Cursor cursor) { transient SoftReference references; @Override - public References getReferences() { - this.references = build(this.references); + public References getReferences(ClassLoader classLoader) { + this.references = build(this.references, getClass().getClassLoader()); return Objects.requireNonNull(this.references.get()); } } diff --git a/rewrite-properties/src/test/java/org/openrewrite/properties/trait/PropertiesReferenceTest.java b/rewrite-properties/src/test/java/org/openrewrite/properties/trait/PropertiesReferenceTest.java index 5283957a46d..0ab6a3e24d0 100644 --- a/rewrite-properties/src/test/java/org/openrewrite/properties/trait/PropertiesReferenceTest.java +++ b/rewrite-properties/src/test/java/org/openrewrite/properties/trait/PropertiesReferenceTest.java @@ -44,7 +44,7 @@ void findJavaReferencesInApplicationProperties(String filename) { properties( PROPERTIES, spec -> spec.path(filename).afterRecipe(doc -> - assertThat(doc.getReferences().getReferences()) + assertThat(doc.getReferences(getClass().getClassLoader()).getReferences()) .satisfiesExactlyInAnyOrder( ref -> { assertThat(ref.getKind()).isEqualTo(Reference.Kind.TYPE); @@ -72,7 +72,7 @@ void noReferencesInMismatchedFilenames(String filename) { rewriteRun( properties( PROPERTIES, - spec -> spec.path(filename).afterRecipe(doc -> assertThat(doc.getReferences().getReferences()).isEmpty()) + spec -> spec.path(filename).afterRecipe(doc -> assertThat(doc.getReferences(getClass().getClassLoader()).getReferences()).isEmpty()) ) ); } diff --git a/rewrite-xml/src/main/java/org/openrewrite/xml/tree/Xml.java b/rewrite-xml/src/main/java/org/openrewrite/xml/tree/Xml.java index 138f470ab7a..57ecad8be34 100755 --- a/rewrite-xml/src/main/java/org/openrewrite/xml/tree/Xml.java +++ b/rewrite-xml/src/main/java/org/openrewrite/xml/tree/Xml.java @@ -168,8 +168,8 @@ public T service(Class service) { transient SoftReference references; @Override - public References getReferences() { - this.references = build(this.references); + public References getReferences(ClassLoader classLoader) { + this.references = build(this.references, getClass().getClassLoader()); return Objects.requireNonNull(this.references.get()); } } diff --git a/rewrite-xml/src/test/java/org/openrewrite/xml/XmlParserTest.java b/rewrite-xml/src/test/java/org/openrewrite/xml/XmlParserTest.java index 57ae47a0905..2dc78b5ca6e 100755 --- a/rewrite-xml/src/test/java/org/openrewrite/xml/XmlParserTest.java +++ b/rewrite-xml/src/test/java/org/openrewrite/xml/XmlParserTest.java @@ -145,9 +145,9 @@ void javaReferenceDocument() { """, spec -> spec.afterRecipe(doc -> { - assertThat(doc.getReferences().getReferences().stream().anyMatch(typeRef -> typeRef.getValue().equals("java.lang.String"))).isTrue(); - assertThat(doc.getReferences().getReferences().stream().anyMatch(typeRef -> typeRef.getKind() == Reference.Kind.TYPE)).isTrue(); - assertThat(doc.getReferences().getReferences().stream().anyMatch(typeRef -> typeRef.getKind() == Reference.Kind.PACKAGE)).isTrue(); + assertThat(doc.getReferences(getClass().getClassLoader()).getReferences().stream().anyMatch(typeRef -> typeRef.getValue().equals("java.lang.String"))).isTrue(); + assertThat(doc.getReferences(getClass().getClassLoader()).getReferences().stream().anyMatch(typeRef -> typeRef.getKind() == Reference.Kind.TYPE)).isTrue(); + assertThat(doc.getReferences(getClass().getClassLoader()).getReferences().stream().anyMatch(typeRef -> typeRef.getKind() == Reference.Kind.PACKAGE)).isTrue(); }) ) ); diff --git a/rewrite-yaml/src/main/java/org/openrewrite/yaml/tree/Yaml.java b/rewrite-yaml/src/main/java/org/openrewrite/yaml/tree/Yaml.java index 9603f3e11db..acf26e4c854 100755 --- a/rewrite-yaml/src/main/java/org/openrewrite/yaml/tree/Yaml.java +++ b/rewrite-yaml/src/main/java/org/openrewrite/yaml/tree/Yaml.java @@ -136,8 +136,8 @@ public

TreeVisitor> printer(Cursor cursor) { transient SoftReference references; @Override - public References getReferences() { - this.references = build(this.references); + public References getReferences(ClassLoader classLoader) { + this.references = build(this.references, getClass().getClassLoader()); return Objects.requireNonNull(this.references.get()); } } diff --git a/rewrite-yaml/src/test/java/org/openrewrite/yaml/trait/YamlReferenceTest.java b/rewrite-yaml/src/test/java/org/openrewrite/yaml/trait/YamlReferenceTest.java index ddc9abdeff9..662a7838266 100644 --- a/rewrite-yaml/src/test/java/org/openrewrite/yaml/trait/YamlReferenceTest.java +++ b/rewrite-yaml/src/test/java/org/openrewrite/yaml/trait/YamlReferenceTest.java @@ -53,7 +53,7 @@ void findJavaReferencesInYamlProperties(String filename) { yaml( YAML, spec -> spec.path(filename).afterRecipe(doc -> - assertThat(doc.getReferences().getReferences()).satisfiesExactlyInAnyOrder( + assertThat(doc.getReferences(getClass().getClassLoader()).getReferences()).satisfiesExactlyInAnyOrder( ref -> { assertThat(ref.getKind()).isEqualTo(Reference.Kind.TYPE); assertThat(ref.getValue()).isEqualTo("java.lang.String"); @@ -90,7 +90,7 @@ void noReferencesInMismatchedFilenames(String filename) { rewriteRun( yaml( YAML, - spec -> spec.path(filename).afterRecipe(doc -> assertThat(doc.getReferences().getReferences()).isEmpty()) + spec -> spec.path(filename).afterRecipe(doc -> assertThat(doc.getReferences(getClass().getClassLoader()).getReferences()).isEmpty()) ) ); } @@ -108,7 +108,7 @@ void endsWithDot() { """, spec -> spec .path("application.yml") - .afterRecipe(doc -> assertThat(doc.getReferences().getReferences()).singleElement().satisfies( + .afterRecipe(doc -> assertThat(doc.getReferences(getClass().getClassLoader()).getReferences()).singleElement().satisfies( ref -> { assertThat(ref.getKind()).isEqualTo(Reference.Kind.TYPE); assertThat(ref.getValue()).isEqualTo("org.openrewrite.java.DoSomething"); From bc55cd60105b2b934aabfcd418dcccc5a4bd20c6 Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Thu, 13 Feb 2025 14:58:52 +0100 Subject: [PATCH 02/14] Apply suggestions from code review Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .../java/org/openrewrite/gradle/AddDependencyTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java b/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java index debb73b7ca6..09f132689cd 100644 --- a/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java +++ b/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java @@ -83,8 +83,8 @@ public TreeVisitor getVisitor() { return new JavaVisitor<>(){ @Override - public J visitMethodDeclaration(J.MethodDeclaration method, ExecutionContext executionContext) { - return super.visitMethodDeclaration(method, executionContext); + public J visitMethodDeclaration(J.MethodDeclaration method, ExecutionContext ctx) { + return super.visitMethodDeclaration(method, ctx); } }; } @@ -95,7 +95,8 @@ public J visitMethodDeclaration(J.MethodDeclaration method, ExecutionContext exe void tsts() { rewriteRun( spec -> spec.recipe(new TSTRecipe()), - java(""" + java( + """ import java.util.List; class A { void tst() { From 25025b1e51909146153e3a7399056fe17c8e7689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merlin=20B=C3=B6gershausen?= Date: Fri, 14 Feb 2025 12:34:01 +0100 Subject: [PATCH 03/14] remove ClassLoader as parameter of getReferences --- .../java/org/openrewrite/SourceFileWithReferences.java | 8 ++++---- .../src/main/java/org/openrewrite/text/PlainText.java | 2 +- .../java/org/openrewrite/properties/tree/Properties.java | 2 +- .../src/main/java/org/openrewrite/xml/tree/Xml.java | 2 +- .../src/main/java/org/openrewrite/yaml/tree/Yaml.java | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/rewrite-core/src/main/java/org/openrewrite/SourceFileWithReferences.java b/rewrite-core/src/main/java/org/openrewrite/SourceFileWithReferences.java index 84757b5a7d2..be0b73365f5 100644 --- a/rewrite-core/src/main/java/org/openrewrite/SourceFileWithReferences.java +++ b/rewrite-core/src/main/java/org/openrewrite/SourceFileWithReferences.java @@ -29,10 +29,10 @@ public interface SourceFileWithReferences extends SourceFile { References getReferences(ClassLoader classLoader); - default SoftReference build(@Nullable SoftReference<@Nullable References> references, ClassLoader classLoader) { + default SoftReference build(@Nullable SoftReference<@Nullable References> references) { References cache = references == null ? null : references.get(); if (cache == null || cache.getSourceFile() != this) { - return new SoftReference<>(References.build(this, classLoader)); + return new SoftReference<>(References.build(this)); } return references; } @@ -54,9 +54,9 @@ public Collection findMatches(Reference.Matcher matcher) { return list; } - private static References build(SourceFile sourceFile, ClassLoader classLoader) { + private static References build(SourceFile sourceFile) { Set references = new HashSet<>(); - ServiceLoader loader = ServiceLoader.load(Reference.Provider.class, classLoader); + ServiceLoader loader = ServiceLoader.load(Reference.Provider.class); loader.reload(); loader.forEach(provider -> { if (provider.isAcceptable(sourceFile)) { diff --git a/rewrite-core/src/main/java/org/openrewrite/text/PlainText.java b/rewrite-core/src/main/java/org/openrewrite/text/PlainText.java index 5602948d3cf..43d0631e95b 100644 --- a/rewrite-core/src/main/java/org/openrewrite/text/PlainText.java +++ b/rewrite-core/src/main/java/org/openrewrite/text/PlainText.java @@ -105,7 +105,7 @@ public PlainText(UUID id, Path sourcePath, Markers markers, @Nullable String cha @Override public References getReferences(ClassLoader classLoader) { - this.references = build(this.references, getClass().getClassLoader()); + this.references = build(this.references); return Objects.requireNonNull(this.references.get()); } diff --git a/rewrite-properties/src/main/java/org/openrewrite/properties/tree/Properties.java b/rewrite-properties/src/main/java/org/openrewrite/properties/tree/Properties.java index d8045ed1c0a..e9b77bfc749 100755 --- a/rewrite-properties/src/main/java/org/openrewrite/properties/tree/Properties.java +++ b/rewrite-properties/src/main/java/org/openrewrite/properties/tree/Properties.java @@ -119,7 +119,7 @@ public

TreeVisitor> printer(Cursor cursor) { @Override public References getReferences(ClassLoader classLoader) { - this.references = build(this.references, getClass().getClassLoader()); + this.references = build(this.references); return Objects.requireNonNull(this.references.get()); } } diff --git a/rewrite-xml/src/main/java/org/openrewrite/xml/tree/Xml.java b/rewrite-xml/src/main/java/org/openrewrite/xml/tree/Xml.java index 57ecad8be34..b1aea9b0df5 100755 --- a/rewrite-xml/src/main/java/org/openrewrite/xml/tree/Xml.java +++ b/rewrite-xml/src/main/java/org/openrewrite/xml/tree/Xml.java @@ -169,7 +169,7 @@ public T service(Class service) { @Override public References getReferences(ClassLoader classLoader) { - this.references = build(this.references, getClass().getClassLoader()); + this.references = build(this.references); return Objects.requireNonNull(this.references.get()); } } diff --git a/rewrite-yaml/src/main/java/org/openrewrite/yaml/tree/Yaml.java b/rewrite-yaml/src/main/java/org/openrewrite/yaml/tree/Yaml.java index acf26e4c854..2c9e03862d2 100755 --- a/rewrite-yaml/src/main/java/org/openrewrite/yaml/tree/Yaml.java +++ b/rewrite-yaml/src/main/java/org/openrewrite/yaml/tree/Yaml.java @@ -137,7 +137,7 @@ public

TreeVisitor> printer(Cursor cursor) { @Override public References getReferences(ClassLoader classLoader) { - this.references = build(this.references, getClass().getClassLoader()); + this.references = build(this.references); return Objects.requireNonNull(this.references.get()); } } From eacff9ff8594d1aec423e632e65cf9fd58e8e490 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merlin=20B=C3=B6gershausen?= Date: Fri, 14 Feb 2025 12:34:37 +0100 Subject: [PATCH 04/14] set TCCL globally before recipe execution --- rewrite-core/src/main/java/org/openrewrite/RecipeScheduler.java | 1 + 1 file changed, 1 insertion(+) diff --git a/rewrite-core/src/main/java/org/openrewrite/RecipeScheduler.java b/rewrite-core/src/main/java/org/openrewrite/RecipeScheduler.java index 795dad5b841..b98317507aa 100644 --- a/rewrite-core/src/main/java/org/openrewrite/RecipeScheduler.java +++ b/rewrite-core/src/main/java/org/openrewrite/RecipeScheduler.java @@ -38,6 +38,7 @@ public RecipeRun scheduleRun(Recipe recipe, int maxCycles, int minCycles) { try { + Thread.currentThread().setContextClassLoader(recipe.getClass().getClassLoader()); LargeSourceSet after = runRecipeCycles(recipe, sourceSet, ctx, maxCycles, minCycles); return new RecipeRun( after.getChangeset(), From 008218cc771134aae8ea4c8b3f4a6c46649e5e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merlin=20B=C3=B6gershausen?= Date: Fri, 14 Feb 2025 12:36:48 +0100 Subject: [PATCH 05/14] remove parameter from calls --- .../main/java/org/openrewrite/SourceFileWithReferences.java | 2 +- .../src/main/java/org/openrewrite/text/PlainText.java | 2 +- .../src/main/java/org/openrewrite/java/ChangePackage.java | 4 ++-- .../src/main/java/org/openrewrite/java/ChangeType.java | 2 +- .../main/java/org/openrewrite/java/search/FindTypes.java | 2 +- .../src/main/java/org/openrewrite/java/search/UsesType.java | 2 +- .../java/org/openrewrite/properties/tree/Properties.java | 2 +- .../properties/trait/PropertiesReferenceTest.java | 4 ++-- rewrite-xml/src/main/java/org/openrewrite/xml/tree/Xml.java | 2 +- .../src/test/java/org/openrewrite/xml/XmlParserTest.java | 6 +++--- .../src/main/java/org/openrewrite/yaml/tree/Yaml.java | 2 +- .../java/org/openrewrite/yaml/trait/YamlReferenceTest.java | 6 +++--- 12 files changed, 18 insertions(+), 18 deletions(-) diff --git a/rewrite-core/src/main/java/org/openrewrite/SourceFileWithReferences.java b/rewrite-core/src/main/java/org/openrewrite/SourceFileWithReferences.java index be0b73365f5..bf7aa7ab987 100644 --- a/rewrite-core/src/main/java/org/openrewrite/SourceFileWithReferences.java +++ b/rewrite-core/src/main/java/org/openrewrite/SourceFileWithReferences.java @@ -27,7 +27,7 @@ @Incubating(since = "8.39.0") public interface SourceFileWithReferences extends SourceFile { - References getReferences(ClassLoader classLoader); + References getReferences(); default SoftReference build(@Nullable SoftReference<@Nullable References> references) { References cache = references == null ? null : references.get(); diff --git a/rewrite-core/src/main/java/org/openrewrite/text/PlainText.java b/rewrite-core/src/main/java/org/openrewrite/text/PlainText.java index 43d0631e95b..623122d9921 100644 --- a/rewrite-core/src/main/java/org/openrewrite/text/PlainText.java +++ b/rewrite-core/src/main/java/org/openrewrite/text/PlainText.java @@ -104,7 +104,7 @@ public PlainText(UUID id, Path sourcePath, Markers markers, @Nullable String cha } @Override - public References getReferences(ClassLoader classLoader) { + public References getReferences() { this.references = build(this.references); return Objects.requireNonNull(this.references.get()); } diff --git a/rewrite-java/src/main/java/org/openrewrite/java/ChangePackage.java b/rewrite-java/src/main/java/org/openrewrite/java/ChangePackage.java index 8a3ac5c0f10..dd32bea75a5 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/ChangePackage.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/ChangePackage.java @@ -118,7 +118,7 @@ public TreeVisitor getVisitor() { SourceFileWithReferences cu = (SourceFileWithReferences) tree; boolean recursive = Boolean.TRUE.equals(ChangePackage.this.recursive); String recursivePackageNamePrefix = oldPackageName + "."; - for (Reference ref : cu.getReferences(getClass().getClassLoader()).getReferences()) { + for (Reference ref : cu.getReferences().getReferences()) { if (ref.getValue().equals(oldPackageName) || recursive && ref.getValue().startsWith(recursivePackageNamePrefix)) { return SearchResult.found(cu); } @@ -141,7 +141,7 @@ public boolean isAcceptable(SourceFile sourceFile, ExecutionContext ctx) { return new JavaChangePackageVisitor().visit(tree, ctx, requireNonNull(getCursor().getParent())); } else if (tree instanceof SourceFileWithReferences) { SourceFileWithReferences sourceFile = (SourceFileWithReferences) tree; - SourceFileWithReferences.References references = sourceFile.getReferences(getClass().getClassLoader()); + SourceFileWithReferences.References references = sourceFile.getReferences(); boolean recursive = Boolean.TRUE.equals(ChangePackage.this.recursive); PackageMatcher matcher = new PackageMatcher(oldPackageName, recursive); Map matches = new HashMap<>(); diff --git a/rewrite-java/src/main/java/org/openrewrite/java/ChangeType.java b/rewrite-java/src/main/java/org/openrewrite/java/ChangeType.java index 04181e3d831..8cdb8cf4865 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/ChangeType.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/ChangeType.java @@ -111,7 +111,7 @@ public boolean isAcceptable(SourceFile sourceFile, ExecutionContext ctx) { return new JavaChangeTypeVisitor(oldFullyQualifiedTypeName, newFullyQualifiedTypeName, ignoreDefinition).visit(tree, ctx, requireNonNull(getCursor().getParent())); } else if (tree instanceof SourceFileWithReferences) { SourceFileWithReferences sourceFile = (SourceFileWithReferences) tree; - SourceFileWithReferences.References references = sourceFile.getReferences(getClass().getClassLoader()); + SourceFileWithReferences.References references = sourceFile.getReferences(); TypeMatcher matcher = new TypeMatcher(oldFullyQualifiedTypeName); Map matches = new HashMap<>(); for (Reference ref : references.findMatches(matcher)) { diff --git a/rewrite-java/src/main/java/org/openrewrite/java/search/FindTypes.java b/rewrite-java/src/main/java/org/openrewrite/java/search/FindTypes.java index 64f08064dbc..7a0dff047c5 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/search/FindTypes.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/search/FindTypes.java @@ -77,7 +77,7 @@ public boolean isAcceptable(SourceFile sourceFile, ExecutionContext ctx) { return new JavaSourceFileVisitor(fullyQualifiedType).visit(tree, ctx); } else if (tree instanceof SourceFileWithReferences) { SourceFileWithReferences sourceFile = (SourceFileWithReferences) tree; - SourceFileWithReferences.References references = sourceFile.getReferences(getClass().getClassLoader()); + SourceFileWithReferences.References references = sourceFile.getReferences(); TypeMatcher matcher = new TypeMatcher(fullyQualifiedTypeName); Set matches = references.findMatches(matcher).stream().map(Trait::getTree).collect(Collectors.toSet()); return new ReferenceVisitor(matches).visit(tree, ctx); diff --git a/rewrite-java/src/main/java/org/openrewrite/java/search/UsesType.java b/rewrite-java/src/main/java/org/openrewrite/java/search/UsesType.java index 163f0af3e45..4044dfcbc78 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/search/UsesType.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/search/UsesType.java @@ -121,7 +121,7 @@ public boolean isAcceptable(SourceFile sourceFile, P p) { } } else if (tree instanceof SourceFileWithReferences) { SourceFileWithReferences sourceFile = (SourceFileWithReferences) tree; - SourceFileWithReferences.References references = sourceFile.getReferences(getClass().getClassLoader()); + SourceFileWithReferences.References references = sourceFile.getReferences(); TypeMatcher matcher = typeMatcher != null ? typeMatcher : new TypeMatcher(fullyQualifiedType); for (Reference ignored : references.findMatches(matcher)) { return SearchResult.found(sourceFile); diff --git a/rewrite-properties/src/main/java/org/openrewrite/properties/tree/Properties.java b/rewrite-properties/src/main/java/org/openrewrite/properties/tree/Properties.java index e9b77bfc749..d24b3706fa7 100755 --- a/rewrite-properties/src/main/java/org/openrewrite/properties/tree/Properties.java +++ b/rewrite-properties/src/main/java/org/openrewrite/properties/tree/Properties.java @@ -118,7 +118,7 @@ public

TreeVisitor> printer(Cursor cursor) { transient SoftReference references; @Override - public References getReferences(ClassLoader classLoader) { + public References getReferences() { this.references = build(this.references); return Objects.requireNonNull(this.references.get()); } diff --git a/rewrite-properties/src/test/java/org/openrewrite/properties/trait/PropertiesReferenceTest.java b/rewrite-properties/src/test/java/org/openrewrite/properties/trait/PropertiesReferenceTest.java index 0ab6a3e24d0..5283957a46d 100644 --- a/rewrite-properties/src/test/java/org/openrewrite/properties/trait/PropertiesReferenceTest.java +++ b/rewrite-properties/src/test/java/org/openrewrite/properties/trait/PropertiesReferenceTest.java @@ -44,7 +44,7 @@ void findJavaReferencesInApplicationProperties(String filename) { properties( PROPERTIES, spec -> spec.path(filename).afterRecipe(doc -> - assertThat(doc.getReferences(getClass().getClassLoader()).getReferences()) + assertThat(doc.getReferences().getReferences()) .satisfiesExactlyInAnyOrder( ref -> { assertThat(ref.getKind()).isEqualTo(Reference.Kind.TYPE); @@ -72,7 +72,7 @@ void noReferencesInMismatchedFilenames(String filename) { rewriteRun( properties( PROPERTIES, - spec -> spec.path(filename).afterRecipe(doc -> assertThat(doc.getReferences(getClass().getClassLoader()).getReferences()).isEmpty()) + spec -> spec.path(filename).afterRecipe(doc -> assertThat(doc.getReferences().getReferences()).isEmpty()) ) ); } diff --git a/rewrite-xml/src/main/java/org/openrewrite/xml/tree/Xml.java b/rewrite-xml/src/main/java/org/openrewrite/xml/tree/Xml.java index b1aea9b0df5..138f470ab7a 100755 --- a/rewrite-xml/src/main/java/org/openrewrite/xml/tree/Xml.java +++ b/rewrite-xml/src/main/java/org/openrewrite/xml/tree/Xml.java @@ -168,7 +168,7 @@ public T service(Class service) { transient SoftReference references; @Override - public References getReferences(ClassLoader classLoader) { + public References getReferences() { this.references = build(this.references); return Objects.requireNonNull(this.references.get()); } diff --git a/rewrite-xml/src/test/java/org/openrewrite/xml/XmlParserTest.java b/rewrite-xml/src/test/java/org/openrewrite/xml/XmlParserTest.java index 2dc78b5ca6e..57ae47a0905 100755 --- a/rewrite-xml/src/test/java/org/openrewrite/xml/XmlParserTest.java +++ b/rewrite-xml/src/test/java/org/openrewrite/xml/XmlParserTest.java @@ -145,9 +145,9 @@ void javaReferenceDocument() { """, spec -> spec.afterRecipe(doc -> { - assertThat(doc.getReferences(getClass().getClassLoader()).getReferences().stream().anyMatch(typeRef -> typeRef.getValue().equals("java.lang.String"))).isTrue(); - assertThat(doc.getReferences(getClass().getClassLoader()).getReferences().stream().anyMatch(typeRef -> typeRef.getKind() == Reference.Kind.TYPE)).isTrue(); - assertThat(doc.getReferences(getClass().getClassLoader()).getReferences().stream().anyMatch(typeRef -> typeRef.getKind() == Reference.Kind.PACKAGE)).isTrue(); + assertThat(doc.getReferences().getReferences().stream().anyMatch(typeRef -> typeRef.getValue().equals("java.lang.String"))).isTrue(); + assertThat(doc.getReferences().getReferences().stream().anyMatch(typeRef -> typeRef.getKind() == Reference.Kind.TYPE)).isTrue(); + assertThat(doc.getReferences().getReferences().stream().anyMatch(typeRef -> typeRef.getKind() == Reference.Kind.PACKAGE)).isTrue(); }) ) ); diff --git a/rewrite-yaml/src/main/java/org/openrewrite/yaml/tree/Yaml.java b/rewrite-yaml/src/main/java/org/openrewrite/yaml/tree/Yaml.java index 2c9e03862d2..9603f3e11db 100755 --- a/rewrite-yaml/src/main/java/org/openrewrite/yaml/tree/Yaml.java +++ b/rewrite-yaml/src/main/java/org/openrewrite/yaml/tree/Yaml.java @@ -136,7 +136,7 @@ public

TreeVisitor> printer(Cursor cursor) { transient SoftReference references; @Override - public References getReferences(ClassLoader classLoader) { + public References getReferences() { this.references = build(this.references); return Objects.requireNonNull(this.references.get()); } diff --git a/rewrite-yaml/src/test/java/org/openrewrite/yaml/trait/YamlReferenceTest.java b/rewrite-yaml/src/test/java/org/openrewrite/yaml/trait/YamlReferenceTest.java index 662a7838266..ddc9abdeff9 100644 --- a/rewrite-yaml/src/test/java/org/openrewrite/yaml/trait/YamlReferenceTest.java +++ b/rewrite-yaml/src/test/java/org/openrewrite/yaml/trait/YamlReferenceTest.java @@ -53,7 +53,7 @@ void findJavaReferencesInYamlProperties(String filename) { yaml( YAML, spec -> spec.path(filename).afterRecipe(doc -> - assertThat(doc.getReferences(getClass().getClassLoader()).getReferences()).satisfiesExactlyInAnyOrder( + assertThat(doc.getReferences().getReferences()).satisfiesExactlyInAnyOrder( ref -> { assertThat(ref.getKind()).isEqualTo(Reference.Kind.TYPE); assertThat(ref.getValue()).isEqualTo("java.lang.String"); @@ -90,7 +90,7 @@ void noReferencesInMismatchedFilenames(String filename) { rewriteRun( yaml( YAML, - spec -> spec.path(filename).afterRecipe(doc -> assertThat(doc.getReferences(getClass().getClassLoader()).getReferences()).isEmpty()) + spec -> spec.path(filename).afterRecipe(doc -> assertThat(doc.getReferences().getReferences()).isEmpty()) ) ); } @@ -108,7 +108,7 @@ void endsWithDot() { """, spec -> spec .path("application.yml") - .afterRecipe(doc -> assertThat(doc.getReferences(getClass().getClassLoader()).getReferences()).singleElement().satisfies( + .afterRecipe(doc -> assertThat(doc.getReferences().getReferences()).singleElement().satisfies( ref -> { assertThat(ref.getKind()).isEqualTo(Reference.Kind.TYPE); assertThat(ref.getValue()).isEqualTo("org.openrewrite.java.DoSomething"); From 431e371fcda517db48a4e9ee6fc25059293561f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merlin=20B=C3=B6gershausen?= Date: Fri, 14 Feb 2025 12:39:10 +0100 Subject: [PATCH 06/14] remove artefact --- .../openrewrite/gradle/AddDependencyTest.java | 55 ++----------------- 1 file changed, 5 insertions(+), 50 deletions(-) diff --git a/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java b/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java index 09f132689cd..6bf96f4ad45 100644 --- a/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java +++ b/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java @@ -21,10 +21,12 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; -import org.openrewrite.*; +import org.openrewrite.ExecutionContext; +import org.openrewrite.Issue; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; import org.openrewrite.gradle.marker.GradleDependencyConfiguration; import org.openrewrite.gradle.marker.GradleProject; -import org.openrewrite.java.JavaIsoVisitor; import org.openrewrite.java.JavaParser; import org.openrewrite.java.JavaVisitor; import org.openrewrite.java.tree.J; @@ -32,7 +34,6 @@ import org.openrewrite.test.RewriteTest; import org.openrewrite.test.TypeValidation; -import java.util.List; import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; @@ -41,12 +42,7 @@ import static org.openrewrite.gradle.toolingapi.Assertions.withToolingApi; import static org.openrewrite.groovy.Assertions.groovy; import static org.openrewrite.groovy.Assertions.srcMainGroovy; -import static org.openrewrite.java.Assertions.java; -import static org.openrewrite.java.Assertions.mavenProject; -import static org.openrewrite.java.Assertions.srcMainJava; -import static org.openrewrite.java.Assertions.srcMainResources; -import static org.openrewrite.java.Assertions.srcSmokeTestJava; -import static org.openrewrite.java.Assertions.srcTestJava; +import static org.openrewrite.java.Assertions.*; import static org.openrewrite.properties.Assertions.properties; @SuppressWarnings("GroovyUnusedAssignment") @@ -67,47 +63,6 @@ boolean getMap() { } """; - public static class TSTRecipe extends Recipe { - @Override - public String getDisplayName() { - return "A"; - } - - @Override - public String getDescription() { - return "B."; - } - - @Override - public TreeVisitor getVisitor() { - return new JavaVisitor<>(){ - - @Override - public J visitMethodDeclaration(J.MethodDeclaration method, ExecutionContext ctx) { - return super.visitMethodDeclaration(method, ctx); - } - }; - } - } - - @Disabled - @Test - void tsts() { - rewriteRun( - spec -> spec.recipe(new TSTRecipe()), - java( - """ - import java.util.List; - class A { - void tst() { - List.of("A", "B"); - } - } - """ - ) - ); - } - @ParameterizedTest @ValueSource(strings = {"com.google.common.math.*", "com.google.common.math.IntMath"}) void onlyIfUsingTestScope(String onlyIfUsing) { From 049e6157c25fb36db42d32f2d06802897648cf2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merlin=20B=C3=B6gershausen?= Date: Fri, 14 Feb 2025 12:39:43 +0100 Subject: [PATCH 07/14] remove artefact --- .../src/main/java/org/openrewrite/SourceFileWithReferences.java | 1 - 1 file changed, 1 deletion(-) diff --git a/rewrite-core/src/main/java/org/openrewrite/SourceFileWithReferences.java b/rewrite-core/src/main/java/org/openrewrite/SourceFileWithReferences.java index bf7aa7ab987..bb1584aaabf 100644 --- a/rewrite-core/src/main/java/org/openrewrite/SourceFileWithReferences.java +++ b/rewrite-core/src/main/java/org/openrewrite/SourceFileWithReferences.java @@ -57,7 +57,6 @@ public Collection findMatches(Reference.Matcher matcher) { private static References build(SourceFile sourceFile) { Set references = new HashSet<>(); ServiceLoader loader = ServiceLoader.load(Reference.Provider.class); - loader.reload(); loader.forEach(provider -> { if (provider.isAcceptable(sourceFile)) { references.addAll(provider.getReferences(sourceFile)); From 596328b9d1936a345373b5ea783c515a70a46c26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merlin=20B=C3=B6gershausen?= Date: Fri, 21 Feb 2025 13:04:34 +0100 Subject: [PATCH 08/14] rollback changes --- .../java/org/openrewrite/RecipeScheduler.java | 1 - .../openrewrite/gradle/AddDependencyTest.java | 252 +++++++++++++++++- 2 files changed, 243 insertions(+), 10 deletions(-) diff --git a/rewrite-core/src/main/java/org/openrewrite/RecipeScheduler.java b/rewrite-core/src/main/java/org/openrewrite/RecipeScheduler.java index b98317507aa..795dad5b841 100644 --- a/rewrite-core/src/main/java/org/openrewrite/RecipeScheduler.java +++ b/rewrite-core/src/main/java/org/openrewrite/RecipeScheduler.java @@ -38,7 +38,6 @@ public RecipeRun scheduleRun(Recipe recipe, int maxCycles, int minCycles) { try { - Thread.currentThread().setContextClassLoader(recipe.getClass().getClassLoader()); LargeSourceSet after = runRecipeCycles(recipe, sourceSet, ctx, maxCycles, minCycles); return new RecipeRun( after.getChangeset(), diff --git a/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java b/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java index 6bf96f4ad45..9f112b539a7 100644 --- a/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java +++ b/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java @@ -17,19 +17,15 @@ import org.intellij.lang.annotations.Language; import org.jspecify.annotations.Nullable; -import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.ValueSource; -import org.openrewrite.ExecutionContext; import org.openrewrite.Issue; -import org.openrewrite.Recipe; -import org.openrewrite.TreeVisitor; import org.openrewrite.gradle.marker.GradleDependencyConfiguration; import org.openrewrite.gradle.marker.GradleProject; import org.openrewrite.java.JavaParser; -import org.openrewrite.java.JavaVisitor; -import org.openrewrite.java.tree.J; import org.openrewrite.test.RecipeSpec; import org.openrewrite.test.RewriteTest; import org.openrewrite.test.TypeValidation; @@ -688,7 +684,7 @@ class A { dependencies { implementation "commons-lang:commons-lang:2.6" - + testImplementation "junit:junit:4.13" } """, @@ -734,7 +730,7 @@ void addDependenciesToExistingGrouping() { dependencies { implementation group: "commons-lang", name: "commons-lang", version: "1.0" - + def junitVersion = "4.12" testImplementation group: "junit", name: "junit", version: junitVersion } @@ -936,7 +932,7 @@ void matchesDependencyDeclarationStyle() { dependencies { implementation group: "commons-lang", name: "commons-lang", version: "1.0" - + testImplementation group: "com.google.guava", name: "guava", version: "29.0-jre" } """ @@ -1346,6 +1342,244 @@ void addUnconditionally() { ); } + @Nested + @Issue("https://github.com/moderneinc/customer-requests/issues/792") + class AddToJVMTestSuite { + @Test + void addToJVMSuite() { + rewriteRun( + spec -> spec.recipe(addDependency("com.google.guava:guava:29.0-jre")), + mavenProject("project", + srcMainJava( + java(usingGuavaIntMath, sourceSpecs -> sourceSet(sourceSpecs, "integrationTest"))), + buildGradle( + //language=groovy + """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + dependencies { + implementation "org.apache.logging.log4j:log4j-core:2.22.1" + } + + testing { + suites { + integrationTest(JvmTestSuite) { + dependencies { + } + } + } + } + """, + """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + dependencies { + implementation "org.apache.logging.log4j:log4j-core:2.22.1" + } + + testing { + suites { + integrationTest(JvmTestSuite) { + dependencies { + implementation "com.google.guava:guava:29.0-jre" + } + } + } + } + """ + ))); + } + + @Test + void actNormalForDefaultTestWithoutSuiteDefinition() { + rewriteRun( + spec -> spec.recipe(addDependency("com.google.guava:guava:29.0-jre")), + mavenProject("project", + srcMainJava( + java(usingGuavaIntMath, sourceSpecs -> sourceSet(sourceSpecs, "test"))), + buildGradle( + //language=groovy + """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + dependencies { + implementation "org.apache.logging.log4j:log4j-core:2.22.1" + } + + testing { + suites { + integrationTest(JvmTestSuite) { + dependencies { + } + } + } + } + """, + """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + dependencies { + implementation "org.apache.logging.log4j:log4j-core:2.22.1" + + testImplementation "com.google.guava:guava:29.0-jre" + } + + testing { + suites { + integrationTest(JvmTestSuite) { + dependencies { + } + } + } + } + """ + ))); + } + + @Test + void actNormalForSuiteWithoutDependencyBlock() { + rewriteRun( + spec -> spec.recipe(addDependency("com.google.guava:guava:29.0-jre")), + mavenProject("project", + srcMainJava( + java(usingGuavaIntMath, sourceSpecs -> sourceSet(sourceSpecs, "integrationTest"))), + buildGradle( + //language=groovy + """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + testing { + suites { + integrationTest(JvmTestSuite) { + } + } + } + """, + """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + testing { + suites { + integrationTest(JvmTestSuite) { + } + } + } + + dependencies { + integrationTestImplementation "com.google.guava:guava:29.0-jre" + } + """ + ))); + } + + @ParameterizedTest + @CsvSource({ + "integrationTestImplementation,implementation", + "integrationTestCompileOnly,compileOnly", + "integrationTestRuntimeOnly,runtimeOnly", + "integrationTestAnnotationProcessor,annotationProcessor"}) + void withExplicitConfiguration(String recipeConfiguration, String gradleConfiguration) { + rewriteRun( + spec -> spec.recipe(addDependency("com.google.guava:guava:29.0-jre", null, recipeConfiguration)), + mavenProject("project", + srcMainJava( + java(usingGuavaIntMath, sourceSpecs -> sourceSet(sourceSpecs, "integrationTest"))), + buildGradle( + //language=groovy + """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + dependencies { + implementation "org.apache.logging.log4j:log4j-core:2.22.1" + } + + testing { + suites { + integrationTest(JvmTestSuite) { + dependencies { + } + } + } + } + """, + //language=groovy + """ + plugins { + id "java-library" + id 'jvm-test-suite' + } + + repositories { + mavenCentral() + } + + dependencies { + implementation "org.apache.logging.log4j:log4j-core:2.22.1" + } + + testing { + suites { + integrationTest(JvmTestSuite) { + dependencies { + %s "com.google.guava:guava:29.0-jre" + } + } + } + } + """.formatted(gradleConfiguration) + ))); + } + } + private AddDependency addDependency(@SuppressWarnings("SameParameterValue") String gav) { return addDependency(gav, null, null); } From 8117508a4c3efc6ba003b9c465e680e3c69462da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merlin=20B=C3=B6gershausen?= Date: Fri, 21 Feb 2025 13:04:57 +0100 Subject: [PATCH 09/14] use `InMemoryLargeSourceSet` to set TCCL properly --- .../internal/InMemoryLargeSourceSet.java | 38 +++++++++++++++++-- .../LargeSourceSetCheckingExpectedCycles.java | 2 +- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/rewrite-core/src/main/java/org/openrewrite/internal/InMemoryLargeSourceSet.java b/rewrite-core/src/main/java/org/openrewrite/internal/InMemoryLargeSourceSet.java index 1d8fb5828bb..c1aab7c1aec 100644 --- a/rewrite-core/src/main/java/org/openrewrite/internal/InMemoryLargeSourceSet.java +++ b/rewrite-core/src/main/java/org/openrewrite/internal/InMemoryLargeSourceSet.java @@ -39,20 +39,32 @@ public class InMemoryLargeSourceSet implements LargeSourceSet { private List currentRecipeStack; + @Nullable + private ClassLoader originalTCCL; + + @Nullable + private ClassLoader recipeClassLoader; + public InMemoryLargeSourceSet(List ls) { - this(null, null, ls); + this(null, null, ls, null); + } + + public InMemoryLargeSourceSet(List ls, @Nullable ClassLoader classLoader) { + this(null, null, ls, classLoader); } protected InMemoryLargeSourceSet(@Nullable InMemoryLargeSourceSet initialState, @Nullable Map> deletions, - List ls) { + List ls, + @Nullable ClassLoader classLoader) { this.initialState = initialState; this.ls = ls; this.deletions = deletions; + this.recipeClassLoader = classLoader; } protected InMemoryLargeSourceSet withChanges(@Nullable Map> deletions, List mapped) { - return new InMemoryLargeSourceSet(getInitialState(), deletions, mapped); + return new InMemoryLargeSourceSet(getInitialState(), deletions, mapped, recipeClassLoader); } @Override @@ -94,6 +106,26 @@ protected InMemoryLargeSourceSet getInitialState() { return initialState == null ? this : initialState; } + @Override + public void beforeCycle(boolean definitelyLastCycle) { + LargeSourceSet.super.beforeCycle(definitelyLastCycle); + if (recipeClassLoader != null) { + // set TCCL to the recipe's classloader and store the original value, needed by SPI to load providers from recipe artifacts + originalTCCL = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(recipeClassLoader); + } + } + + @Override + public void afterCycle(boolean lastCycle) { + try { + LargeSourceSet.super.afterCycle(lastCycle); + } finally { + // reset TCCL value to the original one to no infer with other tooling + Thread.currentThread().setContextClassLoader(originalTCCL); + } + } + @Override public Changeset getChangeset() { Map sourceFileIdentities = new HashMap<>(); diff --git a/rewrite-test/src/main/java/org/openrewrite/test/LargeSourceSetCheckingExpectedCycles.java b/rewrite-test/src/main/java/org/openrewrite/test/LargeSourceSetCheckingExpectedCycles.java index 6b14d34aabf..23a4a83923e 100644 --- a/rewrite-test/src/main/java/org/openrewrite/test/LargeSourceSetCheckingExpectedCycles.java +++ b/rewrite-test/src/main/java/org/openrewrite/test/LargeSourceSetCheckingExpectedCycles.java @@ -42,7 +42,7 @@ class LargeSourceSetCheckingExpectedCycles extends InMemoryLargeSourceSet { } private LargeSourceSetCheckingExpectedCycles(LargeSourceSetCheckingExpectedCycles from, @Nullable Map> deletions, List mapped) { - super(from.getInitialState(), deletions, mapped); + super(from.getInitialState(), deletions, mapped, null); this.expectedCyclesThatMakeChanges = from.expectedCyclesThatMakeChanges; this.cyclesThatResultedInChanges = from.cyclesThatResultedInChanges; this.lastCycleEdits = from.lastCycleEdits; From 9b182fe3a619236d3972589132a994afd2011548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merlin=20B=C3=B6gershausen?= Date: Mon, 24 Feb 2025 17:08:49 +0100 Subject: [PATCH 10/14] move adjustments to the TCCL into edit method to avoid thread related clashes --- .../internal/InMemoryLargeSourceSet.java | 47 ++++++++++--------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/rewrite-core/src/main/java/org/openrewrite/internal/InMemoryLargeSourceSet.java b/rewrite-core/src/main/java/org/openrewrite/internal/InMemoryLargeSourceSet.java index 78114404c3e..6e95c5d1453 100644 --- a/rewrite-core/src/main/java/org/openrewrite/internal/InMemoryLargeSourceSet.java +++ b/rewrite-core/src/main/java/org/openrewrite/internal/InMemoryLargeSourceSet.java @@ -40,9 +40,6 @@ public class InMemoryLargeSourceSet implements LargeSourceSet { private List currentRecipeStack; - @Nullable - private ClassLoader originalTCCL; - @Nullable private ClassLoader recipeClassLoader; @@ -75,17 +72,31 @@ public void setRecipe(List recipeStack) { @Override public LargeSourceSet edit(UnaryOperator map) { - List mapped = ListUtils.map(ls, before -> { - SourceFile after = map.apply(before); - if (after == null) { - if (deletions == null) { - deletions = new LinkedHashMap<>(); + ClassLoader originalTCCL = null; + try { + if (recipeClassLoader != null) { + // set TCCL to the recipe's classloader and store the original value, needed by SPI to load providers from recipe artifacts + originalTCCL = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(recipeClassLoader); + } + List mapped = ListUtils.map(ls, before -> { + SourceFile after = map.apply(before); + if (after == null) { + if (deletions == null) { + deletions = new LinkedHashMap<>(); + } + deletions.put(before, currentRecipeStack); } - deletions.put(before, currentRecipeStack); + return after; + }); + return mapped != ls ? withChanges(deletions, mapped) : this; + } finally { + if (originalTCCL != null) { + // reset TCCL value to the original one to no infer with other tooling + Thread.currentThread().setContextClassLoader(originalTCCL); } - return after; - }); - return mapped != ls ? withChanges(deletions, mapped) : this; + } + } @Override @@ -110,21 +121,11 @@ protected InMemoryLargeSourceSet getInitialState() { @Override public void beforeCycle(boolean definitelyLastCycle) { LargeSourceSet.super.beforeCycle(definitelyLastCycle); - if (recipeClassLoader != null) { - // set TCCL to the recipe's classloader and store the original value, needed by SPI to load providers from recipe artifacts - originalTCCL = Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(recipeClassLoader); - } } @Override public void afterCycle(boolean lastCycle) { - try { - LargeSourceSet.super.afterCycle(lastCycle); - } finally { - // reset TCCL value to the original one to no infer with other tooling - Thread.currentThread().setContextClassLoader(originalTCCL); - } + LargeSourceSet.super.afterCycle(lastCycle); } @Override From 06f9240f9d34733fe2dc61462298e2e401015460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merlin=20B=C3=B6gershausen?= Date: Mon, 24 Feb 2025 17:20:18 +0100 Subject: [PATCH 11/14] remove not needed methods --- .../openrewrite/internal/InMemoryLargeSourceSet.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/rewrite-core/src/main/java/org/openrewrite/internal/InMemoryLargeSourceSet.java b/rewrite-core/src/main/java/org/openrewrite/internal/InMemoryLargeSourceSet.java index 6e95c5d1453..2a996f31569 100644 --- a/rewrite-core/src/main/java/org/openrewrite/internal/InMemoryLargeSourceSet.java +++ b/rewrite-core/src/main/java/org/openrewrite/internal/InMemoryLargeSourceSet.java @@ -118,16 +118,6 @@ protected InMemoryLargeSourceSet getInitialState() { return initialState == null ? this : initialState; } - @Override - public void beforeCycle(boolean definitelyLastCycle) { - LargeSourceSet.super.beforeCycle(definitelyLastCycle); - } - - @Override - public void afterCycle(boolean lastCycle) { - LargeSourceSet.super.afterCycle(lastCycle); - } - @Override public Changeset getChangeset() { Map sourceFileIdentities = new HashMap<>(); From dacd1d670b0d5843214e1df17ee45742b1113d74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merlin=20B=C3=B6gershausen?= Date: Wed, 26 Feb 2025 15:13:05 +0100 Subject: [PATCH 12/14] propose reusable composite loader that delegates calls to a list of child class loaders until the first result is found --- .../openrewrite/java/CompositClassLoader.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 rewrite-java/src/main/java/org/openrewrite/java/CompositClassLoader.java diff --git a/rewrite-java/src/main/java/org/openrewrite/java/CompositClassLoader.java b/rewrite-java/src/main/java/org/openrewrite/java/CompositClassLoader.java new file mode 100644 index 00000000000..e4bf04634e9 --- /dev/null +++ b/rewrite-java/src/main/java/org/openrewrite/java/CompositClassLoader.java @@ -0,0 +1,51 @@ +package org.openrewrite.java; + +import org.jetbrains.annotations.Nullable; + +import java.net.URL; +import java.util.Arrays; +import java.util.List; + +/** + * A composite class loader that delegates to a list of child class loaders. + * This Classloader comes in handy when recipes from different artifacts are used together which are loaded dependently. + * The implementations will return the first found result. + */ +public class CompositClassLoader extends ClassLoader { + + static { + ClassLoader.registerAsParallelCapable(); + } + + private final ClassLoader[] childLoaders; + + public CompositClassLoader(List childLoaders) { + this.childLoaders = childLoaders.toArray(new ClassLoader[0]); + } + + public CompositClassLoader(ClassLoader... childLoaders) { + this.childLoaders = Arrays.copyOf(childLoaders, childLoaders.length); + } + + @Override + public Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + for (ClassLoader childLoader : childLoaders) { + try { + return childLoader.loadClass(name); + } catch (ClassNotFoundException ignored) { + } + } + throw new ClassNotFoundException(name); + } + + @Override + public @Nullable URL getResource(String name) { + for (ClassLoader childLoader : childLoaders) { + URL resource = childLoader.getResource(name); + if (resource != null) { + return resource; + } + } + return null; // null means found nothing + } +} From db8f9f34054a5634d24fbaf403c2c0a3dd3eafc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merlin=20B=C3=B6gershausen?= Date: Wed, 26 Feb 2025 15:19:35 +0100 Subject: [PATCH 13/14] add license informations --- .../org/openrewrite/java/CompositClassLoader.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/rewrite-java/src/main/java/org/openrewrite/java/CompositClassLoader.java b/rewrite-java/src/main/java/org/openrewrite/java/CompositClassLoader.java index e4bf04634e9..ab265e1cbbe 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/CompositClassLoader.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/CompositClassLoader.java @@ -1,3 +1,18 @@ +/* + * Copyright 2025 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.openrewrite.java; import org.jetbrains.annotations.Nullable; From d5d1c749b38b880bd35375ce161023ed796a36c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Merlin=20B=C3=B6gershausen?= Date: Wed, 26 Feb 2025 17:16:59 +0100 Subject: [PATCH 14/14] remove CompositClassLoader.java --- .../openrewrite/java/CompositClassLoader.java | 66 ------------------- 1 file changed, 66 deletions(-) delete mode 100644 rewrite-java/src/main/java/org/openrewrite/java/CompositClassLoader.java diff --git a/rewrite-java/src/main/java/org/openrewrite/java/CompositClassLoader.java b/rewrite-java/src/main/java/org/openrewrite/java/CompositClassLoader.java deleted file mode 100644 index ab265e1cbbe..00000000000 --- a/rewrite-java/src/main/java/org/openrewrite/java/CompositClassLoader.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2025 the original author or authors. - *

- * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - *

- * https://www.apache.org/licenses/LICENSE-2.0 - *

- * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.openrewrite.java; - -import org.jetbrains.annotations.Nullable; - -import java.net.URL; -import java.util.Arrays; -import java.util.List; - -/** - * A composite class loader that delegates to a list of child class loaders. - * This Classloader comes in handy when recipes from different artifacts are used together which are loaded dependently. - * The implementations will return the first found result. - */ -public class CompositClassLoader extends ClassLoader { - - static { - ClassLoader.registerAsParallelCapable(); - } - - private final ClassLoader[] childLoaders; - - public CompositClassLoader(List childLoaders) { - this.childLoaders = childLoaders.toArray(new ClassLoader[0]); - } - - public CompositClassLoader(ClassLoader... childLoaders) { - this.childLoaders = Arrays.copyOf(childLoaders, childLoaders.length); - } - - @Override - public Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - for (ClassLoader childLoader : childLoaders) { - try { - return childLoader.loadClass(name); - } catch (ClassNotFoundException ignored) { - } - } - throw new ClassNotFoundException(name); - } - - @Override - public @Nullable URL getResource(String name) { - for (ClassLoader childLoader : childLoaders) { - URL resource = childLoader.getResource(name); - if (resource != null) { - return resource; - } - } - return null; // null means found nothing - } -}