diff options
Diffstat (limited to 'org.jacoco.cli/src/org/jacoco/cli/internal/commands/Report.java')
-rw-r--r-- | org.jacoco.cli/src/org/jacoco/cli/internal/commands/Report.java | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Report.java b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Report.java new file mode 100644 index 00000000..eaa78842 --- /dev/null +++ b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Report.java @@ -0,0 +1,174 @@ +/******************************************************************************* + * Copyright (c) 2009, 2017 Mountainminds GmbH & Co. KG and Contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * John Keeping - initial implementation + * Marc R. Hoffmann - rework + * + *******************************************************************************/ +package org.jacoco.cli.internal.commands; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.jacoco.cli.internal.Command; +import org.jacoco.core.analysis.Analyzer; +import org.jacoco.core.analysis.CoverageBuilder; +import org.jacoco.core.analysis.IBundleCoverage; +import org.jacoco.core.analysis.IClassCoverage; +import org.jacoco.core.data.ExecutionDataStore; +import org.jacoco.core.tools.ExecFileLoader; +import org.jacoco.report.DirectorySourceFileLocator; +import org.jacoco.report.FileMultiReportOutput; +import org.jacoco.report.IReportVisitor; +import org.jacoco.report.ISourceFileLocator; +import org.jacoco.report.MultiReportVisitor; +import org.jacoco.report.MultiSourceFileLocator; +import org.jacoco.report.csv.CSVFormatter; +import org.jacoco.report.html.HTMLFormatter; +import org.jacoco.report.xml.XMLFormatter; +import org.kohsuke.args4j.Argument; +import org.kohsuke.args4j.Option; + +/** + * The <code>report</code> command. + */ +public class Report extends Command { + + @Argument(usage = "list of JaCoCo *.exec files to read", metaVar = "<execfiles>") + List<File> execfiles = new ArrayList<File>(); + + @Option(name = "--classfiles", usage = "location of Java class files", metaVar = "<path>", required = true) + List<File> classfiles = new ArrayList<File>(); + + @Option(name = "--sourcefiles", usage = "location of the source files", metaVar = "<path>") + List<File> sourcefiles = new ArrayList<File>(); + + @Option(name = "--tabwith", usage = "tab stop width for the source pages (default 4)", metaVar = "<n>") + int tabwidth = 4; + + @Option(name = "--name", usage = "name used for this report", metaVar = "<name>") + String name = "JaCoCo Coverage Report"; + + @Option(name = "--encoding", usage = "source file encoding (by default platform encoding is used)", metaVar = "<charset>") + String encoding; + + @Option(name = "--xml", usage = "output file for the XML report", metaVar = "<file>") + File xml; + + @Option(name = "--csv", usage = "output file for the CSV report", metaVar = "<file>") + File csv; + + @Option(name = "--html", usage = "output directory for the HTML report", metaVar = "<dir>") + File html; + + @Override + public String description() { + return "Generate reports in different formats by reading exec and Java class files."; + } + + @Override + public int execute(final PrintWriter out, final PrintWriter err) + throws IOException { + final ExecFileLoader loader = loadExecutionData(out); + final IBundleCoverage bundle = analyze(loader.getExecutionDataStore(), + out); + writeReports(bundle, loader, out); + return 0; + } + + private ExecFileLoader loadExecutionData(final PrintWriter out) + throws IOException { + final ExecFileLoader loader = new ExecFileLoader(); + if (execfiles.isEmpty()) { + out.println("[WARN] No execution data files provided."); + } else { + for (final File file : execfiles) { + out.printf("[INFO] Loading execution data file %s.%n", + file.getAbsolutePath()); + loader.load(file); + } + } + return loader; + } + + private IBundleCoverage analyze(final ExecutionDataStore data, + final PrintWriter out) throws IOException { + final CoverageBuilder builder = new CoverageBuilder(); + final Analyzer analyzer = new Analyzer(data, builder); + for (final File f : classfiles) { + analyzer.analyzeAll(f); + } + printNoMatchWarning(builder.getNoMatchClasses(), out); + return builder.getBundle(name); + } + + private void printNoMatchWarning(final Collection<IClassCoverage> nomatch, + final PrintWriter out) { + if (!nomatch.isEmpty()) { + out.println( + "[WARN] Some classes do not match with execution data."); + out.println( + "[WARN] For report generation the same class files must be used as at runtime."); + for (final IClassCoverage c : nomatch) { + out.printf( + "[WARN] Execution data for class %s does not match.%n", + c.getName()); + } + } + } + + private void writeReports(final IBundleCoverage bundle, + final ExecFileLoader loader, final PrintWriter out) + throws IOException { + out.printf("[INFO] Analyzing %s classes.%n", + Integer.valueOf(bundle.getClassCounter().getTotalCount())); + final IReportVisitor visitor = createReportVisitor(); + visitor.visitInfo(loader.getSessionInfoStore().getInfos(), + loader.getExecutionDataStore().getContents()); + visitor.visitBundle(bundle, getSourceLocator()); + visitor.visitEnd(); + } + + private IReportVisitor createReportVisitor() + throws IOException, IOException { + final List<IReportVisitor> visitors = new ArrayList<IReportVisitor>(); + + if (xml != null) { + final XMLFormatter formatter = new XMLFormatter(); + visitors.add(formatter.createVisitor(new FileOutputStream(xml))); + } + + if (csv != null) { + final CSVFormatter formatter = new CSVFormatter(); + visitors.add(formatter.createVisitor(new FileOutputStream(csv))); + } + + if (html != null) { + final HTMLFormatter formatter = new HTMLFormatter(); + visitors.add( + formatter.createVisitor(new FileMultiReportOutput(html))); + } + + return new MultiReportVisitor(visitors); + } + + private ISourceFileLocator getSourceLocator() { + final MultiSourceFileLocator multi = new MultiSourceFileLocator( + tabwidth); + for (final File f : sourcefiles) { + multi.add(new DirectorySourceFileLocator(f, encoding, tabwidth)); + } + return multi; + } + +} |