aboutsummaryrefslogtreecommitdiff
path: root/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Report.java
diff options
context:
space:
mode:
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.java170
1 files changed, 170 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..be2fbfe4
--- /dev/null
+++ b/org.jacoco.cli/src/org/jacoco/cli/internal/commands/Report.java
@@ -0,0 +1,170 @@
+/*******************************************************************************
+ * 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 (default platform encoding)", 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();
+ 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] Writing report with %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;
+ }
+
+}