From 4e02a6ce1960fc34aa670cd5a13ce2e91aa8ee48 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 24 Jan 2026 03:56:49 +0000 Subject: [PATCH 01/11] Initial plan From 567c52311d67489cca57f208f756a047c4694fc2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 24 Jan 2026 04:00:43 +0000 Subject: [PATCH 02/11] Add ExpandWildcardImports Maven plugin integration implementation Co-authored-by: shitikanth <544054+shitikanth@users.noreply.github.com> --- .../spotless/maven/AbstractSpotlessMojo.java | 2 +- .../spotless/maven/FormatterConfig.java | 10 ++- .../spotless/maven/FormatterFactory.java | 2 +- .../spotless/maven/FormatterStepConfig.java | 10 ++- .../maven/java/ExpandWildcardImports.java | 63 +++++++++++++++++++ .../diffplug/spotless/maven/java/Java.java | 4 ++ 6 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ExpandWildcardImports.java diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java index 3952a8de70..d2c84d7cdb 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java @@ -397,7 +397,7 @@ private FormatterConfig getFormatterConfig() { FileLocator fileLocator = getFileLocator(); final Optional optionalRatchetFrom = Optional.ofNullable(this.ratchetFrom) .filter(ratchet -> !RATCHETFROM_NONE.equals(ratchet)); - return new FormatterConfig(baseDir, encoding, lineEndings, optionalRatchetFrom, provisioner, fileLocator, formatterStepFactories, Optional.ofNullable(setLicenseHeaderYearsFromGitHistory), lintSuppressions); + return new FormatterConfig(baseDir, encoding, lineEndings, optionalRatchetFrom, provisioner, fileLocator, formatterStepFactories, Optional.ofNullable(setLicenseHeaderYearsFromGitHistory), lintSuppressions, project); } private FileLocator getFileLocator() { diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterConfig.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterConfig.java index 842d4da68e..4ef7ff1800 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterConfig.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterConfig.java @@ -21,6 +21,8 @@ import java.util.List; import java.util.Optional; +import org.apache.maven.project.MavenProject; + import com.diffplug.spotless.LineEnding; import com.diffplug.spotless.LintSuppression; import com.diffplug.spotless.Provisioner; @@ -35,9 +37,10 @@ public class FormatterConfig { private final List globalStepFactories; private final Optional spotlessSetLicenseHeaderYearsFromGitHistory; private final List lintSuppressions; + private final MavenProject project; public FormatterConfig(File baseDir, String encoding, LineEnding lineEndings, Optional ratchetFrom, Provisioner provisioner, - FileLocator fileLocator, List globalStepFactories, Optional spotlessSetLicenseHeaderYearsFromGitHistory, List lintSuppressions) { + FileLocator fileLocator, List globalStepFactories, Optional spotlessSetLicenseHeaderYearsFromGitHistory, List lintSuppressions, MavenProject project) { this.encoding = encoding; this.lineEndings = lineEndings; this.ratchetFrom = ratchetFrom; @@ -46,6 +49,7 @@ public FormatterConfig(File baseDir, String encoding, LineEnding lineEndings, Op this.globalStepFactories = globalStepFactories; this.spotlessSetLicenseHeaderYearsFromGitHistory = spotlessSetLicenseHeaderYearsFromGitHistory; this.lintSuppressions = lintSuppressions; + this.project = project; } public String getEncoding() { @@ -79,4 +83,8 @@ public FileLocator getFileLocator() { public List getLintSuppressions() { return unmodifiableList(lintSuppressions); } + + public MavenProject getProject() { + return project; + } } diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterFactory.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterFactory.java index 6c7cc0d349..62b266c1c2 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterFactory.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterFactory.java @@ -185,7 +185,7 @@ Optional ratchetFrom(FormatterConfig config) { } private FormatterStepConfig stepConfig(Charset encoding, FormatterConfig config) { - return new FormatterStepConfig(encoding, licenseHeaderDelimiter(), ratchetFrom(config), config.getProvisioner(), config.getFileLocator(), config.getSpotlessSetLicenseHeaderYearsFromGitHistory()); + return new FormatterStepConfig(encoding, licenseHeaderDelimiter(), ratchetFrom(config), config.getProvisioner(), config.getFileLocator(), config.getSpotlessSetLicenseHeaderYearsFromGitHistory(), config.getProject()); } private static List gatherStepFactories(List allGlobal, List allConfigured) { diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterStepConfig.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterStepConfig.java index a1f2e52b41..847cd358b7 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterStepConfig.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterStepConfig.java @@ -18,6 +18,8 @@ import java.nio.charset.Charset; import java.util.Optional; +import org.apache.maven.project.MavenProject; + import com.diffplug.spotless.Provisioner; public class FormatterStepConfig { @@ -28,14 +30,16 @@ public class FormatterStepConfig { private final Provisioner provisioner; private final FileLocator fileLocator; private final Optional spotlessSetLicenseHeaderYearsFromGitHistory; + private final MavenProject project; - public FormatterStepConfig(Charset encoding, String licenseHeaderDelimiter, Optional ratchetFrom, Provisioner provisioner, FileLocator fileLocator, Optional spotlessSetLicenseHeaderYearsFromGitHistory) { + public FormatterStepConfig(Charset encoding, String licenseHeaderDelimiter, Optional ratchetFrom, Provisioner provisioner, FileLocator fileLocator, Optional spotlessSetLicenseHeaderYearsFromGitHistory, MavenProject project) { this.encoding = encoding; this.licenseHeaderDelimiter = licenseHeaderDelimiter; this.ratchetFrom = ratchetFrom; this.provisioner = provisioner; this.fileLocator = fileLocator; this.spotlessSetLicenseHeaderYearsFromGitHistory = spotlessSetLicenseHeaderYearsFromGitHistory; + this.project = project; } public Charset getEncoding() { @@ -61,4 +65,8 @@ public FileLocator getFileLocator() { public Optional spotlessSetLicenseHeaderYearsFromGitHistory() { return spotlessSetLicenseHeaderYearsFromGitHistory; } + + public MavenProject getProject() { + return project; + } } diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ExpandWildcardImports.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ExpandWildcardImports.java new file mode 100644 index 0000000000..02829c61a1 --- /dev/null +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ExpandWildcardImports.java @@ -0,0 +1,63 @@ +/* + * Copyright 2025-2026 DiffPlug + * + * 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 + * + * http://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 com.diffplug.spotless.maven.java; + +import java.io.File; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.project.MavenProject; + +import com.diffplug.spotless.FormatterStep; +import com.diffplug.spotless.java.ExpandWildcardImportsStep; +import com.diffplug.spotless.maven.FormatterStepConfig; +import com.diffplug.spotless.maven.FormatterStepFactory; + +public class ExpandWildcardImports implements FormatterStepFactory { + + @Override + public FormatterStep newFormatterStep(FormatterStepConfig config) { + MavenProject project = config.getProject(); + Set typeSolverClasspath = new HashSet<>(); + + // Add source directories + String sourceDirectory = project.getBuild().getSourceDirectory(); + if (sourceDirectory != null) { + File sourceDir = new File(sourceDirectory); + if (sourceDir.exists()) { + typeSolverClasspath.add(sourceDir); + } + } + + String testSourceDirectory = project.getBuild().getTestSourceDirectory(); + if (testSourceDirectory != null) { + File testSourceDir = new File(testSourceDirectory); + if (testSourceDir.exists()) { + typeSolverClasspath.add(testSourceDir); + } + } + + // Add compiled dependencies + project.getArtifacts().stream() + .map(Artifact::getFile) + .filter(Objects::nonNull) + .forEach(typeSolverClasspath::add); + + return ExpandWildcardImportsStep.create(typeSolverClasspath, config.getProvisioner()); + } +} diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java index acc97647d7..53068fead5 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/Java.java @@ -88,6 +88,10 @@ public void addFormatAnnotations(FormatAnnotations formatAnnotations) { addStepFactory(formatAnnotations); } + public void addExpandWildcardImports(ExpandWildcardImports expandWildcardImports) { + addStepFactory(expandWildcardImports); + } + public void addCleanthat(CleanthatJava cleanthat) { addStepFactory(cleanthat); } From 2546cdb24d68cb15ed515cd6d6af88c29e408ff5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 24 Jan 2026 04:03:44 +0000 Subject: [PATCH 03/11] Add documentation for expandWildcardImports in Maven plugin README Co-authored-by: shitikanth <544054+shitikanth@users.noreply.github.com> --- plugin-maven/README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugin-maven/README.md b/plugin-maven/README.md index aa855dd4b9..6bb834dcae 100644 --- a/plugin-maven/README.md +++ b/plugin-maven/README.md @@ -232,6 +232,7 @@ any other maven phase (i.e. compile) then it can be configured as below; + @@ -257,6 +258,14 @@ any other maven phase (i.e. compile) then it can be configured as below; ``` +### expandWildcardImports + +Automatically replaces wildcard imports (e.g., `import java.util.*`) with explicit imports for the classes actually used in the code. This step analyzes your source code and project dependencies to determine which specific classes are needed and generates the appropriate import statements. + +```xml + +``` + ### forbidModuleImports ```xml From ee80a74f247087eedd7d5e61726b1109d0f6fd4e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 24 Jan 2026 04:05:51 +0000 Subject: [PATCH 04/11] Fix copyright year and improve source root handling to support multiple directories Co-authored-by: shitikanth <544054+shitikanth@users.noreply.github.com> --- .../maven/java/ExpandWildcardImports.java | 29 ++++++++----------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ExpandWildcardImports.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ExpandWildcardImports.java index 02829c61a1..bcea932608 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ExpandWildcardImports.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ExpandWildcardImports.java @@ -1,5 +1,5 @@ /* - * Copyright 2025-2026 DiffPlug + * Copyright 2025 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,22 +35,17 @@ public FormatterStep newFormatterStep(FormatterStepConfig config) { MavenProject project = config.getProject(); Set typeSolverClasspath = new HashSet<>(); - // Add source directories - String sourceDirectory = project.getBuild().getSourceDirectory(); - if (sourceDirectory != null) { - File sourceDir = new File(sourceDirectory); - if (sourceDir.exists()) { - typeSolverClasspath.add(sourceDir); - } - } - - String testSourceDirectory = project.getBuild().getTestSourceDirectory(); - if (testSourceDirectory != null) { - File testSourceDir = new File(testSourceDirectory); - if (testSourceDir.exists()) { - typeSolverClasspath.add(testSourceDir); - } - } + // Add all main source roots + project.getCompileSourceRoots().stream() + .map(File::new) + .filter(File::exists) + .forEach(typeSolverClasspath::add); + + // Add all test source roots + project.getTestCompileSourceRoots().stream() + .map(File::new) + .filter(File::exists) + .forEach(typeSolverClasspath::add); // Add compiled dependencies project.getArtifacts().stream() From 00b22ba2e3e3c6704a9b2028010cff88098d9359 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 24 Jan 2026 04:10:54 +0000 Subject: [PATCH 05/11] Add Maven plugin test for ExpandWildcardImportsStep Co-authored-by: shitikanth <544054+shitikanth@users.noreply.github.com> --- .../java/ExpandWildcardImportsStepTest.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 plugin-maven/src/test/java/com/diffplug/spotless/maven/java/ExpandWildcardImportsStepTest.java diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/ExpandWildcardImportsStepTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/ExpandWildcardImportsStepTest.java new file mode 100644 index 0000000000..7b7fcbeeb3 --- /dev/null +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/ExpandWildcardImportsStepTest.java @@ -0,0 +1,48 @@ +/* + * Copyright 2025 DiffPlug + * + * 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 + * + * http://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 com.diffplug.spotless.maven.java; + +import org.junit.jupiter.api.Test; + +import com.diffplug.spotless.maven.MavenIntegrationHarness; + +class ExpandWildcardImportsStepTest extends MavenIntegrationHarness { + + @Test + void testExpandWildcardImports() throws Exception { + writePomWithJavaSteps(""); + + // Create the supporting classes needed for import resolution + setFile("src/main/java/foo/bar/AnotherClassInSamePackage.java") + .toResource("java/expandwildcardimports/AnotherClassInSamePackage.test"); + setFile("src/main/java/foo/bar/baz/AnotherImportedClass.java") + .toResource("java/expandwildcardimports/AnotherImportedClass.test"); + + // Create the annotation class that's used in the test + setFile("src/main/java/org/example/SomeAnnotation.java") + .toContent("package org.example;\n\npublic @interface SomeAnnotation {}\n"); + + // Set the main file to format + String path = "src/main/java/foo/bar/JavaClassWithWildcards.java"; + setFile(path).toResource("java/expandwildcardimports/JavaClassWithWildcardsUnformatted.test"); + + // Run spotless:apply + mavenRunner().withArguments("spotless:apply").runNoError(); + + // Verify the wildcards were expanded + assertFile(path).sameAsResource("java/expandwildcardimports/JavaClassWithWildcardsFormatted.test"); + } +} From 0e5abc253d91ba9283009e1d4e465ecec987b83e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 Jan 2026 06:20:15 +0000 Subject: [PATCH 06/11] Add multi-module Maven test for ExpandWildcardImportsStep Co-authored-by: shitikanth <544054+shitikanth@users.noreply.github.com> --- .../java/ExpandWildcardImportsStepTest.java | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/ExpandWildcardImportsStepTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/ExpandWildcardImportsStepTest.java index 7b7fcbeeb3..af2cfcdec7 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/ExpandWildcardImportsStepTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/ExpandWildcardImportsStepTest.java @@ -15,6 +15,11 @@ */ package com.diffplug.spotless.maven.java; +import static java.util.Collections.emptyMap; + +import java.io.IOException; +import java.util.Map; + import org.junit.jupiter.api.Test; import com.diffplug.spotless.maven.MavenIntegrationHarness; @@ -45,4 +50,80 @@ void testExpandWildcardImports() throws Exception { // Verify the wildcards were expanded assertFile(path).sameAsResource("java/expandwildcardimports/JavaClassWithWildcardsFormatted.test"); } + + @Test + void testExpandWildcardImportsMultiModule() throws Exception { + /* + Create a multi-module project with the following structure: + + /junit-tmp-dir + ├── common + │ ├── pom.xml + │ └── src/main/java + │ ├── foo/bar/AnotherClassInSamePackage.java + │ ├── foo/bar/baz/AnotherImportedClass.java + │ └── org/example/SomeAnnotation.java + ├── app + │ ├── pom.xml + │ └── src/main/java + │ └── foo/bar/JavaClassWithWildcards.java (depends on common module) + ├── pom.xml (parent) + ├── .mvn + ├── mvnw + └── mvnw.cmd + */ + + // Create parent POM + String[] modules = new String[]{"common", "app"}; + String[] configuration = new String[]{ + "", + " ", + "" + }; + Map parentPomParams = buildPomXmlParams(null, null, null, configuration, modules, null, null); + setFile("pom.xml").toContent(createPomXmlContent("/multi-module/pom-parent.xml.mustache", parentPomParams)); + + // Create common module with supporting classes + setFile("common/pom.xml").toContent(createChildPom("common")); + setFile("common/src/main/java/foo/bar/AnotherClassInSamePackage.java") + .toResource("java/expandwildcardimports/AnotherClassInSamePackage.test"); + setFile("common/src/main/java/foo/bar/baz/AnotherImportedClass.java") + .toResource("java/expandwildcardimports/AnotherImportedClass.test"); + setFile("common/src/main/java/org/example/SomeAnnotation.java") + .toContent("package org.example;\n\npublic @interface SomeAnnotation {}\n"); + + // Create app module that depends on common + setFile("app/pom.xml").toContent(createChildPomWithDependency("app", "common")); + String path = "app/src/main/java/foo/bar/JavaClassWithWildcards.java"; + setFile(path).toResource("java/expandwildcardimports/JavaClassWithWildcardsUnformatted.test"); + + // Build common module first to make it available as dependency + mavenRunner().withArguments("-f", "common", "clean", "install").runNoError(); + + // Format all files in the multi-module project + mavenRunner().withArguments("spotless:apply").runNoError(); + + // Verify the wildcards were expanded in app module + assertFile(path).sameAsResource("java/expandwildcardimports/JavaClassWithWildcardsFormatted.test"); + } + + private String createChildPom(String childId) throws IOException { + return createPomXmlContent("/multi-module/pom-child.xml.mustache", Map.of("childId", childId)); + } + + private String createChildPomWithDependency(String childId, String dependencyModule) throws IOException { + String childPom = createChildPom(childId); + // Add dependency to the common module + String dependency = """ + + + com.diffplug.spotless + spotless-maven-plugin-tests-child-%s + 1.0.0-SNAPSHOT + + + """.formatted(dependencyModule); + // Insert before + return childPom.replace("", dependency + "\n"); + } } From 379c6a74a229e9bed9d6a2b307e14cdaba749124 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 Jan 2026 06:29:00 +0000 Subject: [PATCH 07/11] Initial plan From ec8ba9ad1f7417a6766e83847e4bb398155e7ed9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 Jan 2026 06:38:34 +0000 Subject: [PATCH 08/11] Disable multi-module test and remove mvn install requirement The test now validates the desired behavior (spotless:apply without mvn install) but is disabled until the implementation supports reactor dependencies via target/classes directories. Co-authored-by: shitikanth <544054+shitikanth@users.noreply.github.com> --- .../maven/java/ExpandWildcardImportsStepTest.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/ExpandWildcardImportsStepTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/ExpandWildcardImportsStepTest.java index af2cfcdec7..8e6a1d3be9 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/ExpandWildcardImportsStepTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/ExpandWildcardImportsStepTest.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.util.Map; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import com.diffplug.spotless.maven.MavenIntegrationHarness; @@ -52,6 +53,9 @@ void testExpandWildcardImports() throws Exception { } @Test + @Disabled("Multi-module reactor builds currently require 'mvn install' on dependency modules first. " + + "The implementation uses project.getArtifacts() which returns JAR files, but reactor dependencies " + + "need target/classes directories included in typeSolverClasspath before installation.") void testExpandWildcardImportsMultiModule() throws Exception { /* Create a multi-module project with the following structure: @@ -97,10 +101,8 @@ void testExpandWildcardImportsMultiModule() throws Exception { String path = "app/src/main/java/foo/bar/JavaClassWithWildcards.java"; setFile(path).toResource("java/expandwildcardimports/JavaClassWithWildcardsUnformatted.test"); - // Build common module first to make it available as dependency - mavenRunner().withArguments("-f", "common", "clean", "install").runNoError(); - - // Format all files in the multi-module project + // Format all files in the multi-module project without requiring 'mvn install' first + // This tests that spotless:apply works in a reactor build without pre-installing dependencies mavenRunner().withArguments("spotless:apply").runNoError(); // Verify the wildcards were expanded in app module From 10120ed53f2af6b761a96d98b759b544fd6d9139 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 Jan 2026 08:30:05 +0000 Subject: [PATCH 09/11] Use Maven DependencyResolver API for reactor dependencies - Added RepositorySystem and RepositorySystemSession to FormatterStepConfig - Updated configuration chain to pass these through FormatterConfig - Modified ExpandWildcardImports to use resolveDependencies() API - WorkspaceReader in session resolves reactor modules to target/classes - Fallback to project.getArtifacts() if resolution fails - Re-enabled multi-module test Co-authored-by: shitikanth <544054+shitikanth@users.noreply.github.com> --- .../spotless/maven/AbstractSpotlessMojo.java | 2 +- .../spotless/maven/FormatterConfig.java | 16 ++++- .../spotless/maven/FormatterFactory.java | 2 +- .../spotless/maven/FormatterStepConfig.java | 16 ++++- .../maven/java/ExpandWildcardImports.java | 63 +++++++++++++++++-- .../java/ExpandWildcardImportsStepTest.java | 3 - 6 files changed, 89 insertions(+), 13 deletions(-) diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java index d2c84d7cdb..e138cbd157 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/AbstractSpotlessMojo.java @@ -397,7 +397,7 @@ private FormatterConfig getFormatterConfig() { FileLocator fileLocator = getFileLocator(); final Optional optionalRatchetFrom = Optional.ofNullable(this.ratchetFrom) .filter(ratchet -> !RATCHETFROM_NONE.equals(ratchet)); - return new FormatterConfig(baseDir, encoding, lineEndings, optionalRatchetFrom, provisioner, fileLocator, formatterStepFactories, Optional.ofNullable(setLicenseHeaderYearsFromGitHistory), lintSuppressions, project); + return new FormatterConfig(baseDir, encoding, lineEndings, optionalRatchetFrom, provisioner, fileLocator, formatterStepFactories, Optional.ofNullable(setLicenseHeaderYearsFromGitHistory), lintSuppressions, project, repositorySystem, repositorySystemSession); } private FileLocator getFileLocator() { diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterConfig.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterConfig.java index 4ef7ff1800..9477d36725 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterConfig.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterConfig.java @@ -22,6 +22,8 @@ import java.util.Optional; import org.apache.maven.project.MavenProject; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; import com.diffplug.spotless.LineEnding; import com.diffplug.spotless.LintSuppression; @@ -38,9 +40,11 @@ public class FormatterConfig { private final Optional spotlessSetLicenseHeaderYearsFromGitHistory; private final List lintSuppressions; private final MavenProject project; + private final RepositorySystem repositorySystem; + private final RepositorySystemSession repositorySystemSession; public FormatterConfig(File baseDir, String encoding, LineEnding lineEndings, Optional ratchetFrom, Provisioner provisioner, - FileLocator fileLocator, List globalStepFactories, Optional spotlessSetLicenseHeaderYearsFromGitHistory, List lintSuppressions, MavenProject project) { + FileLocator fileLocator, List globalStepFactories, Optional spotlessSetLicenseHeaderYearsFromGitHistory, List lintSuppressions, MavenProject project, RepositorySystem repositorySystem, RepositorySystemSession repositorySystemSession) { this.encoding = encoding; this.lineEndings = lineEndings; this.ratchetFrom = ratchetFrom; @@ -50,6 +54,8 @@ public FormatterConfig(File baseDir, String encoding, LineEnding lineEndings, Op this.spotlessSetLicenseHeaderYearsFromGitHistory = spotlessSetLicenseHeaderYearsFromGitHistory; this.lintSuppressions = lintSuppressions; this.project = project; + this.repositorySystem = repositorySystem; + this.repositorySystemSession = repositorySystemSession; } public String getEncoding() { @@ -87,4 +93,12 @@ public List getLintSuppressions() { public MavenProject getProject() { return project; } + + public RepositorySystem getRepositorySystem() { + return repositorySystem; + } + + public RepositorySystemSession getRepositorySystemSession() { + return repositorySystemSession; + } } diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterFactory.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterFactory.java index 62b266c1c2..1e8e24915f 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterFactory.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterFactory.java @@ -185,7 +185,7 @@ Optional ratchetFrom(FormatterConfig config) { } private FormatterStepConfig stepConfig(Charset encoding, FormatterConfig config) { - return new FormatterStepConfig(encoding, licenseHeaderDelimiter(), ratchetFrom(config), config.getProvisioner(), config.getFileLocator(), config.getSpotlessSetLicenseHeaderYearsFromGitHistory(), config.getProject()); + return new FormatterStepConfig(encoding, licenseHeaderDelimiter(), ratchetFrom(config), config.getProvisioner(), config.getFileLocator(), config.getSpotlessSetLicenseHeaderYearsFromGitHistory(), config.getProject(), config.getRepositorySystem(), config.getRepositorySystemSession()); } private static List gatherStepFactories(List allGlobal, List allConfigured) { diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterStepConfig.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterStepConfig.java index 847cd358b7..38dce91eef 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterStepConfig.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/FormatterStepConfig.java @@ -19,6 +19,8 @@ import java.util.Optional; import org.apache.maven.project.MavenProject; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; import com.diffplug.spotless.Provisioner; @@ -31,8 +33,10 @@ public class FormatterStepConfig { private final FileLocator fileLocator; private final Optional spotlessSetLicenseHeaderYearsFromGitHistory; private final MavenProject project; + private final RepositorySystem repositorySystem; + private final RepositorySystemSession repositorySystemSession; - public FormatterStepConfig(Charset encoding, String licenseHeaderDelimiter, Optional ratchetFrom, Provisioner provisioner, FileLocator fileLocator, Optional spotlessSetLicenseHeaderYearsFromGitHistory, MavenProject project) { + public FormatterStepConfig(Charset encoding, String licenseHeaderDelimiter, Optional ratchetFrom, Provisioner provisioner, FileLocator fileLocator, Optional spotlessSetLicenseHeaderYearsFromGitHistory, MavenProject project, RepositorySystem repositorySystem, RepositorySystemSession repositorySystemSession) { this.encoding = encoding; this.licenseHeaderDelimiter = licenseHeaderDelimiter; this.ratchetFrom = ratchetFrom; @@ -40,6 +44,8 @@ public FormatterStepConfig(Charset encoding, String licenseHeaderDelimiter, Opti this.fileLocator = fileLocator; this.spotlessSetLicenseHeaderYearsFromGitHistory = spotlessSetLicenseHeaderYearsFromGitHistory; this.project = project; + this.repositorySystem = repositorySystem; + this.repositorySystemSession = repositorySystemSession; } public Charset getEncoding() { @@ -69,4 +75,12 @@ public Optional spotlessSetLicenseHeaderYearsFromGitHistory() { public MavenProject getProject() { return project; } + + public RepositorySystem getRepositorySystem() { + return repositorySystem; + } + + public RepositorySystemSession getRepositorySystemSession() { + return repositorySystemSession; + } } diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ExpandWildcardImports.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ExpandWildcardImports.java index bcea932608..01755d21a8 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ExpandWildcardImports.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ExpandWildcardImports.java @@ -17,11 +17,21 @@ import java.io.File; import java.util.HashSet; +import java.util.List; import java.util.Objects; import java.util.Set; +import java.util.stream.Collectors; -import org.apache.maven.artifact.Artifact; import org.apache.maven.project.MavenProject; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.collection.CollectRequest; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.resolution.ArtifactResult; +import org.eclipse.aether.resolution.DependencyRequest; +import org.eclipse.aether.resolution.DependencyResolutionException; +import org.eclipse.aether.resolution.DependencyResult; import com.diffplug.spotless.FormatterStep; import com.diffplug.spotless.java.ExpandWildcardImportsStep; @@ -47,12 +57,53 @@ public FormatterStep newFormatterStep(FormatterStepConfig config) { .filter(File::exists) .forEach(typeSolverClasspath::add); - // Add compiled dependencies - project.getArtifacts().stream() - .map(Artifact::getFile) - .filter(Objects::nonNull) - .forEach(typeSolverClasspath::add); + // Resolve dependencies using Maven's DependencyResolver API + // This will properly handle reactor dependencies by including their target/classes directories + // via the WorkspaceReader in the RepositorySystemSession + typeSolverClasspath.addAll(resolveDependencies(project, config.getRepositorySystem(), config.getRepositorySystemSession())); return ExpandWildcardImportsStep.create(typeSolverClasspath, config.getProvisioner()); } + + private Set resolveDependencies(MavenProject project, RepositorySystem repositorySystem, RepositorySystemSession session) { + try { + // Convert Maven project dependencies to Aether dependencies + List dependencies = project.getDependencies().stream() + .map(dep -> new Dependency( + new org.eclipse.aether.artifact.DefaultArtifact( + dep.getGroupId(), + dep.getArtifactId(), + dep.getClassifier(), + dep.getType(), + dep.getVersion()), + dep.getScope())) + .collect(Collectors.toList()); + + // Create a collect request with all dependencies + CollectRequest collectRequest = new CollectRequest(); + collectRequest.setDependencies(dependencies); + collectRequest.setRepositories(project.getRemoteProjectRepositories()); + + // Create a dependency request to resolve all artifacts + DependencyRequest dependencyRequest = new DependencyRequest(collectRequest, null); + + // Resolve dependencies - this will use the WorkspaceReader in the session + // to resolve reactor modules to their target/classes directories + DependencyResult result = repositorySystem.resolveDependencies(session, dependencyRequest); + + // Extract the resolved artifact files + return result.getArtifactResults().stream() + .map(ArtifactResult::getArtifact) + .map(Artifact::getFile) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + } catch (DependencyResolutionException e) { + // If resolution fails, fall back to using the artifacts already attached to the project + // This ensures the build doesn't fail, but may not include reactor dependencies + return project.getArtifacts().stream() + .map(org.apache.maven.artifact.Artifact::getFile) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + } + } } diff --git a/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/ExpandWildcardImportsStepTest.java b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/ExpandWildcardImportsStepTest.java index 8e6a1d3be9..17670df238 100644 --- a/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/ExpandWildcardImportsStepTest.java +++ b/plugin-maven/src/test/java/com/diffplug/spotless/maven/java/ExpandWildcardImportsStepTest.java @@ -53,9 +53,6 @@ void testExpandWildcardImports() throws Exception { } @Test - @Disabled("Multi-module reactor builds currently require 'mvn install' on dependency modules first. " + - "The implementation uses project.getArtifacts() which returns JAR files, but reactor dependencies " + - "need target/classes directories included in typeSolverClasspath before installation.") void testExpandWildcardImportsMultiModule() throws Exception { /* Create a multi-module project with the following structure: From 903bcd5158312fd25a2b99d073b80cf754670f4b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 Jan 2026 08:31:36 +0000 Subject: [PATCH 10/11] Improve dependency resolution and error handling - Use project.getArtifacts() instead of getDependencies() to include transitives - Add warning message when falling back to non-reactor-aware resolution - Better error handling for dependency resolution failures Co-authored-by: shitikanth <544054+shitikanth@users.noreply.github.com> --- .../maven/java/ExpandWildcardImports.java | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ExpandWildcardImports.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ExpandWildcardImports.java index 01755d21a8..ca5a4e0bf4 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ExpandWildcardImports.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ExpandWildcardImports.java @@ -67,16 +67,18 @@ public FormatterStep newFormatterStep(FormatterStepConfig config) { private Set resolveDependencies(MavenProject project, RepositorySystem repositorySystem, RepositorySystemSession session) { try { - // Convert Maven project dependencies to Aether dependencies - List dependencies = project.getDependencies().stream() - .map(dep -> new Dependency( + // Use the project's already-resolved artifacts (which includes transitives) + // and convert them to Aether dependencies for re-resolution + // This allows the WorkspaceReader to map reactor modules to target/classes + List dependencies = project.getArtifacts().stream() + .map(artifact -> new Dependency( new org.eclipse.aether.artifact.DefaultArtifact( - dep.getGroupId(), - dep.getArtifactId(), - dep.getClassifier(), - dep.getType(), - dep.getVersion()), - dep.getScope())) + artifact.getGroupId(), + artifact.getArtifactId(), + artifact.getClassifier(), + artifact.getType(), + artifact.getVersion()), + artifact.getScope())) .collect(Collectors.toList()); // Create a collect request with all dependencies @@ -99,7 +101,10 @@ private Set resolveDependencies(MavenProject project, RepositorySystem rep .collect(Collectors.toSet()); } catch (DependencyResolutionException e) { // If resolution fails, fall back to using the artifacts already attached to the project - // This ensures the build doesn't fail, but may not include reactor dependencies + // This ensures the build doesn't fail, but reactor dependencies may not be properly resolved + // Log at debug level to help troubleshoot dependency resolution issues + System.err.println("Warning: Failed to resolve dependencies using RepositorySystem, " + + "falling back to project artifacts. Reactor dependencies may not be properly resolved: " + e.getMessage()); return project.getArtifacts().stream() .map(org.apache.maven.artifact.Artifact::getFile) .filter(Objects::nonNull) From c903208926f46b06eff3930db283e8346a15d3c0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 Jan 2026 08:32:55 +0000 Subject: [PATCH 11/11] Extract fallback logic to separate method - Created getFallbackArtifacts() method to reduce code duplication - Added clarifying comment about System.err usage in FormatterStepFactory Co-authored-by: shitikanth <544054+shitikanth@users.noreply.github.com> --- .../spotless/maven/java/ExpandWildcardImports.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ExpandWildcardImports.java b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ExpandWildcardImports.java index ca5a4e0bf4..11e8440a43 100644 --- a/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ExpandWildcardImports.java +++ b/plugin-maven/src/main/java/com/diffplug/spotless/maven/java/ExpandWildcardImports.java @@ -102,13 +102,17 @@ private Set resolveDependencies(MavenProject project, RepositorySystem rep } catch (DependencyResolutionException e) { // If resolution fails, fall back to using the artifacts already attached to the project // This ensures the build doesn't fail, but reactor dependencies may not be properly resolved - // Log at debug level to help troubleshoot dependency resolution issues + // Note: Using System.err as this is a FormatterStepFactory without access to Maven's logger System.err.println("Warning: Failed to resolve dependencies using RepositorySystem, " + "falling back to project artifacts. Reactor dependencies may not be properly resolved: " + e.getMessage()); - return project.getArtifacts().stream() - .map(org.apache.maven.artifact.Artifact::getFile) - .filter(Objects::nonNull) - .collect(Collectors.toSet()); + return getFallbackArtifacts(project); } } + + private Set getFallbackArtifacts(MavenProject project) { + return project.getArtifacts().stream() + .map(org.apache.maven.artifact.Artifact::getFile) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + } }