AbstractConfigurationMojo.java
package io.github.jonasrutishauser.errorprone.maven.plugin;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
abstract class AbstractConfigurationMojo extends AbstractMojo {
/**
* Allows disabling Error Prone altogether.
* <p>
* Error Prone will still be in the annotation processor path, but
* {@code -Xplugin:ErrorProne} won't be passed as a compiler argument.
*/
@Parameter(defaultValue = "true", property = "errorprone.enabled")
private boolean enabled;
/**
* Disable all Error Prone checks. Maps to {@code -XepDisableAllChecks}.
* <p>
* This will be the first argument, so checks can then be re-enabled on a
* case-by-case basis.
*/
@Parameter(defaultValue = "false", property = "errorprone.disableAllChecks")
private boolean disableAllChecks;
/**
* Disables all Error Prone warnings. Maps to {@code -XepDisableAllWarnings}.
* <p>
* This will be among the first arguments, so checks can then be re-enabled on a
* case-by-case basis.
*/
@Parameter(defaultValue = "false", property = "errorprone.disableAllWarnings")
private boolean disableAllWarnings;
/**
* Turns all Error Prone errors into warnings. Maps to
* {@code -XepAllErrorsAsWarnings}.
* <p>
* This will be among the first arguments, so checks can then be promoted back
* to error on a case-by-case basis.
*/
@Parameter(defaultValue = "false", property = "errorprone.allErrorsAsWarnings")
private boolean allErrorsAsWarnings;
/**
* Turn all Error Prone suggestions into warnings. Maps to
* {@code -XepAllSuggestionsAsWarnings}.
* <p>
* This will be among the first arguments, so checks can then be demoted back to
* suggestions on a case-by-case basis.
*/
@Parameter(defaultValue = "false", property = "errorprone.allSuggestionsAsWarnings")
private boolean allSuggestionsAsWarnings;
/**
* Enables all Error Prone checks, checks that are disabled by default are
* enabled as warnings. Maps to {@code -XepAllDisabledChecksAsWarnings}.
* <p>
* This will be among the first arguments, so checks can then be disabled again
* on a case-by-case basis.
*/
@Parameter(defaultValue = "false", property = "errorprone.allDisabledChecksAsWarnings")
private boolean allDisabledChecksAsWarnings;
/**
* Disables warnings in classes annotated with {@code @Generated}. Maps to
* {@code -XepDisableWarningsInGeneratedCode}.
*/
@Parameter(defaultValue = "false", property = "errorprone.disableWarningsInGeneratedCode")
private boolean disableWarningsInGeneratedCode;
/**
* Tells Error Prone to ignore unknown check names in {@link #checks checks}.
* Maps to {@code -XepIgnoreUnknownCheckNames}.
*/
@Parameter(defaultValue = "false", property = "errorprone.ignoreUnknownCheckNames")
private boolean ignoreUnknownCheckNames;
/**
* Ignores suppression annotations, such as
* {@link SuppressWarnings @SuppressWarnings}. Maps to
* {@code -XepIgnoreSuppressionAnnotations}.
*/
@Parameter(defaultValue = "false", property = "errorprone.ignoreSuppressionAnnotations")
private boolean ignoreSuppressionAnnotations;
/**
* A regular expression pattern of file paths to exclude from Error Prone
* checking. Maps to {@code -XepExcludedPaths}.
*/
@Parameter(property = "errorprone.excludePaths")
private String excludePaths;
/**
* A map of check name to {@link CheckSeverity}, to configure which checks are
* enabled or disabled, and their severity.
* <p>
* Maps each entry to {@code -Xep:<key>:<value>}, or {@code -Xep:<key>} if the
* value is {@link CheckSeverity#DEFAULT}.
*/
@Parameter
private Map<String, CheckSeverity> checks = new HashMap<>();
/**
* A map of <a href=
* "https://errorprone.info/docs/flags#pass-additional-info-to-bugcheckers">check
* options</a> to their value.
* <p>
* Use an explicit {@code "true"} value for a boolean option.
* <p>
* Maps each entry to {@code -XepOpt:<key>=<value>}.
*/
@Parameter
private Map<String, String> options = new HashMap<>();
/**
* A map of <a href=
* "https://errorprone.info/docs/flags#pass-additional-info-to-bugcheckers">namespaced
* check options</a> to their value.
* <p>
* Use an explicit {@code "true"} value for a boolean option.
* <p>
* Maps each entry to {@code -XepOpt:<namespace>:<key>=<value>}.
*/
@Parameter
private Map<String, Map<String, String>> namespacedOptions = new HashMap<>();
/**
* Additional arguments passed to Error Prone.
*/
@Parameter(property = "errorprone.arguments")
private List<String> arguments = new ArrayList<>();
/**
* The name of the {@link MavenProject#getProperties() project property} which
* will be set to the generated compiler argument (the value will be of the form
* {@code -Xplugin:ErrorProne <options>}).
*/
@Parameter(defaultValue = "errorprone.compile.argument")
private String propertyName;
@Inject
private MavenProject project;
@Inject
private CompilerConfiguration compilerConfiguration;
@Override
public void execute() throws MojoExecutionException {
String propertyValue = "";
if (enabled) {
List<String> flags = getFlags();
propertyValue = "-Xplugin:ErrorProne " + String.join(" ", flags);
}
getLog().debug("Setting project property \"" + propertyName + "\" to \"" + propertyValue + "\".");
project.getProperties().put(propertyName, propertyValue);
if (enabled) {
compilerConfiguration.configure(project, propertyName);
}
}
private List<String> getFlags() throws MojoExecutionException {
List<String> flags = new ArrayList<>();
maybeAddOption(flags, "-XepDisableAllChecks", disableAllChecks);
maybeAddOption(flags, "-XepDisableAllWarnings", disableAllWarnings);
maybeAddOption(flags, "-XepAllErrorsAsWarnings", allErrorsAsWarnings);
maybeAddOption(flags, "-XepAllSuggestionsAsWarnings", allSuggestionsAsWarnings);
maybeAddOption(flags, "-XepAllDisabledChecksAsWarnings", allDisabledChecksAsWarnings);
maybeAddOption(flags, "-XepDisableWarningsInGeneratedCode", disableWarningsInGeneratedCode);
maybeAddOption(flags, "-XepIgnoreUnknownCheckNames", ignoreUnknownCheckNames);
maybeAddOption(flags, "-XepIgnoreSuppressionAnnotations", ignoreSuppressionAnnotations);
maybeAddOption(flags, "-XepCompilingTestOnlyCode", isCompilingTestOnlyCode());
maybeAddOption(flags, "-XepExcludedPaths", excludePaths);
for (var entry : checks.entrySet()) {
validateName(entry.getKey());
String option = "-Xep:" + entry.getKey();
if (entry.getValue() != CheckSeverity.DEFAULT) {
option += ":" + entry.getValue().name();
}
flags.add(option);
}
for (var namespacedEntry : this.namespacedOptions.entrySet()) {
for (var entry : namespacedEntry.getValue().entrySet()) {
flags.add("-XepOpt:" + namespacedEntry.getKey() + ":" + entry.getKey() + "=" + entry.getValue());
}
}
for (var entry : this.options.entrySet()) {
flags.add("-XepOpt:" + entry.getKey() + "=" + entry.getValue());
}
flags.addAll(arguments);
return flags;
}
private void validateName(String checkName) throws MojoExecutionException {
if (checkName.contains(":")) {
throw new MojoExecutionException(
String.format("Error Prone check name cannot contain a colon (\":\"): \"%s\".", checkName));
}
}
private void maybeAddOption(List<String> options, String option, boolean value) {
if (value) {
options.add(option);
}
}
private void maybeAddOption(List<String> options, String option, String value) {
if (value != null && !value.isBlank()) {
options.add(option + ":" + value);
}
}
protected abstract boolean isCompilingTestOnlyCode();
}