com.diffplug.gradle.spotless.JavaExtension Maven / Gradle / Ivy
Show all versions of spotless-plugin-gradle Show documentation
/*
* Copyright 2016-2024 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.gradle.spotless;
import static com.diffplug.gradle.spotless.PluginGradlePreconditions.requireElementsNonNull;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import javax.inject.Inject;
import org.gradle.api.Project;
import org.gradle.api.tasks.SourceSet;
import com.diffplug.spotless.FormatterStep;
import com.diffplug.spotless.extra.EquoBasedStepBuilder;
import com.diffplug.spotless.extra.java.EclipseJdtFormatterStep;
import com.diffplug.spotless.generic.LicenseHeaderStep;
import com.diffplug.spotless.java.CleanthatJavaStep;
import com.diffplug.spotless.java.FormatAnnotationsStep;
import com.diffplug.spotless.java.GoogleJavaFormatStep;
import com.diffplug.spotless.java.ImportOrderStep;
import com.diffplug.spotless.java.PalantirJavaFormatStep;
import com.diffplug.spotless.java.RemoveUnusedImportsStep;
public class JavaExtension extends FormatExtension implements HasBuiltinDelimiterForLicense, JvmLang {
static final String NAME = "java";
@Inject
public JavaExtension(SpotlessExtension spotless) {
super(spotless);
}
static final String LICENSE_HEADER_DELIMITER = LicenseHeaderStep.DEFAULT_JAVA_HEADER_DELIMITER;
@Override
public LicenseHeaderConfig licenseHeader(String licenseHeader) {
return licenseHeader(licenseHeader, LICENSE_HEADER_DELIMITER);
}
@Override
public LicenseHeaderConfig licenseHeaderFile(Object licenseHeaderFile) {
return licenseHeaderFile(licenseHeaderFile, LICENSE_HEADER_DELIMITER);
}
public ImportOrderConfig importOrder(String... importOrder) {
return new ImportOrderConfig(importOrder);
}
public ImportOrderConfig importOrderFile(Object importOrderFile) {
Objects.requireNonNull(importOrderFile);
return new ImportOrderConfig(getProject().file(importOrderFile));
}
public class ImportOrderConfig {
final String[] importOrder;
final File importOrderFile;
boolean wildcardsLast = false;
boolean semanticSort = false;
Set treatAsPackage = Set.of();
Set treatAsClass = Set.of();
ImportOrderConfig(String[] importOrder) {
this.importOrder = importOrder;
importOrderFile = null;
addStep(createStep());
}
ImportOrderConfig(File importOrderFile) {
importOrder = null;
this.importOrderFile = importOrderFile;
addStep(createStep());
}
/** Sorts wildcard imports after non-wildcard imports, instead of before. */
public ImportOrderConfig wildcardsLast() {
return wildcardsLast(true);
}
public ImportOrderConfig wildcardsLast(boolean wildcardsLast) {
this.wildcardsLast = wildcardsLast;
replaceStep(createStep());
return this;
}
public ImportOrderConfig semanticSort() {
return semanticSort(true);
}
public ImportOrderConfig semanticSort(boolean semanticSort) {
this.semanticSort = semanticSort;
replaceStep(createStep());
return this;
}
public ImportOrderConfig treatAsPackage(String... treatAsPackage) {
return treatAsPackage(Arrays.asList(treatAsPackage));
}
public ImportOrderConfig treatAsPackage(Collection treatAsPackage) {
this.treatAsPackage = new HashSet<>(treatAsPackage);
replaceStep(createStep());
return this;
}
public ImportOrderConfig treatAsClass(String... treatAsClass) {
return treatAsClass(Arrays.asList(treatAsClass));
}
public ImportOrderConfig treatAsClass(Collection treatAsClass) {
this.treatAsClass = new HashSet<>(treatAsClass);
replaceStep(createStep());
return this;
}
private FormatterStep createStep() {
ImportOrderStep importOrderStep = ImportOrderStep.forJava();
return importOrderFile != null
? importOrderStep.createFrom(wildcardsLast, semanticSort, treatAsPackage, treatAsClass, getProject().file(importOrderFile))
: importOrderStep.createFrom(wildcardsLast, semanticSort, treatAsPackage, treatAsClass, importOrder);
}
}
/** Removes any unused imports. */
public void removeUnusedImports() {
addStep(RemoveUnusedImportsStep.create(RemoveUnusedImportsStep.defaultFormatter(), provisioner()));
}
public void removeUnusedImports(String formatter) {
addStep(RemoveUnusedImportsStep.create(formatter, provisioner()));
}
/** Uses the google-java-format jar to format source code. */
public GoogleJavaFormatConfig googleJavaFormat() {
return googleJavaFormat(GoogleJavaFormatStep.defaultVersion());
}
/**
* Uses the given version of google-java-format to format source code.
*
* Limited to published versions. See issue #33
* for a workaround for using snapshot versions.
*/
public GoogleJavaFormatConfig googleJavaFormat(String version) {
Objects.requireNonNull(version);
return new GoogleJavaFormatConfig(version);
}
public class GoogleJavaFormatConfig {
final String version;
String groupArtifact;
String style;
boolean reflowLongStrings;
boolean reorderImports;
boolean formatJavadoc = true;
GoogleJavaFormatConfig(String version) {
this.version = Objects.requireNonNull(version);
this.groupArtifact = GoogleJavaFormatStep.defaultGroupArtifact();
this.style = GoogleJavaFormatStep.defaultStyle();
addStep(createStep());
}
public GoogleJavaFormatConfig groupArtifact(String groupArtifact) {
this.groupArtifact = Objects.requireNonNull(groupArtifact);
replaceStep(createStep());
return this;
}
public GoogleJavaFormatConfig style(String style) {
this.style = Objects.requireNonNull(style);
replaceStep(createStep());
return this;
}
public GoogleJavaFormatConfig aosp() {
return style("AOSP");
}
public GoogleJavaFormatConfig reflowLongStrings() {
return reflowLongStrings(true);
}
public GoogleJavaFormatConfig reflowLongStrings(boolean reflowLongStrings) {
this.reflowLongStrings = reflowLongStrings;
replaceStep(createStep());
return this;
}
public GoogleJavaFormatConfig reorderImports(boolean reorderImports) {
this.reorderImports = reorderImports;
replaceStep(createStep());
return this;
}
public GoogleJavaFormatConfig skipJavadocFormatting() {
return formatJavadoc(false);
}
public GoogleJavaFormatConfig formatJavadoc(boolean formatJavadoc) {
this.formatJavadoc = formatJavadoc;
replaceStep(createStep());
return this;
}
private FormatterStep createStep() {
return GoogleJavaFormatStep.create(
groupArtifact,
version,
style,
provisioner(),
reflowLongStrings,
reorderImports,
formatJavadoc);
}
}
/** Uses the palantir-java-format jar to format source code. */
public PalantirJavaFormatConfig palantirJavaFormat() {
return palantirJavaFormat(PalantirJavaFormatStep.defaultVersion());
}
/**
* Uses the given version of palantir-java-format to format source code.
*
* Limited to published versions. See issue #33
* for a workaround for using snapshot versions.
*/
public PalantirJavaFormatConfig palantirJavaFormat(String version) {
Objects.requireNonNull(version);
return new PalantirJavaFormatConfig(version);
}
public class PalantirJavaFormatConfig {
final String version;
String style;
boolean formatJavadoc;
PalantirJavaFormatConfig(String version) {
this.version = Objects.requireNonNull(version);
this.style = PalantirJavaFormatStep.defaultStyle();
addStep(createStep());
}
public PalantirJavaFormatConfig style(String style) {
this.style = Objects.requireNonNull(style);
replaceStep(createStep());
return this;
}
public PalantirJavaFormatConfig formatJavadoc(boolean formatJavadoc) {
this.formatJavadoc = formatJavadoc;
replaceStep(createStep());
return this;
}
private FormatterStep createStep() {
return PalantirJavaFormatStep.create(version, style, formatJavadoc, provisioner());
}
}
public EclipseConfig eclipse() {
return new EclipseConfig(EclipseJdtFormatterStep.defaultVersion());
}
public EclipseConfig eclipse(String version) {
return new EclipseConfig(version);
}
public class EclipseConfig {
private final EquoBasedStepBuilder builder;
EclipseConfig(String version) {
builder = EclipseJdtFormatterStep.createBuilder(provisioner());
builder.setVersion(version);
addStep(builder.build());
}
public void configFile(Object... configFiles) {
requireElementsNonNull(configFiles);
Project project = getProject();
builder.setPreferences(project.files(configFiles).getFiles());
replaceStep(builder.build());
}
public EclipseConfig withP2Mirrors(Map mirrors) {
builder.setP2Mirrors(mirrors);
replaceStep(builder.build());
return this;
}
}
/** Removes newlines between type annotations and types. */
public FormatAnnotationsConfig formatAnnotations() {
return new FormatAnnotationsConfig();
}
public class FormatAnnotationsConfig {
/** Annotations in addition to those in the default list. */
final List addedTypeAnnotations = new ArrayList<>();
/** Annotations that the user doesn't want treated as type annotations. */
final List removedTypeAnnotations = new ArrayList<>();
FormatAnnotationsConfig() {
addStep(createStep());
}
public FormatAnnotationsConfig addTypeAnnotation(String simpleName) {
Objects.requireNonNull(simpleName);
addedTypeAnnotations.add(simpleName);
replaceStep(createStep());
return this;
}
public FormatAnnotationsConfig removeTypeAnnotation(String simpleName) {
Objects.requireNonNull(simpleName);
removedTypeAnnotations.add(simpleName);
replaceStep(createStep());
return this;
}
private FormatterStep createStep() {
return FormatAnnotationsStep.create(
addedTypeAnnotations,
removedTypeAnnotations);
}
}
/** Apply CleanThat refactoring rules. */
public CleanthatJavaConfig cleanthat() {
return new CleanthatJavaConfig();
}
public class CleanthatJavaConfig {
private String groupArtifact = CleanthatJavaStep.defaultGroupArtifact();
private String version = CleanthatJavaStep.defaultVersion();
private String sourceJdk = CleanthatJavaStep.defaultSourceJdk();
private List mutators = new ArrayList<>(CleanthatJavaStep.defaultMutators());
private List excludedMutators = new ArrayList<>(CleanthatJavaStep.defaultExcludedMutators());
private boolean includeDraft = CleanthatJavaStep.defaultIncludeDraft();
CleanthatJavaConfig() {
addStep(createStep());
}
public CleanthatJavaConfig groupArtifact(String groupArtifact) {
Objects.requireNonNull(groupArtifact);
this.groupArtifact = groupArtifact;
replaceStep(createStep());
return this;
}
public CleanthatJavaConfig version(String version) {
Objects.requireNonNull(version);
this.version = version;
replaceStep(createStep());
return this;
}
public CleanthatJavaConfig sourceCompatibility(String jdkVersion) {
Objects.requireNonNull(jdkVersion);
this.sourceJdk = jdkVersion;
replaceStep(createStep());
return this;
}
// Especially useful to clear default mutators
public CleanthatJavaConfig clearMutators() {
this.mutators.clear();
replaceStep(createStep());
return this;
}
// An id of a mutator (see IMutator.getIds()) or
// tThe fully qualified name of a class implementing eu.solven.cleanthat.engine.java.refactorer.meta.IMutator
public CleanthatJavaConfig addMutator(String mutator) {
this.mutators.add(mutator);
replaceStep(createStep());
return this;
}
public CleanthatJavaConfig addMutators(Collection mutators) {
this.mutators.addAll(mutators);
replaceStep(createStep());
return this;
}
// useful to exclude a mutator amongst the default list of mutators
public CleanthatJavaConfig excludeMutator(String mutator) {
this.excludedMutators.add(mutator);
replaceStep(createStep());
return this;
}
public CleanthatJavaConfig includeDraft(boolean includeDraft) {
this.includeDraft = includeDraft;
replaceStep(createStep());
return this;
}
private FormatterStep createStep() {
return CleanthatJavaStep.create(
groupArtifact,
version,
sourceJdk, mutators, excludedMutators, includeDraft, provisioner());
}
}
/** If the user hasn't specified the files yet, we'll assume he/she means all of the java files. */
@Override
protected void setupTask(SpotlessTask task) {
if (target == null) {
target = getSources(getProject(),
"You must either specify 'target' manually or apply the 'java' plugin.",
SourceSet::getAllJava,
file -> file.getName().endsWith(".java"));
}
steps.replaceAll(step -> {
if (isLicenseHeaderStep(step)) {
return step.filterByFile(LicenseHeaderStep.unsupportedJvmFilesFilter());
} else {
return step;
}
});
super.setupTask(task);
}
}