Skip to content
Merged
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,88 @@
package io.github.finoid.maven.plugins.codequality.report;

import io.github.finoid.maven.plugins.codequality.ExecutionContext;
import io.github.finoid.maven.plugins.codequality.filter.Violations;
import org.apache.maven.plugin.logging.Log;

import java.util.List;
import java.util.Locale;

/**
* A base for console-based {@link ViolationReporter} implementations.
*
* <p>Handles what every console reporter does the same way: splitting the violations into permissive and
* non-permissive groups, emitting the header of each group, and choosing the log level the group is reported at.
* Subclasses decide how the violations themselves are rendered, through {@link #logViolations}.
*/
abstract class AbstractConsoleViolationReporter implements ViolationReporter {
protected static final String GREEN = "\u001B[32m";
protected static final String YELLOW = "\u001B[33m";
protected static final String RESET = "\u001B[0m";

/**
* Reports the collected violations by grouping them into permissive and non-permissive categories,
* and logs each group with formatting and category-based log levels.
*
* @param context the context of the current mojo execution
* @param violations the results of executed code analysis steps containing violations
*/
@Override
public void report(final ExecutionContext context, final Violations violations) {
final Log log = context.getLog();

logViolationsForType(log, violations.getPermissiveViolations(), PermissiveType.PERMISSIVE);
logViolationsForType(log, violations.getNonPermissiveViolations(), PermissiveType.NON_PERMISSIVE);
}

/**
* Renders and logs a group of violations. The header of the group has already been logged.
*
* @param log the log of the current mojo execution
* @param violations the violations of the group, never empty
* @param permissiveType the category the violations belong to
*/
protected abstract void logViolations(final Log log, final List<Violation> violations, final PermissiveType permissiveType);

/**
* Logs the message as a warning for non-permissive violations, and as info otherwise.
*
* @param log the log of the current mojo execution
* @param permissiveType the category the message relates to
* @param message the message to log
*/
protected static void logWithLevel(final Log log, final PermissiveType permissiveType, final String message) {
if (permissiveType == PermissiveType.NON_PERMISSIVE) {
log.warn(message);
} else {
log.info(message);
}
}

private void logViolationsForType(final Log log, final List<Violation> violations, final PermissiveType permissiveType) {
if (violations.isEmpty()) {
log.info(String.format("✅ %s ##### No %s violations found ##### %s ✅ ", GREEN, permissiveType.displayName(), RESET));
return;
}

final String message = String.format("%s ##### found %d %s violations ##### %s",
(permissiveType == PermissiveType.NON_PERMISSIVE) ? YELLOW : GREEN,
violations.size(),
permissiveType.displayName(),
RESET
);

logWithLevel(log, permissiveType, (permissiveType == PermissiveType.NON_PERMISSIVE ? "⚠ " : "✅ ") + message);

logViolations(log, violations, permissiveType);
}

protected enum PermissiveType {
PERMISSIVE,
NON_PERMISSIVE;

String displayName() {
return name().replace('_', ' ')
.toLowerCase(Locale.ROOT);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package io.github.finoid.maven.plugins.codequality.report;

import io.github.finoid.maven.plugins.codequality.ExecutionContext;
import io.github.finoid.maven.plugins.codequality.filter.Violations;
import io.github.finoid.maven.plugins.codequality.log.ViolationLinkableConsoleLogger;
import io.github.finoid.maven.plugins.codequality.util.Precondition;
import org.apache.maven.plugin.logging.Log;
Expand All @@ -10,7 +8,6 @@
import javax.inject.Named;
import javax.inject.Singleton;
import java.util.List;
import java.util.Locale;

/**
* A plain console-based implementation of {@link ViolationReporter} that logs code quality violations
Expand All @@ -21,74 +18,23 @@
*/
@Named("console-plain")
@Singleton
public class ConsolePlainViolationReporter implements ViolationReporter {
public class ConsolePlainViolationReporter extends AbstractConsoleViolationReporter {
public static final String NAME = "CONSOLE_PLAIN";

private static final String GREEN = "\u001B[32m";
private static final String YELLOW = "\u001B[33m";
private static final String RESET = "\u001B[0m";

private final ViolationLinkableConsoleLogger violationLinkableConsoleLogger;

@Inject
public ConsolePlainViolationReporter(final ViolationLinkableConsoleLogger violationLinkableConsoleLogger) {
this.violationLinkableConsoleLogger = Precondition.nonNull(violationLinkableConsoleLogger, "ViolationLinkableConsoleLogger shouldn't be null");
}

/**
* Reports all violations of at least {@link Severity#MINOR} level by grouping them
* into permissive and non-permissive categories, and logs each group with formatting
* and severity-based log levels.
*
* @param context the context of the current mojo execution
* @param violations the results of executed code analysis steps containing violations
*/
@Override
public void report(final ExecutionContext context, final Violations violations) {
final Log log = context.getLog();

logViolationsForType(log, violations.getPermissiveViolations(), PermissiveType.PERMISSIVE);
logViolationsForType(log, violations.getNonPermissiveViolations(), PermissiveType.NON_PERMISSIVE);
}

@Override
public String name() {
return NAME;
}

private void logViolationsForType(final Log log, final List<Violation> violations, final PermissiveType permissiveType) {
if (violations.isEmpty()) {
log.info(String.format("✅ %s ##### No %s violations found ##### %s ✅ ", GREEN, permissiveType.displayName(), RESET));
return;
}

final String message = String.format("%s ##### found %d %s violations ##### %s",
(permissiveType == PermissiveType.NON_PERMISSIVE) ? YELLOW : GREEN,
violations.size(),
permissiveType.displayName(),
RESET
);

logWithLevel(log, permissiveType, (permissiveType == PermissiveType.NON_PERMISSIVE ? "⚠ " : "✅ ") + message);

violations.forEach(v -> logWithLevel(log, permissiveType, violationLinkableConsoleLogger.format(v)));
}

private static void logWithLevel(final Log log, final PermissiveType permissiveType, final String message) {
if (permissiveType == PermissiveType.NON_PERMISSIVE) {
log.warn(message);
} else {
log.info(message);
}
}

private enum PermissiveType {
PERMISSIVE,
NON_PERMISSIVE;

private String displayName() {
return name().replace('_', ' ')
.toLowerCase(Locale.ROOT);
}
@Override
protected void logViolations(final Log log, final List<Violation> violations, final PermissiveType permissiveType) {
violations.forEach(it -> logWithLevel(log, permissiveType, violationLinkableConsoleLogger.format(it)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,11 @@
import de.vandermeer.asciitable.CWC_LongestLine;
import de.vandermeer.asciithemes.TA_GridThemes;
import de.vandermeer.skb.interfaces.transformers.textformat.TextAlignment;
import io.github.finoid.maven.plugins.codequality.ExecutionContext;
import io.github.finoid.maven.plugins.codequality.filter.Violations;
import org.apache.maven.plugin.logging.Log;

import javax.inject.Named;
import javax.inject.Singleton;
import java.util.List;
import java.util.Locale;

/**
* A table console-based implementation of {@link ViolationReporter} that logs code quality violations
Expand All @@ -22,35 +19,30 @@
*/
@Named("console-table")
@Singleton
public class ConsoleTableViolationReporter implements ViolationReporter {
public class ConsoleTableViolationReporter extends AbstractConsoleViolationReporter {
public static final String NAME = "CONSOLE_TABLE";

private static final String GREEN = "\u001B[32m";
private static final String YELLOW = "\u001B[33m";
private static final String RESET = "\u001B[0m";

/**
* Reports all violations of at least {@link Severity#MINOR} level by grouping them
* into permissive and non-permissive categories, and logs each group with formatting
* and severity-based log levels.
*
* @param context the context of the current mojo execution
* @param violations the results of executed code analysis steps containing violations
* The width, in characters, the table is rendered at.
*/
@Override
public void report(final ExecutionContext context, final Violations violations) {
final Log log = context.getLog();
private static final int TABLE_WIDTH = 200;

logViolationsForType(log, violations.getPermissiveViolations(), PermissiveType.PERMISSIVE);
logViolationsForType(log, violations.getNonPermissiveViolations(), PermissiveType.NON_PERMISSIVE);
}
/**
* The padding, in characters, on either side of every cell.
*/
private static final int CELL_PADDING = 1;

@Override
public String name() {
return NAME;
}

private String renderTable(final List<Violation> violations) {
@Override
protected void logViolations(final Log log, final List<Violation> violations, final PermissiveType permissiveType) {
logWithLevel(log, permissiveType, System.lineSeparator() + renderTable(violations));
}

private static String renderTable(final List<Violation> violations) {
final AsciiTable table = new AsciiTable();

// Add the header
Expand All @@ -60,8 +52,6 @@ private String renderTable(final List<Violation> violations) {

// Add each individual violation as a row
violations.forEach(it -> {
table.setPadding(1);

table.addRow(
it.getTool(),
it.getRule(),
Expand All @@ -71,56 +61,23 @@ private String renderTable(final List<Violation> violations) {
table.addRule();
});

// Applies to the rows added so far, so it has to happen once every row is in place
table.setPadding(CELL_PADDING);
table.setTextAlignment(TextAlignment.LEFT);
table.getContext().setGridTheme(TA_GridThemes.FULL);
table.getContext()
.setGridTheme(TA_GridThemes.FULL);

final CWC_LongestLine cwc = new CWC_LongestLine();
table.getRenderer()
.setCWC(cwc);

// Override specific column width ratios (relative percentages)
cwc.add(10, 15) // Type
// Override the minimum and maximum width of each column
cwc.add(10, 15) // Tool
.add(20, 20) // Rule
.add(40, 60) // Description!)
.add(40, 60) // Description
.add(25, 50) // Path
.add(12, 20); // Column number

return table.render(200);
}

private void logViolationsForType(final Log log, final List<Violation> violations, final PermissiveType permissiveType) {
if (violations.isEmpty()) {
log.info(String.format("✅ %s ##### No %s violations found ##### %s ✅ ", GREEN, permissiveType.displayName(), RESET));
return;
}

final String message = String.format("%s ##### found %d %s violations ##### %s",
(permissiveType == PermissiveType.NON_PERMISSIVE) ? YELLOW : GREEN,
violations.size(),
permissiveType.displayName(),
RESET
);

logWithLevel(log, permissiveType, (permissiveType == PermissiveType.NON_PERMISSIVE ? "⚠ " : "✅ ") + message);

log.info(System.lineSeparator() + renderTable(violations));
}

private static void logWithLevel(final Log log, final PermissiveType permissiveType, final String message) {
if (permissiveType == PermissiveType.NON_PERMISSIVE) {
log.warn(message);
} else {
log.info(message);
}
}

private enum PermissiveType {
PERMISSIVE,
NON_PERMISSIVE;
.add(12, 20); // Line/Column number

private String displayName() {
return name().replace('_', ' ')
.toLowerCase(Locale.ROOT);
}
return table.render(TABLE_WIDTH);
}
}
Loading
Loading