| /******************************************************************************* |
| * Copyright (c) 2009, 2018 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; |
| } |
| |
| } |