Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for different output formats and add codeclimate as an output format #235

Merged
merged 3 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,21 @@ documents all of these. The most commonly used flags:
* `-Dmodernizer.failOnViolations` - fail phase if violations detected, defaults to true
* `-Dmodernizer.skip` - skip plugin execution, defaults to false

### Output Formats

The plugin can output Modernizer violations in one of many formats which can be configured with the `<configuration>`
stanza using `<outputFormat>`.

The currently supported formats and their respective configuration options are outlined below:
* `CONSOLE` List each violation using Maven's logger. This is the **default** format.
* `<violationLogLevel>` Specify the log level of the logger: `error`, `warn`, `info` or `debug`.
Default is `error`.
* `CODE_CLIMATE` Write the violations according to [Code Climate's Spec](https://github.com/codeclimate/platform/blob/master/spec/analyzers/SPEC.md).
GitLab uses this format for its code quality as shown [here](https://docs.gitlab.com/ee/ci/testing/code_quality.html#implement-a-custom-tool).
* `<outputFile>` The full path the file to output to. Default is `${project.build.directory}/code-quality.json`
* `<codeClimateSeverity>` Severity of Modernizer violations for CodeClimate: `INFO`, `MINOR`, `MAJOR`, `CRITIAL` or `BLOCKER`.
gaul marked this conversation as resolved.
Show resolved Hide resolved
Default is `MINOR`.

Ignoring elements
-----------------

Expand Down
5 changes: 5 additions & 0 deletions modernizer-maven-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@
<artifactId>plexus-utils</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
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 java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
Expand All @@ -41,6 +43,11 @@
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.gaul.modernizer_maven_plugin.output.CodeClimateOutputer;
import org.gaul.modernizer_maven_plugin.output.LoggerOutputer;
import org.gaul.modernizer_maven_plugin.output.OutputEntry;
import org.gaul.modernizer_maven_plugin.output.OutputFormat;
import org.gaul.modernizer_maven_plugin.output.Outputer;
import org.xml.sax.SAXException;

@Mojo(name = "modernizer", defaultPhase = LifecyclePhase.PROCESS_TEST_CLASSES,
Expand Down Expand Up @@ -121,8 +128,30 @@ public final class ModernizerMojo extends AbstractMojo {
@Parameter(property = "modernizer.exclusionsFile")
private String exclusionsFile;

/**
* Format to output violations in.
*/
@Parameter(defaultValue = "CONSOLE", property = "modernizer.outputFormat")
private OutputFormat outputFormat;

/**
* Path to the file to output violations to.
* Ignored if {@code modernizer.outputFormat} is {@code CONSOLE}.
*/
@Parameter(property = "modernizer.outputFile")
private String outputFile;

/**
* Severity of modernizer violations for CodeClimate.
* Ignored if {@code modernizer.outputFormat} is not {@code CODECLIMATE}.
*/
@Parameter(defaultValue = "MINOR",
property = "modernizer.codeclimateSeverity")
private CodeClimateOutputer.Severity codeClimateSeverity;

/**
* Log level to emit violations at, e.g., error, warn, info, debug.
* Ignored if {@code modernizer.outputFormat} is not {@code CONSOLE}.
*/
@Parameter(defaultValue = "error",
property = "modernizer.violationLogLevel")
Expand Down Expand Up @@ -181,6 +210,8 @@ public final class ModernizerMojo extends AbstractMojo {
@Parameter(defaultValue = "false", property = "modernizer.skip")
protected boolean skip = false;

private List<OutputEntry> outputEntries = new ArrayList<>();

@Override
public void execute() throws MojoExecutionException {
if (skip) {
Expand Down Expand Up @@ -268,18 +299,27 @@ public void execute() throws MojoExecutionException {
allExclusionPatterns, ignorePackages,
ignoreClassNames, allIgnoreFullClassNamePatterns);

long count;
try {
long count = recurseFiles(outputDirectory);
count = recurseFiles(outputDirectory);
if (includeTestClasses) {
count += recurseFiles(testOutputDirectory);
}
if (failOnViolations && count != 0) {
throw new MojoExecutionException("Found " + count +
" violations");
}
} catch (IOException ioe) {
throw new MojoExecutionException("Error reading Java classes", ioe);
}

try {
buildOutputer().output(outputEntries);
} catch (IOException ioe) {
throw new MojoExecutionException(
"Error outputting violations", ioe);
}

if (failOnViolations && count != 0) {
throw new MojoExecutionException("Found " + count +
" violations");
}
}

private static Map<String, Violation> parseViolations(
Expand Down Expand Up @@ -374,7 +414,7 @@ private long recurseFiles(File file) throws IOException {
name = name.substring(0,
name.length() - ".class".length()) + ".java";
}
emitViolation(name, occurrence);
outputEntries.add(new OutputEntry(name, occurrence));
++count;
}
} finally {
Expand All @@ -384,21 +424,16 @@ private long recurseFiles(File file) throws IOException {
return count;
}

private void emitViolation(String name, ViolationOccurrence occurrence) {
String message = name + ":" +
occurrence.getLineNumber() + ": " +
occurrence.getViolation().getComment();
if (violationLogLevel.equals("error")) {
getLog().error(message);
} else if (violationLogLevel.equals("warn")) {
getLog().warn(message);
} else if (violationLogLevel.equals("info")) {
getLog().info(message);
} else if (violationLogLevel.equals("debug")) {
getLog().debug(message);
} else {
throw new IllegalStateException("unexpected log level, was: " +
violationLogLevel);
private Outputer buildOutputer() throws MojoExecutionException {
String baseDir = project.getBuild().getDirectory();
if (Objects.requireNonNull(outputFormat) == OutputFormat.CONSOLE) {
return new LoggerOutputer(getLog(), violationLogLevel);
} else if (outputFormat == OutputFormat.CODE_CLIMATE) {
return new CodeClimateOutputer(
baseDir + "/" + CodeClimateOutputer.DEFAULT_FILENAME,
codeClimateSeverity);
}
throw new MojoExecutionException(
"Invalid output format: " + outputFormat);
}
}
Loading
Loading