com.atlassian.clover.reporters.console.ConsoleReporter.java Source code

Java tutorial

Introduction

Here is the source code for com.atlassian.clover.reporters.console.ConsoleReporter.java

Source

package com.atlassian.clover.reporters.console;

import clover.org.apache.commons.lang3.ArrayUtils;
import com.atlassian.clover.CloverDatabase;
import com.atlassian.clover.CloverLicense;
import com.atlassian.clover.Logger;
import com.atlassian.clover.api.CloverException;
import com.atlassian.clover.api.registry.BranchInfo;
import com.atlassian.clover.api.registry.ClassInfo;
import com.atlassian.clover.api.registry.FileInfo;
import com.atlassian.clover.api.registry.PackageInfo;
import com.atlassian.clover.registry.metrics.ClassMetrics;
import com.atlassian.clover.registry.entities.FullFileInfo;
import com.atlassian.clover.registry.entities.LineInfo;
import com.atlassian.clover.registry.entities.FullMethodInfo;
import com.atlassian.clover.registry.entities.FullPackageInfo;
import com.atlassian.clover.registry.metrics.ProjectMetrics;
import com.atlassian.clover.registry.entities.FullStatementInfo;
import com.atlassian.clover.reporters.CloverReporter;
import com.atlassian.clover.reporters.Format;
import com.atlassian.clover.util.Formatting;
import com.atlassian.clover.util.Color;

import java.io.PrintWriter;
import java.util.Date;
import java.util.List;

import static com.atlassian.clover.reporters.console.ConsoleReporterArgProcessors.*;

public class ConsoleReporter extends CloverReporter {

    static final ArgProcessor[] mandatoryArgProcessors = new ArgProcessor[] { InitString };

    static final ArgProcessor[] optionalArgProcessors = new ArgProcessor[] { CodeTypes, Level, SourcePath, Span,
            ShowInnerFunctions, ShowLambdaFunctions, Title, UnitTests };

    static final ArgProcessor[] allArgProcessors = (ArgProcessor[]) ArrayUtils.addAll(mandatoryArgProcessors,
            optionalArgProcessors);

    /** use to log messages **/
    private static final Logger LOG = Logger.getInstance();

    /** Report settings */
    private final ConsoleReporterConfig cfg;

    public ConsoleReporter(ConsoleReporterConfig cfg) throws CloverException {
        super(cfg.getCoverageDatabase(), cfg);
        this.cfg = cfg;
    }

    public void report(PrintWriter out, CloverDatabase db) {
        out.print("Clover Coverage Report");
        if (cfg.getTitle() != null) {
            out.println(" - " + cfg.getTitle());
        } else {
            out.println();
        }
        out.println("Coverage Timestamp: " + new Date(db.getRecordingTimestamp()));
        out.println("Report for code   : " + cfg.getCodeType());

        List<? extends PackageInfo> packages = db.getModel(cfg.getCodeType()).getAllPackages();
        if (cfg.getLevel().isShowPackages()) {
            out.println();
            out.println("Package Summary - ");
        }

        for (PackageInfo aPackage : packages) {
            FullPackageInfo pkg = (FullPackageInfo) aPackage;
            if (cfg.getPackageSet() != null && !cfg.getPackageSet().contains(pkg.getName())) {
                continue;
            }
            if (cfg.getLevel().isShowPackages()) {
                out.println(
                        pkg.getName() + ": " + Formatting.getPercentStr(pkg.getMetrics().getPcCoveredElements()));
            }

            final List<? extends FileInfo> fileInfos = pkg.getFiles();
            for (FileInfo fileInfo : fileInfos) {
                final FullFileInfo fInfo = (FullFileInfo) fileInfo;

                if (cfg.getLevel().isShowClasses()) {
                    out.println("---------------------------------------");
                    out.println("File: " + fInfo.getPackagePath());

                    final List<? extends ClassInfo> classes = fInfo.getClasses();
                    for (ClassInfo cInfo : classes) {
                        final ClassMetrics metrics = (ClassMetrics) cInfo.getMetrics();
                        out.println("Package: " + cInfo.getPackage().getName());
                        printMetricsSummary(out, "Class: " + cInfo.getName(), metrics, cfg);
                    }
                }

                if (cfg.getLevel().isShowMethods() || cfg.getLevel().isShowStatements()) {
                    final LineInfo[] lines = fInfo.getLineInfo(cfg.isShowLambdaFunctions(),
                            cfg.isShowInnerFunctions());
                    for (LineInfo info : lines) {
                        if (info != null) {
                            if (cfg.getLevel().isShowMethods()) {
                                reportMethodsForLine(out, fInfo, info);
                            }
                            if (cfg.getLevel().isShowStatements()) { // in this case means both statements and branches
                                reportStatementsForLine(out, fInfo, info);
                                reportBranchesForLine(out, fInfo, info);
                            }
                        }
                    }
                }
            }
        }

        out.println();
        out.println();
        ProjectMetrics overview = (ProjectMetrics) db.getModel(cfg.getCodeType()).getMetrics();
        printMetricsSummary(out, "Coverage Overview -", overview, cfg);
        out.flush();
    }

    protected void reportMethodsForLine(final PrintWriter out, final FullFileInfo fInfo, final LineInfo info) {
        final FullMethodInfo[] starts = info.getMethodStarts();
        if (starts.length > 0) {
            for (FullMethodInfo start : starts) {
                if (start.getHitCount() == 0) {
                    out.println(fInfo.getPhysicalFile().getAbsolutePath() + ":" + start.getStartLine() + ":"
                            + start.getStartColumn() + ":" + start.getSimpleName() + ": method not entered.");
                }
            }
        }
    }

    protected void reportStatementsForLine(final PrintWriter out, final FullFileInfo fInfo, final LineInfo info) {
        final FullStatementInfo[] stmts = info.getStatements();
        if (stmts.length > 0) {
            for (FullStatementInfo stmt : stmts) {
                if (stmt.getHitCount() == 0) {
                    out.println(fInfo.getPhysicalFile().getAbsolutePath() + ":" + stmt.getStartLine() + ":"
                            + stmt.getStartColumn() + ": statement not executed.");
                }
            }
        }
    }

    protected void reportBranchesForLine(final PrintWriter out, final FullFileInfo fInfo, final LineInfo info) {
        final BranchInfo[] branches = info.getBranches();
        if (branches.length > 0) {
            for (BranchInfo branch : branches) {
                final String prefix = fInfo.getPhysicalFile().getAbsolutePath() + ":" + branch.getStartLine() + ":"
                        + branch.getStartColumn() + ": ";

                if (!branch.isInstrumented()) {
                    out.println(prefix + "was not instumented, due to assignment in expression.");
                } else if (branch.getTrueHitCount() == 0 && branch.getFalseHitCount() == 0) {
                    out.println(prefix + "branch not evaluated.");
                } else if (branch.getTrueHitCount() == 0) {
                    out.println(prefix + "true branch never taken.");
                } else if (branch.getFalseHitCount() == 0) {
                    out.println(prefix + "false branch never taken.");
                }
            }
        }
    }

    @Override
    protected void validate() throws CloverException {
        super.validate();
    }

    static void printMetricsSummary(PrintWriter out, String title, ClassMetrics metrics,
            ConsoleReporterConfig cfg) {
        out.println(title);
        out.println("Coverage:-");

        final String methodSummary = infoSummaryString(metrics.getNumCoveredMethods(), metrics.getNumMethods(),
                metrics.getPcCoveredMethods());
        final String stmtSummary = infoSummaryString(metrics.getNumCoveredStatements(), metrics.getNumStatements(),
                metrics.getPcCoveredStatements());
        final String branchSummary = infoSummaryString(metrics.getNumCoveredBranches(), metrics.getNumBranches(),
                metrics.getPcCoveredBranches());
        final String totalSummary = Color.make(Formatting.getPercentStr(metrics.getPcCoveredElements())).b()
                .toString();

        out.print("      Methods: " + methodSummary);
        printPcBar(out, methodSummary, metrics.getPcCoveredMethods());
        out.print("   Statements: " + stmtSummary);
        printPcBar(out, stmtSummary, metrics.getPcCoveredStatements());
        out.print("     Branches: " + branchSummary);
        printPcBar(out, branchSummary, metrics.getPcCoveredBranches());
        out.print("        Total: " + totalSummary);
        printPcBar(out, totalSummary, metrics.getPcCoveredElements());

        out.println("Complexity:-");
        out.println("   Avg Method: " + Formatting.format3d(metrics.getAvgMethodComplexity()));
        out.println("      Density: " + Formatting.format3d(metrics.getComplexityDensity()));
        out.println("        Total: " + metrics.getComplexity());

        if ((cfg != null) && (cfg.isShowUnitTests())) {
            out.println("Tests:-");
            out.println("    Available: " + metrics.getNumTests());
            out.println("     Executed: " + metrics.getNumTestsRun());
            out.println("       Passed: " + metrics.getNumTestPasses());
            out.println("       Failed: " + metrics.getNumTestFailures());
            out.println("       Errors: " + metrics.getNumTestErrors());
        }
    }

    private static void printPcBar(PrintWriter out, String summary, float amt) {

        // pad out to 32 spaces from the left.
        int padLen = 32 - summary.length();
        out.print(String.format("%" + (padLen) + "s", " "));

        final int len = 80;
        final int pc = (int) (amt * len);
        for (int i = 0; i <= len; i++) {
            if (i < pc) {
                out.print(Color.make(" ").bg().green());
            } else {
                out.print(Color.make(" ").bg().red());
            }
        }
        out.println();
    }

    private static String infoSummaryString(int covered, int total, float percent) {
        final StringBuilder buf = new StringBuilder();
        buf.append(covered).append("/").append(total);
        buf.append(" (").append(Color.make(Formatting.getPercentStr(percent)).b()).append(")");
        return buf.toString();
    }

    public static void main(String[] args) {
        loadLicense();
        System.exit(runReport(args));
    }

    public static int runReport(String[] args) {
        final ConsoleReporterConfig config = processArgs(args);
        if (canProceedWithReporting(config)) {
            try {
                return new ConsoleReporter(config).execute();
            } catch (Exception e) {
                Logger.getInstance()
                        .error("A problem was encountered while rendering the report: " + e.getMessage(), e);
            }
        }
        return 1;
    }

    public static ConsoleReporterConfig processArgs(String[] args) {
        final ConsoleReporterConfig cfg = new ConsoleReporterConfig();
        cfg.setFormat(Format.DEFAULT_TEXT);
        try {
            int i = 0;

            while (i < args.length) {
                for (ArgProcessor argProcessor : allArgProcessors) {
                    if (argProcessor.matches(args, i)) {
                        i = argProcessor.process(args, i, cfg);
                    }
                }
                i++;
            }

            if (!cfg.validate()) {
                usage(cfg.getValidationFailureReason());
                return null;
            }
        } catch (ArrayIndexOutOfBoundsException e) {
            usage("Missing a parameter.");
            return null;
        }
        return cfg;
    }

    private static void usage(String msg) {
        System.err.println();
        if (msg != null) {
            System.err.println("  *** ERROR: " + msg);
        }
        System.err.println();

        System.err
                .println(buildHelp(ConsoleReporter.class.getName(), mandatoryArgProcessors, optionalArgProcessors));

        System.err.println();
    }

    @Override
    protected int executeImpl() throws CloverException {
        report(new PrintWriter(System.out), database);
        return 0;
    }

}