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("""