From 1114a98a8a169e4018cd113641d30b728fb4171f Mon Sep 17 00:00:00 2001 From: Joan Viladrosa Date: Tue, 5 Sep 2023 00:17:34 +0200 Subject: [PATCH 01/20] fixed project provenance on gradle files (#226) --- .../gradle/isolated/DefaultProjectParser.java | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java index 4ae1ebc87..16d19d843 100644 --- a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java +++ b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java @@ -640,7 +640,7 @@ public Stream parse(Project subproject, Set alreadyParsed, Exe if (subproject.getPlugins().hasPlugin("org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension") || subproject.getExtensions().findByName("kotlin") != null && subproject.getExtensions().getByName("kotlin").getClass() .getCanonicalName().startsWith("org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension")) { - sourceFileStream = sourceFileStream.concat(parseMultiplatformKotlinProject(subproject, exclusions, alreadyParsed, projectProvenance, ctx)); + sourceFileStream = sourceFileStream.concat(parseMultiplatformKotlinProject(subproject, exclusions, alreadyParsed, ctx)); } for (SourceSet sourceSet : sourceSets) { @@ -798,17 +798,18 @@ public Stream parse(Project subproject, Set alreadyParsed, Exe } JavaSourceSet sourceSetProvenance = JavaSourceSet.build(sourceSet.getName(), dependencyPaths, javaTypeCache, false); - sourceFileStream = sourceFileStream.concat(sourceSetSourceFiles.map(addProvenance(projectProvenance, sourceSetProvenance)), sourceSetSize); + sourceFileStream = sourceFileStream.concat(sourceSetSourceFiles.map(addProvenance(sourceSetProvenance)), sourceSetSize); } - - sourceFileStream = sourceFileStream.concat(parseGradleFiles(exclusions, alreadyParsed, ctx)); + SourceFileStream gradleFiles = parseGradleFiles(exclusions, alreadyParsed, ctx); + sourceFileStream = sourceFileStream.concat(gradleFiles, gradleFiles.size()); SourceFileStream nonProjectResources = parseNonProjectResources(subproject, alreadyParsed, ctx, projectProvenance, sourceFileStream); - sourceFileStream = sourceFileStream.concat(nonProjectResources - .map(addProvenance(projectProvenance, null)), nonProjectResources.size()); + sourceFileStream = sourceFileStream.concat(nonProjectResources, nonProjectResources.size()); progressBar.setMax(sourceFileStream.size()); - return sourceFileStream.peek(it -> progressBar.step()); + return sourceFileStream + .map(addProvenance(projectProvenance)) + .peek(it -> progressBar.step()); } catch (Exception e) { throw new RuntimeException(e); } @@ -952,7 +953,7 @@ private Collection pathMatchers(Path basePath, Collection p .collect(Collectors.toList()); } - private SourceFileStream parseMultiplatformKotlinProject(Project subproject, Collection exclusions, Set alreadyParsed, List projectProvenance, ExecutionContext ctx) { + private SourceFileStream parseMultiplatformKotlinProject(Project subproject, Collection exclusions, Set alreadyParsed, ExecutionContext ctx) { Object kotlinExtension = subproject.getExtensions().getByName("kotlin"); NamedDomainObjectContainer sourceSets; try { @@ -1044,7 +1045,7 @@ private SourceFileStream parseMultiplatformKotlinProject(Project subproject, Col }).filter(Objects::nonNull); JavaSourceSet sourceSetProvenance = JavaSourceSet.build(sourceSetName, dependencyPaths, javaTypeCache, false); - sourceFileStream = sourceFileStream.concat(cus.map(addProvenance(projectProvenance, sourceSetProvenance)), kotlinPaths.size()); + sourceFileStream = sourceFileStream.concat(cus.map(addProvenance(sourceSetProvenance)), kotlinPaths.size()); logger.info("Scanned {} Kotlin sources in {}/{}", kotlinPaths.size(), subproject.getPath(), kotlinDirectorySet.getName()); } return sourceFileStream; @@ -1150,19 +1151,25 @@ private UnaryOperator applyAutodetectedStyle(Map UnaryOperator addProvenance(List projectProvenance, @Nullable Marker sourceSet) { + private UnaryOperator addProvenance(List projectProvenance) { return s -> { Markers m = s.getMarkers(); for (Marker marker : projectProvenance) { - m = m.add(marker); - } - if (sourceSet != null) { - m = m.add(sourceSet); + m = m.addIfAbsent(marker); } return s.withMarkers(m); }; } + private UnaryOperator addProvenance(Marker sourceSet) { + return s -> { + Markers m = s.getMarkers(); + m = m.addIfAbsent(sourceSet); + return s.withMarkers(m); + }; + } + + protected void logRecipesThatMadeChanges(Result result) { String indent = " "; String prefix = " "; From 5927ee44626e7dbfebbcb9596d089b5eeda0aba2 Mon Sep 17 00:00:00 2001 From: Sam Snyder Date: Thu, 7 Sep 2023 20:38:12 -0700 Subject: [PATCH 02/20] Don't double-parse files that appear in multiple, overlapping source sets --- plugin/build.gradle.kts | 5 +- .../org/openrewrite/gradle/RewritePlugin.java | 34 +++++++- .../gradle/isolated/DefaultProjectParser.java | 31 ++++++-- .../org/openrewrite/gradle/RewriteRunTest.kt | 77 +++++++++++++++++++ 4 files changed, 134 insertions(+), 13 deletions(-) diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index 194c0a184..003ddf497 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -67,7 +67,6 @@ configurations.all { } } - java { toolchain { languageVersion.set(JavaLanguageVersion.of(17)) @@ -109,6 +108,7 @@ dependencies { "rewriteDependencies"("org.openrewrite.gradle.tooling:model:$latest") "rewriteDependencies"("org.openrewrite:rewrite-maven") // Newer versions of checkstyle are compiled with a newer version of Java than is supported with gradle 4.x + @Suppress("VulnerableLibrariesLocal", "RedundantSuppression") "rewriteDependencies"("com.puppycrawl.tools:checkstyle:9.3") "rewriteDependencies"("com.fasterxml.jackson.module:jackson-module-kotlin:latest.release") @@ -126,6 +126,7 @@ dependencies { compileOnly("org.openrewrite:rewrite-xml") compileOnly("org.openrewrite:rewrite-yaml") compileOnly("org.openrewrite:rewrite-polyglot:$latest") + @Suppress("VulnerableLibrariesLocal", "RedundantSuppression") compileOnly("com.puppycrawl.tools:checkstyle:9.3") compileOnly("org.jetbrains.kotlin:kotlin-gradle-plugin:latest.release") @@ -155,7 +156,7 @@ tasks.withType() { } val gVP = tasks.register("generateVersionsProperties") { - val outputFile = file("$buildDir/rewrite/versions.properties") + val outputFile = file("${project.layout.buildDirectory.get().asFile}/rewrite/versions.properties") description = "Creates a versions.properties in $outputFile" group = "Build" diff --git a/plugin/src/main/java/org/openrewrite/gradle/RewritePlugin.java b/plugin/src/main/java/org/openrewrite/gradle/RewritePlugin.java index 8949fe13f..1549446dd 100644 --- a/plugin/src/main/java/org/openrewrite/gradle/RewritePlugin.java +++ b/plugin/src/main/java/org/openrewrite/gradle/RewritePlugin.java @@ -22,6 +22,11 @@ import org.gradle.api.plugins.quality.CheckstyleExtension; import org.gradle.api.plugins.quality.CheckstylePlugin; +import java.io.File; +import java.util.Comparator; +import java.util.HashSet; +import java.util.Set; + /** * When applied to the root project of a multi-project build, applies to all subprojects. * When applied to the root project the "rewrite" configuration and "rewrite" DSL created in the root project apply to @@ -37,7 +42,7 @@ public void apply(Project project) { if (!isRootProject && project.getRootProject().getPluginManager().hasPlugin("org.openrewrite.rewrite")) { return; } - if(project.getRootProject().getPluginManager().hasPlugin("io.moderne.rewrite")) { + if (project.getRootProject().getPluginManager().hasPlugin("io.moderne.rewrite")) { // Moderne plugin provides superset of rewrite plugin functionality, no need to apply both return; } @@ -67,7 +72,7 @@ public void apply(Project project) { .setResolveDependenciesTask(resolveRewriteDependenciesTask); rewriteDiscover.dependsOn(rewriteConf); - if(isRootProject) { + if (isRootProject) { project.allprojects(subproject -> configureProject(subproject, extension, rewriteDryRun, rewriteRun)); } else { configureProject(project, extension, rewriteDryRun, rewriteRun); @@ -78,14 +83,14 @@ private static void configureProject(Project project, RewriteExtension extension // DomainObjectCollection.all() accepts a function to be applied to both existing and subsequently added members of the collection // Do not replace all() with any form of collection iteration which does not share this important property project.getPlugins().all(plugin -> { - if(plugin instanceof CheckstylePlugin) { + if (plugin instanceof CheckstylePlugin) { // A multi-project build could hypothetically have different checkstyle configuration per-project // In practice all projects tend to have the same configuration CheckstyleExtension checkstyleExtension = project.getExtensions().getByType(CheckstyleExtension.class); extension.setCheckstyleConfigProvider(checkstyleExtension::getConfigFile); extension.setCheckstylePropertiesProvider(checkstyleExtension::getConfigProperties); } - if(!(plugin instanceof JavaBasePlugin)) { + if (!(plugin instanceof JavaBasePlugin)) { return; } @@ -99,6 +104,27 @@ private static void configureProject(Project project, RewriteExtension extension rewriteRun.dependsOn(compileTask); rewriteDryRun.dependsOn(compileTask); }); + + // Detect SourceSets which overlap other sourceSets and disable the compilation task of the overlapping + // source set. Some plugins will create source sets not intended to be compiled for their own purposes. + Set sourceDirs = new HashSet<>(); + project.afterEvaluate(unused -> javaConvention.getSourceSets().stream() + .sorted(Comparator.comparingInt(sourceSet -> { + if ("main".equals(sourceSet.getName())) { + return 0; + } else if ("test".equals(sourceSet.getName())) { + return 1; + } else { + return 2; + } + })).forEach(sourceSet -> { + for (File file : sourceSet.getAllSource().getSourceDirectories().getFiles()) { + if (!sourceDirs.add(file.getAbsolutePath())) { + Task compileTask = project.getTasks().getByPath(sourceSet.getCompileJavaTaskName()); + compileTask.setEnabled(false); + } + } + })); }); } } diff --git a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java index 16d19d843..fd1ee6f1d 100644 --- a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java +++ b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java @@ -85,7 +85,6 @@ import java.util.function.Consumer; import java.util.function.Supplier; import java.util.function.UnaryOperator; -import java.util.stream.Collectors; import java.util.stream.Stream; import static java.util.Collections.*; @@ -119,7 +118,7 @@ public DefaultProjectParser(Project project, RewriteExtension extension) { OperatingSystemProvenance.current(), new BuildTool(randomId(), BuildTool.Type.Gradle, project.getGradle().getGradleVersion())) .filter(Objects::nonNull) - .collect(Collectors.toList()); + .collect(toList()); } /** @@ -185,7 +184,7 @@ public List getActiveStyles() { } public List getAvailableStyles() { - return environment().listStyles().stream().map(NamedStyles::getName).collect(Collectors.toList()); + return environment().listStyles().stream().map(NamedStyles::getName).collect(toList()); } public void discoverRecipes(boolean interactive, ServiceRegistry serviceRegistry) { @@ -623,18 +622,27 @@ public Stream parse(Project subproject, Set alreadyParsed, Exe List styles = getStyles(); @SuppressWarnings("deprecation") JavaPluginConvention javaConvention = subproject.getConvention().findPlugin(JavaPluginConvention.class); - Set sourceSets; + List sourceSets; List projectProvenance; if (javaConvention == null) { projectProvenance = sharedProvenance; - sourceSets = Collections.emptySet(); + sourceSets = emptyList(); } else { projectProvenance = new ArrayList<>(sharedProvenance); projectProvenance.add(new JavaProject(randomId(), subproject.getName(), new JavaProject.Publication(subproject.getGroup().toString(), subproject.getName(), subproject.getVersion().toString()))); - sourceSets = javaConvention.getSourceSets(); + sourceSets = javaConvention.getSourceSets().stream() + .sorted(Comparator.comparingInt(sourceSet -> { + if ("main".equals(sourceSet.getName())) { + return 0; + } else if ("test".equals(sourceSet.getName())) { + return 1; + } else { + return 2; + } + })).collect(toList()); } if (subproject.getPlugins().hasPlugin("org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension") || @@ -643,7 +651,16 @@ public Stream parse(Project subproject, Set alreadyParsed, Exe sourceFileStream = sourceFileStream.concat(parseMultiplatformKotlinProject(subproject, exclusions, alreadyParsed, ctx)); } + Set sourceDirs = new HashSet<>(); + sourceSetLoop: for (SourceSet sourceSet : sourceSets) { + // Detect SourceSets which overlap other sourceSets and disable the compilation task of the overlapping + // source set. Skip parsing directories already covered by another source set. + for (File file : sourceSet.getAllSource().getSourceDirectories().getFiles()) { + if (!sourceDirs.add(file.getAbsolutePath())) { + continue sourceSetLoop; + } + } Stream sourceSetSourceFiles = Stream.of(); int sourceSetSize = 0; @@ -950,7 +967,7 @@ private static Collection mergeExclusions(Project project, Path baseDir, private Collection pathMatchers(Path basePath, Collection pathExpressions) { return pathExpressions.stream() .map(o -> basePath.getFileSystem().getPathMatcher("glob:" + o)) - .collect(Collectors.toList()); + .collect(toList()); } private SourceFileStream parseMultiplatformKotlinProject(Project subproject, Collection exclusions, Set alreadyParsed, ExecutionContext ctx) { diff --git a/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteRunTest.kt b/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteRunTest.kt index a86891f7d..41cd37646 100644 --- a/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteRunTest.kt +++ b/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteRunTest.kt @@ -972,4 +972,81 @@ class RewriteRunTest : RewritePluginTest { .`as`("Applicability test should have prevented this file from being altered") .isEqualTo("jonathan") } + + @Test + fun overlappingSourceSet(@TempDir buildRoot: File) { + gradleProject(buildRoot) { + rewriteYaml(""" + type: specs.openrewrite.org/v1beta/recipe + name: org.openrewrite.test.FindSneaky + displayName: Find lombok SneakyThrows annotation + description: Find lombok SneakyThrows annotation + recipeList: + - org.openrewrite.java.search.FindTypes: + fullyQualifiedTypeName: lombok.SneakyThrows + """) + buildGradle(""" + plugins { + id("java") + id("org.openrewrite.rewrite") + } + + repositories { + mavenLocal() + mavenCentral() + maven { + url = uri("https://oss.sonatype.org/content/repositories/snapshots") + } + } + + sourceSets { + create("overlapping") { + java.srcDir("src/test/java") + } + } + + rewrite { + activeRecipe("org.openrewrite.test.FindSneaky") + } + + dependencies { + testImplementation("org.projectlombok:lombok:latest.release") + } + """) + sourceSet("test") { + java(""" + package com.foo; + + import lombok.SneakyThrows; + + public class ATest { + + @SneakyThrows + public void fail() { + } + } + """) + } + } + + val result = runGradle(buildRoot, "rewriteRun") + val rewriteRunResult = result.task(":rewriteRun")!! + assertThat(rewriteRunResult.outcome).isEqualTo(TaskOutcome.SUCCESS) + val javaFile = buildRoot.resolve("src/test/java/com/foo/ATest.java") + assertThat(javaFile.readText()) + //language=java + .isEqualTo(""" + package com.foo; + + import lombok.SneakyThrows; + + public class ATest { + + @/*~~>*/SneakyThrows + public void fail() { + } + } + """.trimIndent() + ) + } } From 903faa813c8061f2ac97f72b430f22ccf0e42122 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Sep 2023 17:26:44 +0100 Subject: [PATCH 03/20] chore(ci): bump actions/checkout from 3.6.0 to 4 (#229) * chore(ci): bump actions/checkout from 3.6.0 to 4.0.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3.6.0...v4.0.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Apply suggestions from code review --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Tim te Beek --- .github/workflows/ci.yml | 2 +- .github/workflows/integration-tests.yml | 4 ++-- .github/workflows/publish.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 83d0bfede..234b3d021 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.6.0 + - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: actions/setup-java@v3 diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 5d53aaeed..323cefe4e 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -20,11 +20,11 @@ jobs: name: itest-${{ matrix.java }} steps: - name: checkout-openrewrite/spring-petclinic-migration - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4 with: repository: openrewrite/spring-petclinic-migration - name: setup-plugin-checkout-source - uses: actions/checkout@v3.6.0 + uses: actions/checkout@v4 with: path: rewrite-gradle-plugin - name: setup-plugin-setup-java-11 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 72f71d683..5c243aedb 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -16,7 +16,7 @@ jobs: release: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.6.0 + - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: actions/setup-java@v3 From ce73e203a0be839191635063b4f4e15fba69fc34 Mon Sep 17 00:00:00 2001 From: Knut Wannheden Date: Fri, 22 Sep 2023 23:33:10 +0200 Subject: [PATCH 04/20] Makes sure `.kt` sources are contained in `listSources()` (#225) --- .../org/openrewrite/gradle/isolated/DefaultProjectParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java index fd1ee6f1d..8afe696f9 100644 --- a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java +++ b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java @@ -273,7 +273,7 @@ public Collection listSources() { JavaPluginConvention javaConvention = project.getConvention().findPlugin(JavaPluginConvention.class); if (javaConvention != null) { for (SourceSet sourceSet : javaConvention.getSourceSets()) { - sourceSet.getAllJava().getFiles().stream() + sourceSet.getAllSource().getFiles().stream() .filter(it -> it.isFile() && (it.getName().endsWith(".java") || it.getName().endsWith(".kt"))) .map(File::toPath) .map(Path::toAbsolutePath) From 2553b5485bb82a7fd03a427902e85527c177f6ef Mon Sep 17 00:00:00 2001 From: Sam Snyder Date: Fri, 22 Sep 2023 17:26:43 -0700 Subject: [PATCH 05/20] Fix #231 non-source code files in subprojects parsed multiple times with incorrect paths --- .../gradle/isolated/DefaultProjectParser.java | 25 +++++++++++-------- .../org/openrewrite/gradle/RewriteRunTest.kt | 21 +++++++++++++--- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java index 8afe696f9..0442d6566 100644 --- a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java +++ b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java @@ -268,7 +268,7 @@ private static StringBuilder repeat(int repeat) { public Collection listSources() { // Use a sorted collection so that gradle input detection isn't thrown off by ordering - Set result = new TreeSet<>(omniParser(emptySet()).acceptedPaths(project.getProjectDir().toPath())); + Set result = new TreeSet<>(omniParser(emptySet()).build().acceptedPaths(baseDir, project.getProjectDir().toPath())); //noinspection deprecation JavaPluginConvention javaConvention = project.getConvention().findPlugin(JavaPluginConvention.class); if (javaConvention != null) { @@ -292,6 +292,7 @@ public void dryRun(Path reportPath, boolean dumpGcActivity, Consumer heapMetrics.bindTo(meterRegistry); new JvmMemoryMetrics().bindTo(meterRegistry); + //noinspection deprecation File rewriteBuildDir = new File(project.getBuildDir(), "/rewrite"); if (rewriteBuildDir.exists() || rewriteBuildDir.mkdirs()) { File rewriteGcLog = new File(rewriteBuildDir, "rewrite-gc.csv"); @@ -715,6 +716,7 @@ public Stream parse(Project subproject, Set alreadyParsed, Exe .map(Supplier::get) .flatMap(jp -> jp.parse(javaPaths, baseDir, ctx)) .map(cu -> { + //noinspection deprecation if (isExcluded(exclusions, cu.getSourcePath()) || cu.getSourcePath().startsWith(baseDir.relativize(subproject.getBuildDir().toPath()))) { return null; @@ -804,12 +806,13 @@ public Stream parse(Project subproject, Set alreadyParsed, Exe for (File resourcesDir : sourceSet.getResources().getSourceDirectories()) { if (resourcesDir.exists()) { - OmniParser omniParser = omniParser(alreadyParsed); - List accepted = omniParser.acceptedPaths(resourcesDir.toPath()); + OmniParser omniParser = omniParser(alreadyParsed).build(); + List accepted = omniParser.acceptedPaths(baseDir, resourcesDir.toPath()); sourceSetSourceFiles = Stream.concat( sourceSetSourceFiles, - omniParser.parse(accepted, resourcesDir.toPath(), new InMemoryExecutionContext()) + omniParser.parse(accepted, baseDir, new InMemoryExecutionContext()) ); + alreadyParsed.addAll(accepted); sourceSetSize += accepted.size(); } } @@ -936,13 +939,14 @@ private SourceFileStream parseGradleFiles( protected SourceFileStream parseNonProjectResources(Project subproject, Set alreadyParsed, ExecutionContext ctx, List projectProvenance, Stream sourceFiles) { //Collect any additional yaml/properties/xml files that are NOT already in a source set. - OmniParser omniParser = omniParser(alreadyParsed); - List accepted = omniParser.acceptedPaths(subproject.getProjectDir().toPath()); - return SourceFileStream.build("", s -> { - }).concat(omniParser.parse(accepted, subproject.getProjectDir().toPath(), ctx), accepted.size()); + OmniParser omniParser = omniParser(alreadyParsed) + .build(); + List accepted = omniParser.acceptedPaths(baseDir, subproject.getProjectDir().toPath()); + return SourceFileStream.build("", s -> {}) + .concat(omniParser.parse(accepted, baseDir, ctx), accepted.size()); } - private OmniParser omniParser(Set alreadyParsed) { + private OmniParser.Builder omniParser(Set alreadyParsed) { return OmniParser.builder( OmniParser.RESOURCE_PARSERS, PlainTextParser.builder() @@ -952,8 +956,7 @@ private OmniParser omniParser(Set alreadyParsed) { ) .exclusionMatchers(pathMatchers(baseDir, mergeExclusions(project, baseDir, extension))) .exclusions(alreadyParsed) - .sizeThresholdMb(extension.getSizeThresholdMb()) - .build(); + .sizeThresholdMb(extension.getSizeThresholdMb()); } private static Collection mergeExclusions(Project project, Path baseDir, RewriteExtension extension) { diff --git a/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteRunTest.kt b/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteRunTest.kt index 41cd37646..fd3052a85 100644 --- a/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteRunTest.kt +++ b/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteRunTest.kt @@ -156,12 +156,12 @@ class RewriteRunTest : RewritePluginTest { } @Test - fun `rewriteRun applies built-in AutoFormat to a multi-project build`( + fun `rewriteRun applies recipe to a multi-project build`( @TempDir projectDir: File ) { val bTestClassExpected = """ package com.foo; - + import org.junit.Test; public class BTestClass { @@ -171,6 +171,15 @@ class RewriteRunTest : RewritePluginTest { } """.trimIndent() gradleProject(projectDir) { + rewriteYaml(""" + type: specs.openrewrite.org/v1beta/recipe + name: org.openrewrite.FormatAndAddProperty + recipeList: + - org.openrewrite.java.format.AutoFormat + - org.openrewrite.properties.ChangePropertyKey: + oldPropertyKey: foo + newPropertyKey: bar + """) buildGradle(""" plugins { id("org.openrewrite.rewrite") @@ -178,7 +187,7 @@ class RewriteRunTest : RewritePluginTest { } rewrite { - activeRecipe("org.openrewrite.java.format.AutoFormat") + activeRecipe("org.openrewrite.FormatAndAddProperty") exclusion("**/BTestClass.java") } @@ -216,6 +225,7 @@ class RewriteRunTest : RewritePluginTest { public void passes() { } } """) + propertiesFile("test.properties", "foo=baz\n") } } subproject("b") { @@ -231,7 +241,7 @@ class RewriteRunTest : RewritePluginTest { //language=java val aTestClassExpected = """ package com.foo; - + import org.junit.Test; public class ATestClass { @@ -245,6 +255,9 @@ class RewriteRunTest : RewritePluginTest { assertThat(aTestClassFile.readText()).isEqualTo(aTestClassExpected) val bTestClassFile = File(projectDir, "b/src/test/java/com/foo/BTestClass.java") assertThat(bTestClassFile.readText()).isEqualTo(bTestClassExpected) + + val propertiesFile = File(projectDir, "a/src/test/resources/test.properties") + assertThat(propertiesFile.readText()).isEqualTo("bar=baz\n") } @Suppress("ClassInitializerMayBeStatic", "StatementWithEmptyBody", "ConstantConditions") From da10e291edc2c4b0edc3a0ebad8e5e1ff7be7ddf Mon Sep 17 00:00:00 2001 From: Sam Snyder Date: Fri, 22 Sep 2023 17:29:07 -0700 Subject: [PATCH 06/20] Polish --- .../gradle/isolated/DefaultProjectParser.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java index 0442d6566..2656bd9cf 100644 --- a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java +++ b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java @@ -268,7 +268,7 @@ private static StringBuilder repeat(int repeat) { public Collection listSources() { // Use a sorted collection so that gradle input detection isn't thrown off by ordering - Set result = new TreeSet<>(omniParser(emptySet()).build().acceptedPaths(baseDir, project.getProjectDir().toPath())); + Set result = new TreeSet<>(omniParser(emptySet()).acceptedPaths(baseDir, project.getProjectDir().toPath())); //noinspection deprecation JavaPluginConvention javaConvention = project.getConvention().findPlugin(JavaPluginConvention.class); if (javaConvention != null) { @@ -806,7 +806,7 @@ public Stream parse(Project subproject, Set alreadyParsed, Exe for (File resourcesDir : sourceSet.getResources().getSourceDirectories()) { if (resourcesDir.exists()) { - OmniParser omniParser = omniParser(alreadyParsed).build(); + OmniParser omniParser = omniParser(alreadyParsed); List accepted = omniParser.acceptedPaths(baseDir, resourcesDir.toPath()); sourceSetSourceFiles = Stream.concat( sourceSetSourceFiles, @@ -939,14 +939,13 @@ private SourceFileStream parseGradleFiles( protected SourceFileStream parseNonProjectResources(Project subproject, Set alreadyParsed, ExecutionContext ctx, List projectProvenance, Stream sourceFiles) { //Collect any additional yaml/properties/xml files that are NOT already in a source set. - OmniParser omniParser = omniParser(alreadyParsed) - .build(); + OmniParser omniParser = omniParser(alreadyParsed); List accepted = omniParser.acceptedPaths(baseDir, subproject.getProjectDir().toPath()); return SourceFileStream.build("", s -> {}) .concat(omniParser.parse(accepted, baseDir, ctx), accepted.size()); } - private OmniParser.Builder omniParser(Set alreadyParsed) { + private OmniParser omniParser(Set alreadyParsed) { return OmniParser.builder( OmniParser.RESOURCE_PARSERS, PlainTextParser.builder() @@ -956,7 +955,8 @@ private OmniParser.Builder omniParser(Set alreadyParsed) { ) .exclusionMatchers(pathMatchers(baseDir, mergeExclusions(project, baseDir, extension))) .exclusions(alreadyParsed) - .sizeThresholdMb(extension.getSizeThresholdMb()); + .sizeThresholdMb(extension.getSizeThresholdMb()) + .build(); } private static Collection mergeExclusions(Project project, Path baseDir, RewriteExtension extension) { From 3975972d2a7b682d59d6f70e742d6e4feaa24ba4 Mon Sep 17 00:00:00 2001 From: Jonathan Schneider Date: Sun, 24 Sep 2023 02:18:34 -0400 Subject: [PATCH 07/20] RESOURCE_PARSERS -> defaultResourceParsers() --- .../org/openrewrite/gradle/isolated/DefaultProjectParser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java index 2656bd9cf..bc8d72ce9 100644 --- a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java +++ b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java @@ -947,7 +947,7 @@ protected SourceFileStream parseNonProjectResources(Project subproject, Set alreadyParsed) { return OmniParser.builder( - OmniParser.RESOURCE_PARSERS, + OmniParser.defaultResourceParsers(), PlainTextParser.builder() .plainTextMasks(baseDir, extension.getPlainTextMasks()) .build(), From 01707ca029b8d1f156a492d2cbc4ac7d2ba46466 Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Mon, 25 Sep 2023 11:38:38 +0200 Subject: [PATCH 08/20] Jenkinsfiles now parsed as Groovy --- .../java/org/openrewrite/gradle/DefaultRewriteExtension.java | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin/src/main/java/org/openrewrite/gradle/DefaultRewriteExtension.java b/plugin/src/main/java/org/openrewrite/gradle/DefaultRewriteExtension.java index 2208aa03c..5f31d93b4 100644 --- a/plugin/src/main/java/org/openrewrite/gradle/DefaultRewriteExtension.java +++ b/plugin/src/main/java/org/openrewrite/gradle/DefaultRewriteExtension.java @@ -343,7 +343,6 @@ public List getPlainTextMasks() { "**.gitattributes", "**.gitignore", "**.java-version", - "**Jenkinsfile", "**.jsp", "**.ksh", "**.kts", From e34bcf0b80ddd132eaae4218a5bd6bd93be7a516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20Schn=C3=A9ider?= Date: Tue, 26 Sep 2023 18:47:13 +0000 Subject: [PATCH 09/20] refactor: Spaces Use this link to re-run the recipe: https://app.moderne.io/recipes/org.openrewrite.java.format.Spaces?organizationId=T3BlblJld3JpdGU%3D Co-authored-by: Moderne --- .../gradle/AbstractRewriteTask.java | 4 +- .../gradle/DefaultRewriteExtension.java | 24 +++--- .../gradle/DelegatingProjectParser.java | 2 +- .../gradle/SanitizedMarkerPrinter.java | 4 +- .../org/openrewrite/gradle/TimeUtils.java | 18 ++--- .../openrewrite/gradle/GradleProjectSpec.kt | 62 +++++++------- .../openrewrite/gradle/RewriteDiscoverTest.kt | 2 +- .../openrewrite/gradle/RewriteDryRunTest.kt | 12 +-- .../openrewrite/gradle/RewritePluginTest.kt | 2 +- .../org/openrewrite/gradle/RewriteRunTest.kt | 80 +++++++++---------- scripts/spring-petclinic-test.init.gradle | 38 ++++----- 11 files changed, 124 insertions(+), 124 deletions(-) diff --git a/plugin/src/main/java/org/openrewrite/gradle/AbstractRewriteTask.java b/plugin/src/main/java/org/openrewrite/gradle/AbstractRewriteTask.java index 8ac585073..ddecf1501 100755 --- a/plugin/src/main/java/org/openrewrite/gradle/AbstractRewriteTask.java +++ b/plugin/src/main/java/org/openrewrite/gradle/AbstractRewriteTask.java @@ -57,8 +57,8 @@ public boolean isDumpGcActivity() { @Internal protected T getProjectParser() { - if(gpp == null) { - if(extension == null) { + if (gpp == null) { + if (extension == null) { throw new IllegalArgumentException("Must configure extension"); } if (resolveDependenciesTask == null) { diff --git a/plugin/src/main/java/org/openrewrite/gradle/DefaultRewriteExtension.java b/plugin/src/main/java/org/openrewrite/gradle/DefaultRewriteExtension.java index 5f31d93b4..a8856d872 100644 --- a/plugin/src/main/java/org/openrewrite/gradle/DefaultRewriteExtension.java +++ b/plugin/src/main/java/org/openrewrite/gradle/DefaultRewriteExtension.java @@ -38,7 +38,7 @@ public class DefaultRewriteExtension implements RewriteExtension { private File configFile; private Provider checkstyleConfigProvider; - private Provider> checkstylePropertiesProvider; + private Provider> checkstylePropertiesProvider; private File checkstyleConfigFile; private String metricsUri = magicalMetricsLogString; private boolean enableExperimentalGradleBuildScriptParsing = true; @@ -98,10 +98,10 @@ public void setCheckstyleConfigFile(File configFile) { @Override @Nullable public File getCheckstyleConfigFile() { - if(checkstyleConfigFile == null && checkstyleConfigProvider != null) { + if (checkstyleConfigFile == null && checkstyleConfigProvider != null) { try { return checkstyleConfigProvider.get(); - } catch(Exception e) { + } catch (Exception e) { return null; } } @@ -110,7 +110,7 @@ public File getCheckstyleConfigFile() { @Override public Map getCheckstyleProperties() { - if(checkstyleConfigProvider == null) { + if (checkstyleConfigProvider == null) { return emptyMap(); } return checkstylePropertiesProvider.get(); @@ -195,11 +195,11 @@ public List getActiveRecipes() { } private Properties getVersionProps() { - if(versionProps == null) { - try(InputStream is = DefaultRewriteExtension.class.getResourceAsStream("/rewrite/versions.properties")) { + if (versionProps == null) { + try (InputStream is = DefaultRewriteExtension.class.getResourceAsStream("/rewrite/versions.properties")) { versionProps = new Properties(); versionProps.load(is); - } catch(IOException e) { + } catch (IOException e) { throw new RuntimeException(e); } } @@ -211,7 +211,7 @@ private Properties getVersionProps() { */ @Override public String getRewriteVersion() { - if(rewriteVersion == null) { + if (rewriteVersion == null) { return getVersionProps().getProperty("org.openrewrite:rewrite-core"); } return rewriteVersion; @@ -219,7 +219,7 @@ public String getRewriteVersion() { @Override public String getRewritePolyglotVersion() { - if(rewriteVersion == null) { + if (rewriteVersion == null) { return getVersionProps().getProperty("org.openrewrite:rewrite-polyglot"); } return rewriteVersion; @@ -228,7 +228,7 @@ public String getRewritePolyglotVersion() { private String rewriteGradleModelVersion; @Override public String getRewriteGradleModelVersion() { - if(rewriteGradleModelVersion == null) { + if (rewriteGradleModelVersion == null) { rewriteGradleModelVersion = getVersionProps().getProperty("org.openrewrite.gradle.tooling:model"); } return rewriteGradleModelVersion; @@ -237,7 +237,7 @@ public String getRewriteGradleModelVersion() { private String rewriteKotlinVersion; @Override public String getRewriteKotlinVersion() { - if(rewriteKotlinVersion == null) { + if (rewriteKotlinVersion == null) { rewriteKotlinVersion = getVersionProps().getProperty("org.openrewrite:rewrite-kotlin"); } return rewriteKotlinVersion; @@ -384,7 +384,7 @@ public String getJacksonModuleKotlinVersion() { @Override public boolean getThrowOnParseFailures() { - if(project.getProperties().containsKey("rewrite.throwOnParseFailures")) { + if (project.getProperties().containsKey("rewrite.throwOnParseFailures")) { return true; } return throwOnParseFailures; diff --git a/plugin/src/main/java/org/openrewrite/gradle/DelegatingProjectParser.java b/plugin/src/main/java/org/openrewrite/gradle/DelegatingProjectParser.java index 77ae7fac4..2b33d8726 100755 --- a/plugin/src/main/java/org/openrewrite/gradle/DelegatingProjectParser.java +++ b/plugin/src/main/java/org/openrewrite/gradle/DelegatingProjectParser.java @@ -54,7 +54,7 @@ public DelegatingProjectParser(Project project, RewriteExtension extension, Set< .getResource("/org/openrewrite/gradle/isolated/DefaultProjectParser.class") .toString()); classpathUrls.add(currentJar); - if(rewriteClassLoader == null || !classpathUrls.equals(rewriteClasspath)) { + if (rewriteClassLoader == null || !classpathUrls.equals(rewriteClasspath)) { if (rewriteClassLoader != null) { rewriteClassLoader.close(); } diff --git a/plugin/src/main/java/org/openrewrite/gradle/SanitizedMarkerPrinter.java b/plugin/src/main/java/org/openrewrite/gradle/SanitizedMarkerPrinter.java index 0d89b75af..131c01f41 100644 --- a/plugin/src/main/java/org/openrewrite/gradle/SanitizedMarkerPrinter.java +++ b/plugin/src/main/java/org/openrewrite/gradle/SanitizedMarkerPrinter.java @@ -29,7 +29,7 @@ public class SanitizedMarkerPrinter implements PrintOutputCapture.MarkerPrinter { @Override public String beforeSyntax(Marker marker, Cursor cursor, UnaryOperator commentWrapper) { - if(marker instanceof SearchResult) { + if (marker instanceof SearchResult) { return DEFAULT.beforeSyntax(marker, cursor, commentWrapper); } return ""; @@ -37,7 +37,7 @@ public String beforeSyntax(Marker marker, Cursor cursor, UnaryOperator c @Override public String afterSyntax(Marker marker, Cursor cursor, UnaryOperator commentWrapper) { - if(marker instanceof SearchResult) { + if (marker instanceof SearchResult) { return DEFAULT.afterSyntax(marker, cursor, commentWrapper); } return ""; diff --git a/plugin/src/main/java/org/openrewrite/gradle/TimeUtils.java b/plugin/src/main/java/org/openrewrite/gradle/TimeUtils.java index 063101748..271c5194b 100644 --- a/plugin/src/main/java/org/openrewrite/gradle/TimeUtils.java +++ b/plugin/src/main/java/org/openrewrite/gradle/TimeUtils.java @@ -27,39 +27,39 @@ public static String prettyPrint(Duration duration) { StringBuilder result = new StringBuilder(); long days = duration.getSeconds() / SECONDS_PER_DAY; boolean startedPrinting = false; - if(days > 0) { + if (days > 0) { startedPrinting = true; result.append(days); result.append(" day"); - if(days != 1) { + if (days != 1) { result.append("s"); } result.append(" "); } - long hours = duration.toHours() % 24; - if(startedPrinting || hours > 0) { + long hours = duration.toHours() % 24; + if (startedPrinting || hours > 0) { startedPrinting = true; result.append(hours); result.append(" hour"); - if(hours != 1) { + if (hours != 1) { result.append("s"); } result.append(" "); } long minutes = (duration.getSeconds() / SECONDS_PER_MINUTE) % MINUTES_PER_HOUR; - if(startedPrinting || minutes > 0) { + if (startedPrinting || minutes > 0) { result.append(minutes); result.append(" minute"); - if(minutes != 1) { + if (minutes != 1) { result.append("s"); } result.append(" "); } long seconds = duration.getSeconds() % SECONDS_PER_MINUTE; - if(startedPrinting || seconds > 0) { + if (startedPrinting || seconds > 0) { result.append(seconds); result.append(" second"); if (seconds != 1) { @@ -71,7 +71,7 @@ public static String prettyPrint(Duration duration) { long millis = duration.getNano() / 1000_000; result.append(millis); result.append(" millisecond"); - if(millis != 1) { + if (millis != 1) { result.append("s"); } diff --git a/plugin/src/main/kotlin/org/openrewrite/gradle/GradleProjectSpec.kt b/plugin/src/main/kotlin/org/openrewrite/gradle/GradleProjectSpec.kt index a0acd9647..6b147d45e 100644 --- a/plugin/src/main/kotlin/org/openrewrite/gradle/GradleProjectSpec.kt +++ b/plugin/src/main/kotlin/org/openrewrite/gradle/GradleProjectSpec.kt @@ -77,51 +77,51 @@ class GradleProjectSpec( fun build(): GradleProjectSpec { dir.mkdirs() - if(settingsGradle != null) { + if (settingsGradle != null) { File(dir, "settings.gradle").writeText(settingsGradle!!) } - if(groovyBuildScript != null) { + if (groovyBuildScript != null) { File(dir, "build.gradle").writeText(groovyBuildScript!!) } - if(rewriteYaml != null) { + if (rewriteYaml != null) { File(dir, "rewrite.yml").writeText(rewriteYaml!!) } - if(checkstyleXml != null) { - File(dir, "config/checkstyle/checkstyle.xml").apply { + if (checkstyleXml != null) { + File(dir, "config/checkstyle/checkstyle.xml").apply{ parentFile.mkdirs() writeText(checkstyleXml!!) } } - for(props in propertiesFiles.entries) { - File(dir, props.key).apply { + for (props in propertiesFiles.entries) { + File(dir, props.key).apply{ parentFile.mkdirs() writeText(props.value) } } - for(text in textFiles.entries) { - File(dir, text.key).apply { + for (text in textFiles.entries) { + File(dir, text.key).apply{ parentFile.mkdirs() writeText(text.value) } } - for(sourceSet in sourceSets) { + for (sourceSet in sourceSets) { sourceSet.build(File(dir, "src")) } val settings = File(dir, "settings.gradle") val settingsText = "rootProject.name = \"${dir.name}\"\n" - if(subprojects.isEmpty()) { + if (subprojects.isEmpty()) { settings.writeText("rootProject.name = \"${dir.name}\"\n") } else { - val subprojectsDeclarations = subprojects.joinToString("\n") { subproject -> "include('${subproject.dir.name}')" } + val subprojectsDeclarations = subprojects.joinToString("\n") { subproject -> "include('${subproject.dir.name}')" } settings.writeText(settingsText + subprojectsDeclarations) - for(subproject in subprojects) { + for (subproject in subprojects) { subproject.build() } } @@ -161,8 +161,8 @@ class GradleSourceSetSpec( @Suppress("RegExpSimplifiable") fun build(dir: File): GradleSourceSetSpec { dir.mkdirs() - for(javaSource in javaSources) { - val peckage = if(javaSource.startsWith("package")) { + for (javaSource in javaSources) { + val peckage = if (javaSource.startsWith("package")) { "package\\s+([a-zA-Z0-9.]+);".toRegex(RegexOption.MULTILINE) .find(javaSource)!! .groupValues[1] @@ -170,18 +170,18 @@ class GradleSourceSetSpec( "" }.replace(".", "/") val clazz = ".*(class|interface|enum)\\s+([a-zA-Z0-9-_]+)".toRegex(RegexOption.MULTILINE).find(javaSource)!!.groupValues[2] - val path = if(peckage.isEmpty()) { + val path = if (peckage.isEmpty()) { "$name/java/$clazz.java" } else { "$name/java/$peckage/$clazz.java" } - File(dir, path).apply { + File(dir, path).apply{ parentFile.mkdirs() writeText(javaSource) } } - for(kotlinSource in kotlinSources) { - val peckage = if(kotlinSource.startsWith("package")) { + for (kotlinSource in kotlinSources) { + val peckage = if (kotlinSource.startsWith("package")) { "package\\s+([a-zA-Z0-9.]+)".toRegex(RegexOption.MULTILINE) .find(kotlinSource)!! .groupValues[1] @@ -189,18 +189,18 @@ class GradleSourceSetSpec( "" }.replace(".", "/") val clazz = ".*(class|interface|enum)\\s+([a-zA-Z0-9-_]+)".toRegex(RegexOption.MULTILINE).find(kotlinSource)!!.groupValues[2] - val path = if(peckage.isEmpty()) { + val path = if (peckage.isEmpty()) { "$name/kotlin/$clazz.kt" } else { "$name/kotlin/$peckage/$clazz.kt" } - File(dir, path).apply { + File(dir, path).apply{ parentFile.mkdirs() writeText(kotlinSource) } } - for(groovySource in groovyClasses) { - val peckage = if(groovySource.startsWith("package")) { + for (groovySource in groovyClasses) { + val peckage = if (groovySource.startsWith("package")) { "package\\s+([a-zA-Z0-9.]+);?".toRegex(RegexOption.MULTILINE) .find(groovySource)!! .groupValues[1] @@ -208,27 +208,27 @@ class GradleSourceSetSpec( "" }.replace(".", "/") val clazz = ".*(class|interface|enum)\\s+([a-zA-Z0-9-_]+)".toRegex(RegexOption.MULTILINE).find(groovySource)!!.groupValues[2] - val path = if(peckage.isEmpty()) { + val path = if (peckage.isEmpty()) { "$name/groovy/$clazz.groovy" } else { "$name/groovy/$peckage/$clazz.groovy" } - File(dir, path).apply { + File(dir, path).apply{ parentFile.mkdirs() writeText(groovySource) } } - if(propertiesFiles.isNotEmpty()) { - for(props in propertiesFiles.entries) { - File(dir, "$name/resources/${props.key}").apply { + if (propertiesFiles.isNotEmpty()) { + for (props in propertiesFiles.entries) { + File(dir, "$name/resources/${props.key}").apply{ parentFile.mkdirs() writeText(props.value) } } } - if(yamlFiles.isNotEmpty()) { - for(yaml in yamlFiles.entries) { - File(dir, "$name/resources/${yaml.key}").apply { + if (yamlFiles.isNotEmpty()) { + for (yaml in yamlFiles.entries) { + File(dir, "$name/resources/${yaml.key}").apply{ parentFile.mkdirs() writeText(yaml.value) } diff --git a/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteDiscoverTest.kt b/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteDiscoverTest.kt index f2bd14a59..0e17b2d89 100644 --- a/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteDiscoverTest.kt +++ b/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteDiscoverTest.kt @@ -28,7 +28,7 @@ class RewriteDiscoverTest : RewritePluginTest { fun `rewriteDiscover prints recipes from external dependencies`( @TempDir projectDir: File ) { - gradleProject(projectDir) { + gradleProject(projectDir) { buildGradle(""" plugins { id("java") diff --git a/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteDryRunTest.kt b/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteDryRunTest.kt index 7a2d37da7..254e17772 100644 --- a/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteDryRunTest.kt +++ b/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteDryRunTest.kt @@ -35,7 +35,7 @@ class RewriteDryRunTest : RewritePluginTest { }public static void main(String[] args) { sayGoodbye(); } } """.trimIndent() - gradleProject(projectDir) { + gradleProject(projectDir) { rewriteYaml(""" type: specs.openrewrite.org/v1beta/recipe name: org.openrewrite.gradle.SayHello @@ -65,7 +65,7 @@ class RewriteDryRunTest : RewritePluginTest { activeRecipe("org.openrewrite.gradle.SayHello", "org.openrewrite.java.format.AutoFormat") } """) - sourceSet("main") { + sourceSet("main") { java(helloWorld) } } @@ -82,7 +82,7 @@ class RewriteDryRunTest : RewritePluginTest { fun `A recipe with optional configuration can be activated directly`( @TempDir projectDir: File ) { - gradleProject(projectDir) { + gradleProject(projectDir) { buildGradle(""" plugins { id("java") @@ -97,7 +97,7 @@ class RewriteDryRunTest : RewritePluginTest { } } """) - sourceSet("main") { + sourceSet("main") { java(""" package org.openrewrite.before; @@ -127,7 +127,7 @@ class RewriteDryRunTest : RewritePluginTest { @DisabledIf("lessThanGradle6_1") @Test fun testMultiplatform(@TempDir projectDir: File) { - gradleProject(projectDir) { + gradleProject(projectDir) { buildGradle(""" plugins { id("java") @@ -177,7 +177,7 @@ class RewriteDryRunTest : RewritePluginTest { } rootProject.name = "example" """) - sourceSet("commonMain") { + sourceSet("commonMain") { kotlin(""" class HelloWorld { fun sayHello() { diff --git a/plugin/src/test/kotlin/org/openrewrite/gradle/RewritePluginTest.kt b/plugin/src/test/kotlin/org/openrewrite/gradle/RewritePluginTest.kt index 7ff56fb66..d2b7f9e9b 100644 --- a/plugin/src/test/kotlin/org/openrewrite/gradle/RewritePluginTest.kt +++ b/plugin/src/test/kotlin/org/openrewrite/gradle/RewritePluginTest.kt @@ -29,7 +29,7 @@ interface RewritePluginTest { GradleRunner.create() .withDebug(ManagementFactory.getRuntimeMXBean().inputArguments.toString().indexOf("-agentlib:jdwp") > 0) .withProjectDir(testDir) - .apply { + .apply{ if (gradleVersion != null) { withGradleVersion(gradleVersion) } diff --git a/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteRunTest.kt b/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteRunTest.kt index fd3052a85..d77f32793 100644 --- a/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteRunTest.kt +++ b/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteRunTest.kt @@ -40,7 +40,7 @@ class RewriteRunTest : RewritePluginTest { // Gradle provides no control over how it arbitrarily orders its classpath // So even if isolation isn't working at all, this could pass if it happens to put the rewrite's required version // of jackson first on the classpath. - gradleProject(projectDir) { + gradleProject(projectDir) { buildGradle(""" buildscript { repositories { @@ -69,7 +69,7 @@ class RewriteRunTest : RewritePluginTest { activeRecipe("org.openrewrite.java.format.AutoFormat") } """) - sourceSet("test") { + sourceSet("test") { java(""" package com.foo; @@ -89,7 +89,7 @@ class RewriteRunTest : RewritePluginTest { fun `rewriteRun will alter the source file according to the provided active recipe`( @TempDir projectDir: File ) { - gradleProject(projectDir) { + gradleProject(projectDir) { rewriteYaml(""" type: specs.openrewrite.org/v1beta/recipe name: org.openrewrite.gradle.SayHello @@ -119,7 +119,7 @@ class RewriteRunTest : RewritePluginTest { activeRecipe("org.openrewrite.gradle.SayHello", "org.openrewrite.java.format.AutoFormat") } """) - sourceSet("main") { + sourceSet("main") { java(""" package org.openrewrite.before; @@ -170,7 +170,7 @@ class RewriteRunTest : RewritePluginTest { public void passes() { } } """.trimIndent() - gradleProject(projectDir) { + gradleProject(projectDir) { rewriteYaml(""" type: specs.openrewrite.org/v1beta/recipe name: org.openrewrite.FormatAndAddProperty @@ -212,8 +212,8 @@ class RewriteRunTest : RewritePluginTest { } } """) - subproject("a") { - sourceSet("test") { + subproject("a") { + sourceSet("test") { java(""" package com.foo; @@ -228,8 +228,8 @@ class RewriteRunTest : RewritePluginTest { propertiesFile("test.properties", "foo=baz\n") } } - subproject("b") { - sourceSet("test") { + subproject("b") { + sourceSet("test") { java(bTestClassExpected) } } @@ -265,7 +265,7 @@ class RewriteRunTest : RewritePluginTest { fun `Checkstyle configuration is applied as a style`( @TempDir projectDir: File ) { - gradleProject(projectDir) { + gradleProject(projectDir) { checkstyleXml(""" Date: Thu, 28 Sep 2023 19:26:56 -0700 Subject: [PATCH 10/20] Handle partially-overlapping source sets better. Parse each directory exactly once. --- .../org/openrewrite/gradle/RewritePlugin.java | 2 +- .../gradle/isolated/DefaultProjectParser.java | 50 ++++++----- .../org/openrewrite/gradle/RewriteRunTest.kt | 88 ++++++++++--------- 3 files changed, 73 insertions(+), 67 deletions(-) diff --git a/plugin/src/main/java/org/openrewrite/gradle/RewritePlugin.java b/plugin/src/main/java/org/openrewrite/gradle/RewritePlugin.java index 1549446dd..16c9534eb 100644 --- a/plugin/src/main/java/org/openrewrite/gradle/RewritePlugin.java +++ b/plugin/src/main/java/org/openrewrite/gradle/RewritePlugin.java @@ -118,7 +118,7 @@ private static void configureProject(Project project, RewriteExtension extension return 2; } })).forEach(sourceSet -> { - for (File file : sourceSet.getAllSource().getSourceDirectories().getFiles()) { + for (File file : sourceSet.getAllJava().getSourceDirectories().getFiles()) { if (!sourceDirs.add(file.getAbsolutePath())) { Task compileTask = project.getTasks().getByPath(sourceSet.getCompileJavaTaskName()); compileTask.setEnabled(false); diff --git a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java index bc8d72ce9..5f2819049 100644 --- a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java +++ b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java @@ -85,6 +85,7 @@ import java.util.function.Consumer; import java.util.function.Supplier; import java.util.function.UnaryOperator; +import java.util.stream.Collectors; import java.util.stream.Stream; import static java.util.Collections.*; @@ -653,15 +654,7 @@ public Stream parse(Project subproject, Set alreadyParsed, Exe } Set sourceDirs = new HashSet<>(); - sourceSetLoop: for (SourceSet sourceSet : sourceSets) { - // Detect SourceSets which overlap other sourceSets and disable the compilation task of the overlapping - // source set. Skip parsing directories already covered by another source set. - for (File file : sourceSet.getAllSource().getSourceDirectories().getFiles()) { - if (!sourceDirs.add(file.getAbsolutePath())) { - continue sourceSetLoop; - } - } Stream sourceSetSourceFiles = Stream.of(); int sourceSetSize = 0; @@ -672,11 +665,24 @@ public Stream parse(Project subproject, Set alreadyParsed, Exe javaCompileTask.getSourceCompatibility(), javaCompileTask.getTargetCompatibility()); - List javaPaths = sourceSet.getAllJava().getFiles().stream() - .filter(it -> it.isFile() && it.getName().endsWith(".java")) - .map(File::toPath) + List unparsedSources = sourceSet.getAllSource() + .getSourceDirectories() + .filter(it -> it.exists() && !alreadyParsed.contains(baseDir.relativize(it.toPath()))) + .getFiles() + .stream() + .flatMap(sourceDir -> { + try { + return Files.walk(sourceDir.toPath()); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }) + .filter(Files::isRegularFile) .map(Path::toAbsolutePath) .map(Path::normalize) + .collect(Collectors.toList()); + List javaPaths = unparsedSources.stream() + .filter(it -> it.toString().endsWith(".java")) .collect(toList()); // classpath doesn't include the transitive dependencies of the implementation configuration @@ -731,11 +737,8 @@ public Stream parse(Project subproject, Set alreadyParsed, Exe } if (subproject.getPlugins().hasPlugin("org.jetbrains.kotlin.jvm")) { - List kotlinPaths = sourceSet.getAllSource().getFiles().stream() - .filter(it -> it.isFile() && it.getName().endsWith(".kt")) - .map(File::toPath) - .map(Path::toAbsolutePath) - .map(Path::normalize) + List kotlinPaths = unparsedSources.stream() + .filter(it -> it.toString().endsWith(".kt")) .collect(toList()); if (!kotlinPaths.isEmpty()) { @@ -762,13 +765,9 @@ public Stream parse(Project subproject, Set alreadyParsed, Exe logger.info("Scanned {} Kotlin sources in {}/{}", kotlinPaths.size(), subproject.getPath(), sourceSet.getName()); } } - if (subproject.getPlugins().hasPlugin(GroovyPlugin.class)) { - List groovyPaths = sourceSet.getAllSource().getFiles().stream() - .filter(it -> it.isFile() && it.getName().endsWith(".groovy")) - .map(File::toPath) - .map(Path::toAbsolutePath) - .map(Path::normalize) + List groovyPaths = unparsedSources.stream() + .filter(it -> it.toString().endsWith(".groovy")) .collect(toList()); if (!groovyPaths.isEmpty()) { @@ -805,7 +804,7 @@ public Stream parse(Project subproject, Set alreadyParsed, Exe } for (File resourcesDir : sourceSet.getResources().getSourceDirectories()) { - if (resourcesDir.exists()) { + if (resourcesDir.exists() && !alreadyParsed.contains(baseDir.relativize(resourcesDir.toPath()))) { OmniParser omniParser = omniParser(alreadyParsed); List accepted = omniParser.acceptedPaths(baseDir, resourcesDir.toPath()); sourceSetSourceFiles = Stream.concat( @@ -819,6 +818,11 @@ public Stream parse(Project subproject, Set alreadyParsed, Exe JavaSourceSet sourceSetProvenance = JavaSourceSet.build(sourceSet.getName(), dependencyPaths, javaTypeCache, false); sourceFileStream = sourceFileStream.concat(sourceSetSourceFiles.map(addProvenance(sourceSetProvenance)), sourceSetSize); + // Some source sets get misconfigured to have the same directories as other source sets + // This causes duplicate source files to be parsed, so once a source set has been parsed exclude it from future parsing + for (File file : sourceSet.getAllSource().getSourceDirectories().getFiles()) { + alreadyParsed.add(baseDir.relativize(file.toPath())); + } } SourceFileStream gradleFiles = parseGradleFiles(exclusions, alreadyParsed, ctx); sourceFileStream = sourceFileStream.concat(gradleFiles, gradleFiles.size()); diff --git a/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteRunTest.kt b/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteRunTest.kt index d77f32793..8aee56aaa 100644 --- a/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteRunTest.kt +++ b/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteRunTest.kt @@ -40,7 +40,7 @@ class RewriteRunTest : RewritePluginTest { // Gradle provides no control over how it arbitrarily orders its classpath // So even if isolation isn't working at all, this could pass if it happens to put the rewrite's required version // of jackson first on the classpath. - gradleProject(projectDir) { + gradleProject(projectDir) { buildGradle(""" buildscript { repositories { @@ -69,7 +69,7 @@ class RewriteRunTest : RewritePluginTest { activeRecipe("org.openrewrite.java.format.AutoFormat") } """) - sourceSet("test") { + sourceSet("test") { java(""" package com.foo; @@ -89,7 +89,7 @@ class RewriteRunTest : RewritePluginTest { fun `rewriteRun will alter the source file according to the provided active recipe`( @TempDir projectDir: File ) { - gradleProject(projectDir) { + gradleProject(projectDir) { rewriteYaml(""" type: specs.openrewrite.org/v1beta/recipe name: org.openrewrite.gradle.SayHello @@ -119,7 +119,7 @@ class RewriteRunTest : RewritePluginTest { activeRecipe("org.openrewrite.gradle.SayHello", "org.openrewrite.java.format.AutoFormat") } """) - sourceSet("main") { + sourceSet("main") { java(""" package org.openrewrite.before; @@ -170,7 +170,7 @@ class RewriteRunTest : RewritePluginTest { public void passes() { } } """.trimIndent() - gradleProject(projectDir) { + gradleProject(projectDir) { rewriteYaml(""" type: specs.openrewrite.org/v1beta/recipe name: org.openrewrite.FormatAndAddProperty @@ -212,8 +212,8 @@ class RewriteRunTest : RewritePluginTest { } } """) - subproject("a") { - sourceSet("test") { + subproject("a") { + sourceSet("test") { java(""" package com.foo; @@ -228,8 +228,8 @@ class RewriteRunTest : RewritePluginTest { propertiesFile("test.properties", "foo=baz\n") } } - subproject("b") { - sourceSet("test") { + subproject("b") { + sourceSet("test") { java(bTestClassExpected) } } @@ -265,7 +265,7 @@ class RewriteRunTest : RewritePluginTest { fun `Checkstyle configuration is applied as a style`( @TempDir projectDir: File ) { - gradleProject(projectDir) { + gradleProject(projectDir) { checkstyleXml(""" Date: Fri, 29 Sep 2023 10:09:46 +0200 Subject: [PATCH 11/20] added log message for active styles (#232) --- .../org/openrewrite/gradle/isolated/DefaultProjectParser.java | 1 + 1 file changed, 1 insertion(+) diff --git a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java index 5f2819049..78a34c559 100644 --- a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java +++ b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java @@ -622,6 +622,7 @@ public Stream parse(Project subproject, Set alreadyParsed, Exe logger.lifecycle("Scanning sources in project {}", subproject.getPath()); List styles = getStyles(); + logger.lifecycle("Using active styles {}", styles.stream().map(NamedStyles::getName).collect(toList())); @SuppressWarnings("deprecation") JavaPluginConvention javaConvention = subproject.getConvention().findPlugin(JavaPluginConvention.class); List sourceSets; From 6c9033e14058ebccd0613cbdd8299cbc76a7eec1 Mon Sep 17 00:00:00 2001 From: Sam Snyder Date: Fri, 29 Sep 2023 12:26:20 -0700 Subject: [PATCH 12/20] Further efforts to parse every source exactly once --- .../gradle/isolated/DefaultProjectParser.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java index 78a34c559..5c493c5f3 100644 --- a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java +++ b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java @@ -275,7 +275,6 @@ public Collection listSources() { if (javaConvention != null) { for (SourceSet sourceSet : javaConvention.getSourceSets()) { sourceSet.getAllSource().getFiles().stream() - .filter(it -> it.isFile() && (it.getName().endsWith(".java") || it.getName().endsWith(".kt"))) .map(File::toPath) .map(Path::toAbsolutePath) .map(Path::normalize) @@ -668,7 +667,7 @@ public Stream parse(Project subproject, Set alreadyParsed, Exe List unparsedSources = sourceSet.getAllSource() .getSourceDirectories() - .filter(it -> it.exists() && !alreadyParsed.contains(baseDir.relativize(it.toPath()))) + .filter(it -> it.exists() && !alreadyParsed.contains(it.toPath())) .getFiles() .stream() .flatMap(sourceDir -> { @@ -681,9 +680,10 @@ public Stream parse(Project subproject, Set alreadyParsed, Exe .filter(Files::isRegularFile) .map(Path::toAbsolutePath) .map(Path::normalize) + .distinct() .collect(Collectors.toList()); List javaPaths = unparsedSources.stream() - .filter(it -> it.toString().endsWith(".java")) + .filter(it -> it.toString().endsWith(".java") && !alreadyParsed.contains(it)) .collect(toList()); // classpath doesn't include the transitive dependencies of the implementation configuration @@ -805,7 +805,7 @@ public Stream parse(Project subproject, Set alreadyParsed, Exe } for (File resourcesDir : sourceSet.getResources().getSourceDirectories()) { - if (resourcesDir.exists() && !alreadyParsed.contains(baseDir.relativize(resourcesDir.toPath()))) { + if (resourcesDir.exists() && !alreadyParsed.contains(resourcesDir.toPath())) { OmniParser omniParser = omniParser(alreadyParsed); List accepted = omniParser.acceptedPaths(baseDir, resourcesDir.toPath()); sourceSetSourceFiles = Stream.concat( @@ -822,7 +822,7 @@ public Stream parse(Project subproject, Set alreadyParsed, Exe // Some source sets get misconfigured to have the same directories as other source sets // This causes duplicate source files to be parsed, so once a source set has been parsed exclude it from future parsing for (File file : sourceSet.getAllSource().getSourceDirectories().getFiles()) { - alreadyParsed.add(baseDir.relativize(file.toPath())); + alreadyParsed.add(file.toPath()); } } SourceFileStream gradleFiles = parseGradleFiles(exclusions, alreadyParsed, ctx); @@ -892,7 +892,7 @@ private SourceFileStream parseGradleFiles( gradleFileCount++; } sourceFiles = sourceFiles.map(sourceFile -> sourceFile.withMarkers(sourceFile.getMarkers().add(gp))); - alreadyParsed.add(buildScriptPath); + alreadyParsed.add(project.getBuildscript().getSourceFile().toPath()); } } @@ -920,7 +920,7 @@ private SourceFileStream parseGradleFiles( return sourceFile.withMarkers(sourceFile.getMarkers().add(finalGs)); })); gradleFileCount++; - alreadyParsed.add(settingsPath); + alreadyParsed.add(settingsGradleFile.toPath()); } else if (settingsGradleKtsFile.exists()) { Path settingsPath = baseDir.relativize(settingsGradleKtsFile.toPath()); sourceFiles = Stream.concat( @@ -934,7 +934,7 @@ private SourceFileStream parseGradleFiles( return sourceFile.withMarkers(sourceFile.getMarkers().add(finalGs)); })); gradleFileCount++; - alreadyParsed.add(settingsPath); + alreadyParsed.add(settingsGradleKtsFile.toPath()); } } From c8ef7d0ab9f5bb4563ffb1150d14332c843ebe4a Mon Sep 17 00:00:00 2001 From: Sam Snyder Date: Fri, 29 Sep 2023 16:54:32 -0700 Subject: [PATCH 13/20] Temporarily pin versions because latest.release isn't getting the latest, for reasons which are unclear to me --- plugin/build.gradle.kts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index 003ddf497..4ad284e60 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -7,7 +7,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import java.util.* plugins { - kotlin("jvm") version("1.8.0") + kotlin("jvm") version("1.9.0") id("com.gradle.plugin-publish") version "1.1.0" id("com.github.hierynomus.license") version "0.16.1" } @@ -89,7 +89,7 @@ tasks.withType().configureEach { val rewriteDependencies = configurations.create("rewriteDependencies") dependencies { - "rewriteDependencies"(platform("org.openrewrite:rewrite-bom:$latest")) + "rewriteDependencies"(platform("org.openrewrite:rewrite-bom:8.6.2")) "rewriteDependencies"("org.openrewrite:rewrite-core") "rewriteDependencies"("org.openrewrite:rewrite-hcl") "rewriteDependencies"("org.openrewrite:rewrite-java") @@ -97,35 +97,35 @@ dependencies { "rewriteDependencies"("org.openrewrite:rewrite-java-11") "rewriteDependencies"("org.openrewrite:rewrite-java-8") "rewriteDependencies"("org.openrewrite:rewrite-json") - "rewriteDependencies"("org.openrewrite:rewrite-kotlin:$latest") + "rewriteDependencies"("org.openrewrite:rewrite-kotlin:1.4.11") "rewriteDependencies"("org.openrewrite:rewrite-xml") "rewriteDependencies"("org.openrewrite:rewrite-yaml") "rewriteDependencies"("org.openrewrite:rewrite-properties") "rewriteDependencies"("org.openrewrite:rewrite-protobuf") "rewriteDependencies"("org.openrewrite:rewrite-groovy") "rewriteDependencies"("org.openrewrite:rewrite-gradle") - "rewriteDependencies"("org.openrewrite:rewrite-polyglot:$latest") - "rewriteDependencies"("org.openrewrite.gradle.tooling:model:$latest") + "rewriteDependencies"("org.openrewrite:rewrite-polyglot:1.6.1") + "rewriteDependencies"("org.openrewrite.gradle.tooling:model:1.3.1") "rewriteDependencies"("org.openrewrite:rewrite-maven") // Newer versions of checkstyle are compiled with a newer version of Java than is supported with gradle 4.x @Suppress("VulnerableLibrariesLocal", "RedundantSuppression") "rewriteDependencies"("com.puppycrawl.tools:checkstyle:9.3") "rewriteDependencies"("com.fasterxml.jackson.module:jackson-module-kotlin:latest.release") - implementation(platform("org.openrewrite:rewrite-bom:$latest")) + implementation(platform("org.openrewrite:rewrite-bom:8.6.2")) compileOnly("org.openrewrite:rewrite-core") compileOnly("org.openrewrite:rewrite-gradle") - compileOnly("org.openrewrite.gradle.tooling:model:$latest") + compileOnly("org.openrewrite.gradle.tooling:model:1.3.1") compileOnly("org.openrewrite:rewrite-groovy") compileOnly("org.openrewrite:rewrite-hcl") compileOnly("org.openrewrite:rewrite-java") compileOnly("org.openrewrite:rewrite-json") - compileOnly("org.openrewrite:rewrite-kotlin:$latest") + compileOnly("org.openrewrite:rewrite-kotlin:1.4.11") compileOnly("org.openrewrite:rewrite-properties") compileOnly("org.openrewrite:rewrite-protobuf") compileOnly("org.openrewrite:rewrite-xml") compileOnly("org.openrewrite:rewrite-yaml") - compileOnly("org.openrewrite:rewrite-polyglot:$latest") + compileOnly("org.openrewrite:rewrite-polyglot:1.6.1") @Suppress("VulnerableLibrariesLocal", "RedundantSuppression") compileOnly("com.puppycrawl.tools:checkstyle:9.3") compileOnly("org.jetbrains.kotlin:kotlin-gradle-plugin:latest.release") From 0a0419b422041487610c598b9cf145e85639c53f Mon Sep 17 00:00:00 2001 From: Sam Snyder Date: Fri, 29 Sep 2023 17:00:10 -0700 Subject: [PATCH 14/20] Revert "Temporarily pin versions because latest.release isn't getting the latest, for reasons which are unclear to me" This reverts commit c8ef7d0ab9f5bb4563ffb1150d14332c843ebe4a. --- plugin/build.gradle.kts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index 4ad284e60..003ddf497 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -7,7 +7,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import java.util.* plugins { - kotlin("jvm") version("1.9.0") + kotlin("jvm") version("1.8.0") id("com.gradle.plugin-publish") version "1.1.0" id("com.github.hierynomus.license") version "0.16.1" } @@ -89,7 +89,7 @@ tasks.withType().configureEach { val rewriteDependencies = configurations.create("rewriteDependencies") dependencies { - "rewriteDependencies"(platform("org.openrewrite:rewrite-bom:8.6.2")) + "rewriteDependencies"(platform("org.openrewrite:rewrite-bom:$latest")) "rewriteDependencies"("org.openrewrite:rewrite-core") "rewriteDependencies"("org.openrewrite:rewrite-hcl") "rewriteDependencies"("org.openrewrite:rewrite-java") @@ -97,35 +97,35 @@ dependencies { "rewriteDependencies"("org.openrewrite:rewrite-java-11") "rewriteDependencies"("org.openrewrite:rewrite-java-8") "rewriteDependencies"("org.openrewrite:rewrite-json") - "rewriteDependencies"("org.openrewrite:rewrite-kotlin:1.4.11") + "rewriteDependencies"("org.openrewrite:rewrite-kotlin:$latest") "rewriteDependencies"("org.openrewrite:rewrite-xml") "rewriteDependencies"("org.openrewrite:rewrite-yaml") "rewriteDependencies"("org.openrewrite:rewrite-properties") "rewriteDependencies"("org.openrewrite:rewrite-protobuf") "rewriteDependencies"("org.openrewrite:rewrite-groovy") "rewriteDependencies"("org.openrewrite:rewrite-gradle") - "rewriteDependencies"("org.openrewrite:rewrite-polyglot:1.6.1") - "rewriteDependencies"("org.openrewrite.gradle.tooling:model:1.3.1") + "rewriteDependencies"("org.openrewrite:rewrite-polyglot:$latest") + "rewriteDependencies"("org.openrewrite.gradle.tooling:model:$latest") "rewriteDependencies"("org.openrewrite:rewrite-maven") // Newer versions of checkstyle are compiled with a newer version of Java than is supported with gradle 4.x @Suppress("VulnerableLibrariesLocal", "RedundantSuppression") "rewriteDependencies"("com.puppycrawl.tools:checkstyle:9.3") "rewriteDependencies"("com.fasterxml.jackson.module:jackson-module-kotlin:latest.release") - implementation(platform("org.openrewrite:rewrite-bom:8.6.2")) + implementation(platform("org.openrewrite:rewrite-bom:$latest")) compileOnly("org.openrewrite:rewrite-core") compileOnly("org.openrewrite:rewrite-gradle") - compileOnly("org.openrewrite.gradle.tooling:model:1.3.1") + compileOnly("org.openrewrite.gradle.tooling:model:$latest") compileOnly("org.openrewrite:rewrite-groovy") compileOnly("org.openrewrite:rewrite-hcl") compileOnly("org.openrewrite:rewrite-java") compileOnly("org.openrewrite:rewrite-json") - compileOnly("org.openrewrite:rewrite-kotlin:1.4.11") + compileOnly("org.openrewrite:rewrite-kotlin:$latest") compileOnly("org.openrewrite:rewrite-properties") compileOnly("org.openrewrite:rewrite-protobuf") compileOnly("org.openrewrite:rewrite-xml") compileOnly("org.openrewrite:rewrite-yaml") - compileOnly("org.openrewrite:rewrite-polyglot:1.6.1") + compileOnly("org.openrewrite:rewrite-polyglot:$latest") @Suppress("VulnerableLibrariesLocal", "RedundantSuppression") compileOnly("com.puppycrawl.tools:checkstyle:9.3") compileOnly("org.jetbrains.kotlin:kotlin-gradle-plugin:latest.release") From 5e7be11f8dbf48ff5289daffbcca2f64b008e5b4 Mon Sep 17 00:00:00 2001 From: Sam Snyder Date: Fri, 29 Sep 2023 17:00:37 -0700 Subject: [PATCH 15/20] Update kotlin version --- plugin/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/build.gradle.kts b/plugin/build.gradle.kts index 003ddf497..845263de0 100644 --- a/plugin/build.gradle.kts +++ b/plugin/build.gradle.kts @@ -7,7 +7,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import java.util.* plugins { - kotlin("jvm") version("1.8.0") + kotlin("jvm") version("1.9.0") id("com.gradle.plugin-publish") version "1.1.0" id("com.github.hierynomus.license") version "0.16.1" } From bd6372d0df6ae435fe07ab0bfbaa1ad9c11d0174 Mon Sep 17 00:00:00 2001 From: Wesley R Date: Tue, 10 Oct 2023 13:51:12 -0400 Subject: [PATCH 16/20] fix: use separate rewrite-polyglot version (#233) (#235) This commit fixes issue #233, where specifying a rewriteVersion inside the rewrite configuration block would result in rewrite-polyglot failing to resolve to a proper version. Co-authored-by: Wesley Rogers --- .../gradle/DefaultRewriteExtension.java | 5 +- .../gradle/RewriteResolveDependenciesTest.kt | 55 +++++++++++++++++++ 2 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 plugin/src/test/kotlin/org/openrewrite/gradle/RewriteResolveDependenciesTest.kt diff --git a/plugin/src/main/java/org/openrewrite/gradle/DefaultRewriteExtension.java b/plugin/src/main/java/org/openrewrite/gradle/DefaultRewriteExtension.java index a8856d872..2ae0f78f5 100644 --- a/plugin/src/main/java/org/openrewrite/gradle/DefaultRewriteExtension.java +++ b/plugin/src/main/java/org/openrewrite/gradle/DefaultRewriteExtension.java @@ -217,12 +217,13 @@ public String getRewriteVersion() { return rewriteVersion; } + private String rewritePolyglotVersion; @Override public String getRewritePolyglotVersion() { - if (rewriteVersion == null) { + if (rewritePolyglotVersion == null) { return getVersionProps().getProperty("org.openrewrite:rewrite-polyglot"); } - return rewriteVersion; + return rewritePolyglotVersion; } private String rewriteGradleModelVersion; diff --git a/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteResolveDependenciesTest.kt b/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteResolveDependenciesTest.kt new file mode 100644 index 000000000..d18446ad3 --- /dev/null +++ b/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteResolveDependenciesTest.kt @@ -0,0 +1,55 @@ +/* + * Copyright ${year} 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.gradle + +import org.assertj.core.api.Assertions.assertThat +import org.gradle.testkit.runner.TaskOutcome +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.io.TempDir +import java.io.File + +class RewriteResolveDependenciesTest : RewritePluginTest { + @Test + fun `Specifying a rewriteVersion does not cause build failures`( + @TempDir projectDir: File + ) { + gradleProject(projectDir) { + buildGradle(""" + plugins { + id("java") + id("org.openrewrite.rewrite") + } + + repositories { + mavenLocal() + mavenCentral() + maven { + url = uri("https://oss.sonatype.org/content/repositories/snapshots") + } + } + + rewrite { + rewriteVersion = "8.6.1" + } + """) + } + + val result = runGradle(projectDir, "rewriteResolveDependencies") + val rewriteDryRunResult = result.task(":rewriteResolveDependencies")!! + assertThat(rewriteDryRunResult.outcome).isEqualTo(TaskOutcome.SUCCESS) + } + +} From cd3fbd12f37edba244c6645a8a210a6b76469e4b Mon Sep 17 00:00:00 2001 From: Sam Snyder Date: Thu, 26 Oct 2023 20:48:52 -0700 Subject: [PATCH 17/20] Fix exclusion of whole project directories, allow "**/" patterns to match files in the root project --- .../gradle/isolated/DefaultProjectParser.java | 56 +++++++++++-------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java index 5c493c5f3..b2fab6f2a 100644 --- a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java +++ b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java @@ -80,6 +80,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.PathMatcher; +import java.nio.file.Paths; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; @@ -614,7 +615,7 @@ public Stream parse(Project subproject, Set alreadyParsed, Exe Collection exclusions = extension.getExclusions().stream() .map(pattern -> subproject.getProjectDir().toPath().getFileSystem().getPathMatcher("glob:" + pattern)) .collect(toList()); - if (isExcluded(exclusions, subproject.getProjectDir().toPath())) { + if (isExcluded(exclusions, baseDir.relativize(subproject.getProjectDir().toPath()))) { logger.lifecycle("Skipping project {} because it is excluded", subproject.getPath()); return Stream.empty(); } @@ -909,31 +910,35 @@ private SourceFileStream parseGradleFiles( if (gradleParser == null) { gradleParser = gradleParser(); } - sourceFiles = Stream.concat( - sourceFiles, - gradleParser - .parse(singleton(settingsGradleFile.toPath()), baseDir, ctx) - .map(sourceFile -> { - if (finalGs == null) { - return sourceFile; - } - return sourceFile.withMarkers(sourceFile.getMarkers().add(finalGs)); - })); - gradleFileCount++; + if(!isExcluded(exclusions, settingsPath)) { + sourceFiles = Stream.concat( + sourceFiles, + gradleParser + .parse(singleton(settingsGradleFile.toPath()), baseDir, ctx) + .map(sourceFile -> { + if (finalGs == null) { + return sourceFile; + } + return sourceFile.withMarkers(sourceFile.getMarkers().add(finalGs)); + })); + gradleFileCount++; + } alreadyParsed.add(settingsGradleFile.toPath()); } else if (settingsGradleKtsFile.exists()) { Path settingsPath = baseDir.relativize(settingsGradleKtsFile.toPath()); - sourceFiles = Stream.concat( - sourceFiles, - PlainTextParser.builder().build() - .parse(singleton(settingsGradleKtsFile.toPath()), baseDir, ctx) - .map(sourceFile -> { - if (finalGs == null) { - return sourceFile; - } - return sourceFile.withMarkers(sourceFile.getMarkers().add(finalGs)); - })); - gradleFileCount++; + if(!isExcluded(exclusions, settingsPath)) { + sourceFiles = Stream.concat( + sourceFiles, + PlainTextParser.builder().build() + .parse(singleton(settingsGradleKtsFile.toPath()), baseDir, ctx) + .map(sourceFile -> { + if (finalGs == null) { + return sourceFile; + } + return sourceFile.withMarkers(sourceFile.getMarkers().add(finalGs)); + })); + gradleFileCount++; + } alreadyParsed.add(settingsGradleKtsFile.toPath()); } } @@ -1099,6 +1104,11 @@ private boolean isExcluded(Collection exclusions, Path path) { return true; } } + // PathMather will not evaluate the path "build.gradle" to be matched by the pattern "**/build.gradle" + // This is counter-intuitive for most users and would otherwise require separate exclusions for files at the root and files in subdirectories + if(!path.isAbsolute() && !path.startsWith(File.separator)) { + return isExcluded(exclusions, Paths.get("/" + path)); + } return false; } From 0daa455128fe26ab97e1754adc23e1b55b931445 Mon Sep 17 00:00:00 2001 From: Kun Li <122563761+kunli2@users.noreply.github.com> Date: Fri, 27 Oct 2023 08:45:21 -0700 Subject: [PATCH 18/20] exclude parse kotlin files under path protos/build/generated (#237) --- .../org/openrewrite/gradle/isolated/DefaultProjectParser.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java index b2fab6f2a..e66388f16 100644 --- a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java +++ b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java @@ -739,7 +739,9 @@ public Stream parse(Project subproject, Set alreadyParsed, Exe } if (subproject.getPlugins().hasPlugin("org.jetbrains.kotlin.jvm")) { + String excludedProtosPath = subproject.getProjectDir().getPath() + "/protos/build/generated"; List kotlinPaths = unparsedSources.stream() + .filter(it -> !it.toString().startsWith(excludedProtosPath)) .filter(it -> it.toString().endsWith(".kt")) .collect(toList()); From c4d0ef275d971ea9d4a2c0e9390b6e73d5e8d6d5 Mon Sep 17 00:00:00 2001 From: traceyyoshima Date: Fri, 17 Nov 2023 12:36:14 -0700 Subject: [PATCH 19/20] Fix: parse all sort sets in parseMultiplatformKotlinProject. --- .../org/openrewrite/gradle/isolated/DefaultProjectParser.java | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java index e66388f16..27f1f8a60 100644 --- a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java +++ b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java @@ -1080,7 +1080,6 @@ private SourceFileStream parseMultiplatformKotlinProject(Project subproject, Col sourceFileStream = sourceFileStream.concat(cus.map(addProvenance(sourceSetProvenance)), kotlinPaths.size()); logger.info("Scanned {} Kotlin sources in {}/{}", kotlinPaths.size(), subproject.getPath(), kotlinDirectorySet.getName()); } - return sourceFileStream; } catch (Exception e) { logger.warn("Failed to resolve sourceSet from {}:{}. Some type information may be incomplete", subproject.getPath(), sourceSetName); From fdfd1aed8ebc297614a445d413222c3792f2ad11 Mon Sep 17 00:00:00 2001 From: Sam Snyder Date: Mon, 20 Nov 2023 13:47:58 -0800 Subject: [PATCH 20/20] Add test covering settings defined repositories --- .../gradle/isolated/DefaultProjectParser.java | 3 +- .../openrewrite/gradle/GradleProjectSpec.kt | 84 +++++++++---------- .../openrewrite/gradle/RewritePluginTest.kt | 7 +- .../org/openrewrite/gradle/RewriteRunTest.kt | 80 ++++++++++++++++-- 4 files changed, 121 insertions(+), 53 deletions(-) diff --git a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java index 27f1f8a60..eee2b7b14 100644 --- a/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java +++ b/plugin/src/main/java/org/openrewrite/gradle/isolated/DefaultProjectParser.java @@ -888,12 +888,11 @@ private SourceFileStream parseGradleFiles( if (buildScriptPath.toString().endsWith(".gradle")) { gradleParser = gradleParser(); sourceFiles = gradleParser.parse(singleton(buildGradleFile.toPath()), baseDir, ctx); - gradleFileCount++; } else { sourceFiles = PlainTextParser.builder().build() .parse(singleton(buildGradleFile.toPath()), baseDir, ctx); - gradleFileCount++; } + gradleFileCount++; sourceFiles = sourceFiles.map(sourceFile -> sourceFile.withMarkers(sourceFile.getMarkers().add(gp))); alreadyParsed.add(project.getBuildscript().getSourceFile().toPath()); } diff --git a/plugin/src/main/kotlin/org/openrewrite/gradle/GradleProjectSpec.kt b/plugin/src/main/kotlin/org/openrewrite/gradle/GradleProjectSpec.kt index 6b147d45e..92620ec2f 100644 --- a/plugin/src/main/kotlin/org/openrewrite/gradle/GradleProjectSpec.kt +++ b/plugin/src/main/kotlin/org/openrewrite/gradle/GradleProjectSpec.kt @@ -22,10 +22,10 @@ import java.io.File * Utility to help with writing gradle projects to disk to assist with plugin testing */ class GradleProjectSpec( - val dir: File + private val dir: File ) { - val subprojects: MutableList = mutableListOf() - val sourceSets: MutableList = mutableListOf() + private val subprojects: MutableList = mutableListOf() + private val sourceSets: MutableList = mutableListOf() @Language("groovy") var groovyBuildScript: String? = null @@ -37,7 +37,7 @@ class GradleProjectSpec( @Language("groovy") var settingsGradle: String? = null fun settingsGradle(@Language("groovy") text: String) { - settingsGradle = text.trimIndent(); + settingsGradle = text.trimIndent() } @Language("yaml") @@ -52,12 +52,12 @@ class GradleProjectSpec( checkstyleXml = text.trimIndent() } - val propertiesFiles: MutableMap = mutableMapOf() + private val propertiesFiles: MutableMap = mutableMapOf() fun propertiesFile(name: String, @Language("properties") text: String) { propertiesFiles[name] = text } - val textFiles: MutableMap = mutableMapOf() + private val textFiles: MutableMap = mutableMapOf() fun textFile(name: String, text: String) { textFiles[name] = text } @@ -77,8 +77,17 @@ class GradleProjectSpec( fun build(): GradleProjectSpec { dir.mkdirs() - if (settingsGradle != null) { - File(dir, "settings.gradle").writeText(settingsGradle!!) + val settings = File(dir, "settings.gradle") + if(settingsGradle == null) { + val settingsText = "rootProject.name = \"${dir.name}\"\n" + if (subprojects.isEmpty()) { + settings.writeText("rootProject.name = \"${dir.name}\"\n") + } else { + val subprojectsDeclarations = subprojects.joinToString("\n") { subproject -> "include('${subproject.dir.name}')" } + settings.writeText(settingsText + subprojectsDeclarations) + } + } else { + settings.writeText(settingsGradle!!) } if (groovyBuildScript != null) { @@ -90,21 +99,21 @@ class GradleProjectSpec( } if (checkstyleXml != null) { - File(dir, "config/checkstyle/checkstyle.xml").apply{ + File(dir, "config/checkstyle/checkstyle.xml").apply{ parentFile.mkdirs() writeText(checkstyleXml!!) } } for (props in propertiesFiles.entries) { - File(dir, props.key).apply{ + File(dir, props.key).apply{ parentFile.mkdirs() writeText(props.value) } } for (text in textFiles.entries) { - File(dir, text.key).apply{ + File(dir, text.key).apply{ parentFile.mkdirs() writeText(text.value) } @@ -113,46 +122,37 @@ class GradleProjectSpec( for (sourceSet in sourceSets) { sourceSet.build(File(dir, "src")) } - - val settings = File(dir, "settings.gradle") - val settingsText = "rootProject.name = \"${dir.name}\"\n" - if (subprojects.isEmpty()) { - settings.writeText("rootProject.name = \"${dir.name}\"\n") - } else { - val subprojectsDeclarations = subprojects.joinToString("\n") { subproject -> "include('${subproject.dir.name}')" } - settings.writeText(settingsText + subprojectsDeclarations) - for (subproject in subprojects) { - subproject.build() - } + for (subproject in subprojects) { + subproject.build() } return this } } class GradleSourceSetSpec( - val name: String + private val name: String ) { - val javaSources: MutableList = mutableListOf() + private val javaSources: MutableList = mutableListOf() fun java(@Language("java") source: String) { javaSources.add(source.trimIndent()) } - val kotlinSources: MutableList = mutableListOf() + private val kotlinSources: MutableList = mutableListOf() fun kotlin(@Language("kotlin") source: String) { kotlinSources.add(source.trimIndent()) } - val propertiesFiles: MutableMap = mutableMapOf() + private val propertiesFiles: MutableMap = mutableMapOf() fun propertiesFile(name: String, @Language("properties") text: String) { propertiesFiles[name] = text } - val yamlFiles: MutableMap = mutableMapOf() + private val yamlFiles: MutableMap = mutableMapOf() fun yamlFile(name: String, @Language("yaml") text: String) { yamlFiles[name] = text } - val groovyClasses: MutableList = mutableListOf() + private val groovyClasses: MutableList = mutableListOf() fun groovyClass(@Language("groovy") source: String) { groovyClasses.add(source.trimIndent()) } @@ -162,7 +162,7 @@ class GradleSourceSetSpec( fun build(dir: File): GradleSourceSetSpec { dir.mkdirs() for (javaSource in javaSources) { - val peckage = if (javaSource.startsWith("package")) { + val packageDecl = if (javaSource.startsWith("package")) { "package\\s+([a-zA-Z0-9.]+);".toRegex(RegexOption.MULTILINE) .find(javaSource)!! .groupValues[1] @@ -170,18 +170,18 @@ class GradleSourceSetSpec( "" }.replace(".", "/") val clazz = ".*(class|interface|enum)\\s+([a-zA-Z0-9-_]+)".toRegex(RegexOption.MULTILINE).find(javaSource)!!.groupValues[2] - val path = if (peckage.isEmpty()) { + val path = if (packageDecl.isEmpty()) { "$name/java/$clazz.java" } else { - "$name/java/$peckage/$clazz.java" + "$name/java/$packageDecl/$clazz.java" } - File(dir, path).apply{ + File(dir, path).apply{ parentFile.mkdirs() writeText(javaSource) } } for (kotlinSource in kotlinSources) { - val peckage = if (kotlinSource.startsWith("package")) { + val packageDecl = if (kotlinSource.startsWith("package")) { "package\\s+([a-zA-Z0-9.]+)".toRegex(RegexOption.MULTILINE) .find(kotlinSource)!! .groupValues[1] @@ -189,18 +189,18 @@ class GradleSourceSetSpec( "" }.replace(".", "/") val clazz = ".*(class|interface|enum)\\s+([a-zA-Z0-9-_]+)".toRegex(RegexOption.MULTILINE).find(kotlinSource)!!.groupValues[2] - val path = if (peckage.isEmpty()) { + val path = if (packageDecl.isEmpty()) { "$name/kotlin/$clazz.kt" } else { - "$name/kotlin/$peckage/$clazz.kt" + "$name/kotlin/$packageDecl/$clazz.kt" } - File(dir, path).apply{ + File(dir, path).apply{ parentFile.mkdirs() writeText(kotlinSource) } } for (groovySource in groovyClasses) { - val peckage = if (groovySource.startsWith("package")) { + val packageDecl = if (groovySource.startsWith("package")) { "package\\s+([a-zA-Z0-9.]+);?".toRegex(RegexOption.MULTILINE) .find(groovySource)!! .groupValues[1] @@ -208,19 +208,19 @@ class GradleSourceSetSpec( "" }.replace(".", "/") val clazz = ".*(class|interface|enum)\\s+([a-zA-Z0-9-_]+)".toRegex(RegexOption.MULTILINE).find(groovySource)!!.groupValues[2] - val path = if (peckage.isEmpty()) { + val path = if (packageDecl.isEmpty()) { "$name/groovy/$clazz.groovy" } else { - "$name/groovy/$peckage/$clazz.groovy" + "$name/groovy/$packageDecl/$clazz.groovy" } - File(dir, path).apply{ + File(dir, path).apply{ parentFile.mkdirs() writeText(groovySource) } } if (propertiesFiles.isNotEmpty()) { for (props in propertiesFiles.entries) { - File(dir, "$name/resources/${props.key}").apply{ + File(dir, "$name/resources/${props.key}").apply{ parentFile.mkdirs() writeText(props.value) } @@ -228,7 +228,7 @@ class GradleSourceSetSpec( } if (yamlFiles.isNotEmpty()) { for (yaml in yamlFiles.entries) { - File(dir, "$name/resources/${yaml.key}").apply{ + File(dir, "$name/resources/${yaml.key}").apply{ parentFile.mkdirs() writeText(yaml.value) } diff --git a/plugin/src/test/kotlin/org/openrewrite/gradle/RewritePluginTest.kt b/plugin/src/test/kotlin/org/openrewrite/gradle/RewritePluginTest.kt index d2b7f9e9b..d149186c5 100644 --- a/plugin/src/test/kotlin/org/openrewrite/gradle/RewritePluginTest.kt +++ b/plugin/src/test/kotlin/org/openrewrite/gradle/RewritePluginTest.kt @@ -29,7 +29,7 @@ interface RewritePluginTest { GradleRunner.create() .withDebug(ManagementFactory.getRuntimeMXBean().inputArguments.toString().indexOf("-agentlib:jdwp") > 0) .withProjectDir(testDir) - .apply{ + .apply{ if (gradleVersion != null) { withGradleVersion(gradleVersion) } @@ -44,4 +44,9 @@ interface RewritePluginTest { val currentVersion = if (gradleVersion == null) GradleVersion.current() else GradleVersion.version(gradleVersion) return currentVersion < GradleVersion.version("6.1") } + + fun lessThanGradle6_8(): Boolean { + val currentVersion = if (gradleVersion == null) GradleVersion.current() else GradleVersion.version(gradleVersion) + return currentVersion < GradleVersion.version("6.8") + } } diff --git a/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteRunTest.kt b/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteRunTest.kt index 8aee56aaa..4ba59e8d8 100644 --- a/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteRunTest.kt +++ b/plugin/src/test/kotlin/org/openrewrite/gradle/RewriteRunTest.kt @@ -21,7 +21,6 @@ package org.openrewrite.gradle import org.assertj.core.api.Assertions.assertThat import org.gradle.testkit.runner.TaskOutcome -import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test import org.junit.jupiter.api.condition.DisabledIf import org.junit.jupiter.api.condition.DisabledOnOs @@ -446,8 +445,8 @@ class RewriteRunTest : RewritePluginTest { rewriteYaml(""" type: specs.openrewrite.org/v1beta/recipe name: org.openrewrite.test.RemoveJacksonCore - displayName: Rename build.gradle to build.gradle.kts - description: Rename build.gradle to build.gradle.kts + displayName: Remove jackson-core + description: Remove jackson-core recipeList: - org.openrewrite.gradle.RemoveDependency: groupId: com.fasterxml.jackson.core @@ -516,6 +515,73 @@ class RewriteRunTest : RewritePluginTest { """.trimIndent()) } + + @DisabledIf("lessThanGradle6_8") + @Test + fun dependencyRepositoriesDeclaredInSettings( + @TempDir projectDir: File + ) { + gradleProject(projectDir) { + rewriteYaml(""" + type: specs.openrewrite.org/v1beta/recipe + name: org.openrewrite.test.UpgradeJacksonCore + displayName: Remove jackson-core + description: Remove jackson-core + recipeList: + - org.openrewrite.gradle.UpgradeDependencyVersion: + groupId: com.fasterxml.jackson.core + artifactId: jackson-core + nevVersion: 2.16.0 + """) + settingsGradle(""" + dependencyResolutionManagement { + repositories { + mavenLocal() + mavenCentral() + maven { + url = uri("https://oss.sonatype.org/content/repositories/snapshots") + } + } + } + """) + buildGradle(""" + plugins { + id("java") + id("org.openrewrite.rewrite") + } + + dependencies { + implementation("com.fasterxml.jackson.core:jackson-core:2.15.1") + } + + rewrite { + activeRecipe("org.openrewrite.test.UpgradeJacksonCore") + } + """) + } + + val result = runGradle(projectDir, "rewriteRun") + val rewriteRunResult = result.task(":rewriteRun")!! + assertThat(rewriteRunResult.outcome).isEqualTo(TaskOutcome.SUCCESS) + + assertThat(projectDir.resolve("build.gradle").readText()) + //language=groovy + .isEqualTo(""" + plugins { + id("java") + id("org.openrewrite.rewrite") + } + + dependencies { + implementation("com.fasterxml.jackson.core:jackson-core:2.16.0") + } + + rewrite { + activeRecipe("org.openrewrite.test.UpgradeJacksonCore") + } + """.trimIndent()) + } + @Test fun mergeConfiguredAndAutodetectedStyles(@TempDir projectDir: File) { gradleProject(projectDir) { @@ -913,7 +979,6 @@ class RewriteRunTest : RewritePluginTest { ) } - @Disabled("Applicability tests are no longer supported for YAML recipes") @DisabledOnOs(OS.WINDOWS) // A file handle I haven't been able to track down is left open, causing JUnit to fail to clean up the directory on Windows @Issue("https://github.com/openrewrite/rewrite-gradle-plugin/issues/176") @Test @@ -937,10 +1002,9 @@ class RewriteRunTest : RewritePluginTest { name: com.example.TextToSam displayName: Changes contents of sam.txt description: Change contents of sam.txt to "sam" - applicability: - singleSource: - - org.openrewrite.FindSourceFiles: - filePattern: "**/sam.txt" + preconditions: + - org.openrewrite.FindSourceFiles: + filePattern: "**/sam.txt" recipeList: - org.openrewrite.text.ChangeText: toText: sam