Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* 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.java;

import java.io.File;
import java.io.Serial;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Objects;
import java.util.Set;

import com.diffplug.spotless.FormatterFunc;
import com.diffplug.spotless.FormatterStep;
import com.diffplug.spotless.JarState;
import com.diffplug.spotless.Provisioner;

public final class ExpandWildcardImportsStep implements Serializable {
@Serial
private static final long serialVersionUID = 1L;

private static final String INCOMPATIBLE_ERROR_MESSAGE = "There was a problem interacting with Java-Parser; maybe you set an incompatible version?";
private static final String MAVEN_COORDINATES = "com.github.javaparser:javaparser-symbol-solver-core";
public static final String DEFAULT_VERSION = "3.27.1";

private final Collection<File> typeSolverClasspath;
private final JarState.Promised jarState;

private ExpandWildcardImportsStep(Collection<File> typeSolverClasspath, JarState.Promised jarState) {
this.typeSolverClasspath = typeSolverClasspath;
this.jarState = jarState;
}

public static FormatterStep create(Set<File> typeSolverClasspath, Provisioner provisioner) {
Objects.requireNonNull(provisioner, "provisioner cannot be null");
return FormatterStep.create("expandwildcardimports",
new ExpandWildcardImportsStep(typeSolverClasspath,
JarState.promise(() -> JarState.from(MAVEN_COORDINATES + ":" + DEFAULT_VERSION, provisioner))),
ExpandWildcardImportsStep::equalityState,
State::toFormatter);
}

private State equalityState() {
return new State(typeSolverClasspath, jarState.get());
}

private static class State implements Serializable {
@Serial
private static final long serialVersionUID = 1L;

private final Collection<File> typeSolverClasspath;
private final JarState jarState;

public State(Collection<File> typeSolverClasspath, JarState jarState) {
this.typeSolverClasspath = typeSolverClasspath;
this.jarState = jarState;
}

FormatterFunc toFormatter() {
try {
return (FormatterFunc) jarState
.getClassLoader()
.loadClass("com.diffplug.spotless.glue.javaparser.ExpandWildcardsFormatterFunc")
.getConstructor(Collection.class)
.newInstance(typeSolverClasspath);
} catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException
| InstantiationException | IllegalAccessException | NoClassDefFoundError cause) {
throw new IllegalStateException(INCOMPATIBLE_ERROR_MESSAGE, cause);
}
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ private FormatterConfig getFormatterConfig() {
FileLocator fileLocator = getFileLocator();
final Optional<String> 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, Optional.ofNullable(project));
}

private FileLocator getFileLocator() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
import java.io.File;
import java.util.List;
import java.util.Optional;
import java.util.Set;

import org.apache.maven.project.MavenProject;

import com.diffplug.spotless.LineEnding;
import com.diffplug.spotless.LintSuppression;
Expand All @@ -35,9 +38,10 @@ public class FormatterConfig {
private final List<FormatterStepFactory> globalStepFactories;
private final Optional<String> spotlessSetLicenseHeaderYearsFromGitHistory;
private final List<LintSuppression> lintSuppressions;
private final Optional<MavenProject> mavenProject;

public FormatterConfig(File baseDir, String encoding, LineEnding lineEndings, Optional<String> ratchetFrom, Provisioner provisioner,
FileLocator fileLocator, List<FormatterStepFactory> globalStepFactories, Optional<String> spotlessSetLicenseHeaderYearsFromGitHistory, List<LintSuppression> lintSuppressions) {
FileLocator fileLocator, List<FormatterStepFactory> globalStepFactories, Optional<String> spotlessSetLicenseHeaderYearsFromGitHistory, List<LintSuppression> lintSuppressions, Optional<MavenProject> mavenProject) {
this.encoding = encoding;
this.lineEndings = lineEndings;
this.ratchetFrom = ratchetFrom;
Expand All @@ -46,6 +50,7 @@ public FormatterConfig(File baseDir, String encoding, LineEnding lineEndings, Op
this.globalStepFactories = globalStepFactories;
this.spotlessSetLicenseHeaderYearsFromGitHistory = spotlessSetLicenseHeaderYearsFromGitHistory;
this.lintSuppressions = lintSuppressions;
this.mavenProject = mavenProject;
}

public String getEncoding() {
Expand Down Expand Up @@ -79,4 +84,8 @@ public FileLocator getFileLocator() {
public List<LintSuppression> getLintSuppressions() {
return unmodifiableList(lintSuppressions);
}

public Optional<MavenProject> getMavenProject() {
return mavenProject;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,12 @@ Optional<String> ratchetFrom(FormatterConfig config) {
}
}

protected Optional<Set<File>> getProjectClasspath(FormatterConfig config) {
return Optional.empty();
}

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(), getProjectClasspath(config));
}

private static List<FormatterStepFactory> gatherStepFactories(List<FormatterStepFactory> allGlobal, List<FormatterStepFactory> allConfigured) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
*/
package com.diffplug.spotless.maven;

import java.io.File;
import java.nio.charset.Charset;
import java.util.Optional;
import java.util.Set;

import com.diffplug.spotless.Provisioner;

Expand All @@ -28,14 +30,16 @@ public class FormatterStepConfig {
private final Provisioner provisioner;
private final FileLocator fileLocator;
private final Optional<String> spotlessSetLicenseHeaderYearsFromGitHistory;
private final Optional<Set<File>> projectClasspath;

public FormatterStepConfig(Charset encoding, String licenseHeaderDelimiter, Optional<String> ratchetFrom, Provisioner provisioner, FileLocator fileLocator, Optional<String> spotlessSetLicenseHeaderYearsFromGitHistory) {
public FormatterStepConfig(Charset encoding, String licenseHeaderDelimiter, Optional<String> ratchetFrom, Provisioner provisioner, FileLocator fileLocator, Optional<String> spotlessSetLicenseHeaderYearsFromGitHistory, Optional<Set<File>> projectClasspath) {
this.encoding = encoding;
this.licenseHeaderDelimiter = licenseHeaderDelimiter;
this.ratchetFrom = ratchetFrom;
this.provisioner = provisioner;
this.fileLocator = fileLocator;
this.spotlessSetLicenseHeaderYearsFromGitHistory = spotlessSetLicenseHeaderYearsFromGitHistory;
this.projectClasspath = projectClasspath;
}

public Charset getEncoding() {
Expand All @@ -61,4 +65,8 @@ public FileLocator getFileLocator() {
public Optional<String> spotlessSetLicenseHeaderYearsFromGitHistory() {
return spotlessSetLicenseHeaderYearsFromGitHistory;
}

public Optional<Set<File>> getProjectClasspath() {
return projectClasspath;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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 java.io.File;
import java.util.Collections;
import java.util.Set;

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) {
Set<File> classpath = config.getProjectClasspath().orElse(Collections.emptySet());
return ExpandWildcardImportsStep.create(classpath, config.getProvisioner());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,18 @@
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;

import org.apache.maven.artifact.DependencyResolutionRequiredException;
import org.apache.maven.model.Build;
import org.apache.maven.project.MavenProject;

import com.diffplug.spotless.generic.LicenseHeaderStep;
import com.diffplug.spotless.maven.FormatterConfig;
import com.diffplug.spotless.maven.FormatterFactory;
import com.diffplug.spotless.maven.generic.LicenseHeader;

Expand Down Expand Up @@ -80,6 +85,10 @@ public void addForbidWildcardImports(ForbidWildcardImports forbidWildcardImports
addStepFactory(forbidWildcardImports);
}

public void addExpandWildcardImports(ExpandWildcardImports expandWildcardImports) {
addStepFactory(expandWildcardImports);
}

public void addForbidModuleImports(ForbidModuleImports forbidModuleImports) {
addStepFactory(forbidModuleImports);
}
Expand All @@ -92,6 +101,27 @@ public void addCleanthat(CleanthatJava cleanthat) {
addStepFactory(cleanthat);
}

@Override
protected Optional<Set<File>> getProjectClasspath(FormatterConfig config) {
return config.getMavenProject().map(project -> {
try {
Set<File> classpath = new HashSet<>();
// Add compile classpath
for (String element : project.getCompileClasspathElements()) {
classpath.add(new File(element));
}
// Add test classpath
for (String element : project.getTestClasspathElements()) {
classpath.add(new File(element));
}
return classpath;
} catch (DependencyResolutionRequiredException e) {
// If we can't resolve dependencies, return empty set
return Collections.<File>emptySet();
}
});
}

private static String fileMask(Path path) {
String dir = path.toString();
if (!dir.endsWith(File.separator)) {
Expand Down