[llvm] r321815 - [llvm-cov] Refactor "export" command implementation and add support for SOURCES.

Max Moroz via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 4 11:33:29 PST 2018


Author: dor1s
Date: Thu Jan  4 11:33:29 2018
New Revision: 321815

URL: http://llvm.org/viewvc/llvm-project?rev=321815&view=rev
Log:
[llvm-cov] Refactor "export" command implementation and add support for SOURCES.

Summary: Define an interface for Exporter + split JSON exporter into .h and .cpp.

Reviewers: vsk, morehouse

Reviewed By: vsk

Subscribers: llvm-commits, Dor1s, kcc

Differential Revision: https://reviews.llvm.org/D41600

Added:
    llvm/trunk/tools/llvm-cov/CoverageExporter.h
    llvm/trunk/tools/llvm-cov/CoverageExporterJson.h
Modified:
    llvm/trunk/docs/CommandGuide/llvm-cov.rst
    llvm/trunk/test/tools/llvm-cov/sources-specified.test
    llvm/trunk/tools/llvm-cov/CodeCoverage.cpp
    llvm/trunk/tools/llvm-cov/CoverageExporterJson.cpp
    llvm/trunk/tools/llvm-cov/CoverageReport.h

Modified: llvm/trunk/docs/CommandGuide/llvm-cov.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CommandGuide/llvm-cov.rst?rev=321815&r1=321814&r2=321815&view=diff
==============================================================================
--- llvm/trunk/docs/CommandGuide/llvm-cov.rst (original)
+++ llvm/trunk/docs/CommandGuide/llvm-cov.rst Thu Jan  4 11:33:29 2018
@@ -361,14 +361,15 @@ EXPORT COMMAND
 SYNOPSIS
 ^^^^^^^^
 
-:program:`llvm-cov export` [*options*] -instr-profile *PROFILE* *BIN* [*-object BIN,...*] [[*-object BIN*]]
+:program:`llvm-cov export` [*options*] -instr-profile *PROFILE* *BIN* [*-object BIN,...*] [[*-object BIN*]] [*SOURCES*]
 
 DESCRIPTION
 ^^^^^^^^^^^
 
 The :program:`llvm-cov export` command exports regions, functions, expansions,
 and summaries of the coverage of the binaries *BIN*,... using the profile data
-*PROFILE* as JSON.
+*PROFILE* as JSON. It can optionally be filtered to only export the coverage
+for the files listed in *SOURCES*.
 
 For information on compiling programs for coverage and generating profile data,
 see :ref:`llvm-cov-show`.

Modified: llvm/trunk/test/tools/llvm-cov/sources-specified.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/sources-specified.test?rev=321815&r1=321814&r2=321815&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/sources-specified.test (original)
+++ llvm/trunk/test/tools/llvm-cov/sources-specified.test Thu Jan  4 11:33:29 2018
@@ -20,6 +20,20 @@ SHOW: {{.*}}sources_specified{{.*}}
 SHOW: {{.*}}sources_specified{{.*}}
 SHOW: {{.*}}sources_specified{{.*}}
 
+
+# Test "export" command. Use a temp .json file as output is a single line.
+RUN: llvm-cov export -instr-profile %S/Inputs/sources_specified/main.profdata \
+RUN:   -path-equivalence=/tmp,%S/Inputs \
+RUN:   %S/Inputs/sources_specified/main.covmapping \
+RUN:   %S/Inputs/sources_specified/main.cc %S/Inputs/sources_specified/extra \
+RUN:   > %t.export.json
+
+RUN: not grep '"filename":"/tmp/sources_specified/abs.h"' %t.export.json
+RUN: grep '"filename":"/tmp/sources_specified/main.cc"' %t.export.json
+RUN: grep '"filename":"/tmp/sources_specified/extra/dec.h"' %t.export.json
+RUN: grep '"filename":"/tmp/sources_specified/extra/inc.h"' %t.export.json
+
+
 Instructions for regenerating the test:
 
 # cd %S/Inputs/sources_specified

Modified: llvm/trunk/tools/llvm-cov/CodeCoverage.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CodeCoverage.cpp?rev=321815&r1=321814&r2=321815&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/CodeCoverage.cpp (original)
+++ llvm/trunk/tools/llvm-cov/CodeCoverage.cpp Thu Jan  4 11:33:29 2018
@@ -13,6 +13,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "CoverageExporterJson.h"
 #include "CoverageFilters.h"
 #include "CoverageReport.h"
 #include "CoverageSummaryInfo.h"
@@ -113,14 +114,14 @@ private:
 
   typedef llvm::function_ref<int(int, const char **)> CommandLineParserType;
 
-  int show(int argc, const char **argv,
-           CommandLineParserType commandLineParser);
-
-  int report(int argc, const char **argv,
+  int doShow(int argc, const char **argv,
              CommandLineParserType commandLineParser);
 
-  int export_(int argc, const char **argv,
-              CommandLineParserType commandLineParser);
+  int doReport(int argc, const char **argv,
+               CommandLineParserType commandLineParser);
+
+  int doExport(int argc, const char **argv,
+               CommandLineParserType commandLineParser);
 
   std::vector<StringRef> ObjectFilenames;
   CoverageViewOptions ViewOpts;
@@ -755,17 +756,17 @@ int CodeCoverageTool::run(Command Cmd, i
 
   switch (Cmd) {
   case Show:
-    return show(argc, argv, commandLineParser);
+    return doShow(argc, argv, commandLineParser);
   case Report:
-    return report(argc, argv, commandLineParser);
+    return doReport(argc, argv, commandLineParser);
   case Export:
-    return export_(argc, argv, commandLineParser);
+    return doExport(argc, argv, commandLineParser);
   }
   return 0;
 }
 
-int CodeCoverageTool::show(int argc, const char **argv,
-                           CommandLineParserType commandLineParser) {
+int CodeCoverageTool::doShow(int argc, const char **argv,
+                             CommandLineParserType commandLineParser) {
 
   cl::OptionCategory ViewCategory("Viewing options");
 
@@ -932,8 +933,8 @@ int CodeCoverageTool::show(int argc, con
   return 0;
 }
 
-int CodeCoverageTool::report(int argc, const char **argv,
-                             CommandLineParserType commandLineParser) {
+int CodeCoverageTool::doReport(int argc, const char **argv,
+                               CommandLineParserType commandLineParser) {
   cl::opt<bool> ShowFunctionSummaries(
       "show-functions", cl::Optional, cl::init(false),
       cl::desc("Show coverage summaries for each function"));
@@ -969,8 +970,8 @@ int CodeCoverageTool::report(int argc, c
   return 0;
 }
 
-int CodeCoverageTool::export_(int argc, const char **argv,
-                              CommandLineParserType commandLineParser) {
+int CodeCoverageTool::doExport(int argc, const char **argv,
+                               CommandLineParserType commandLineParser) {
 
   auto Err = commandLineParser(argc, argv);
   if (Err)
@@ -987,7 +988,12 @@ int CodeCoverageTool::export_(int argc,
     return 1;
   }
 
-  exportCoverageDataToJson(*Coverage.get(), ViewOpts, outs());
+  auto Exporter = CoverageExporterJson(*Coverage.get(), ViewOpts, outs());
+
+  if (SourceFiles.empty())
+    Exporter.renderRoot();
+  else
+    Exporter.renderRoot(SourceFiles);
 
   return 0;
 }

Added: llvm/trunk/tools/llvm-cov/CoverageExporter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CoverageExporter.h?rev=321815&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-cov/CoverageExporter.h (added)
+++ llvm/trunk/tools/llvm-cov/CoverageExporter.h Thu Jan  4 11:33:29 2018
@@ -0,0 +1,51 @@
+//===- CoverageExporter.h - Code coverage exporter ------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class defines a code coverage exporter interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_COV_COVERAGEEXPORTER_H
+#define LLVM_COV_COVERAGEEXPORTER_H
+
+#include "CoverageSummaryInfo.h"
+#include "CoverageViewOptions.h"
+#include "llvm/ProfileData/Coverage/CoverageMapping.h"
+
+namespace llvm {
+
+/// \brief Exports the code coverage information.
+class CoverageExporter {
+protected:
+  /// \brief The full CoverageMapping object to export.
+  const coverage::CoverageMapping &Coverage;
+
+  /// \brief The options passed to the tool.
+  const CoverageViewOptions &Options;
+
+  /// \brief Output stream to print JSON to.
+  raw_ostream &OS;
+
+  CoverageExporter(const coverage::CoverageMapping &CoverageMapping,
+                   const CoverageViewOptions &Options, raw_ostream &OS)
+      : Coverage(CoverageMapping), Options(Options), OS(OS) {}
+
+public:
+  virtual ~CoverageExporter(){};
+
+  /// \brief Render the CoverageMapping object.
+  virtual void renderRoot() = 0;
+
+  /// \brief Render the CoverageMapping object for specified source files.
+  virtual void renderRoot(const std::vector<std::string> &SourceFiles) = 0;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_COV_COVERAGEEXPORTER_H

Modified: llvm/trunk/tools/llvm-cov/CoverageExporterJson.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CoverageExporterJson.cpp?rev=321815&r1=321814&r2=321815&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/CoverageExporterJson.cpp (original)
+++ llvm/trunk/tools/llvm-cov/CoverageExporterJson.cpp Thu Jan  4 11:33:29 2018
@@ -41,11 +41,8 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "CoverageExporterJson.h"
 #include "CoverageReport.h"
-#include "CoverageSummaryInfo.h"
-#include "CoverageViewOptions.h"
-#include "llvm/ProfileData/Coverage/CoverageMapping.h"
-#include <stack>
 
 /// \brief The semantic version combined as a string.
 #define LLVM_COVERAGE_EXPORT_JSON_STR "2.0.0"
@@ -54,381 +51,328 @@
 #define LLVM_COVERAGE_EXPORT_JSON_TYPE_STR "llvm.coverage.json.export"
 
 using namespace llvm;
-using namespace coverage;
 
-class CoverageExporterJson {
-  const CoverageViewOptions &Options;
-
-  /// \brief Output stream to print JSON to.
-  raw_ostream &OS;
-
-  /// \brief The full CoverageMapping object to export.
-  const CoverageMapping &Coverage;
-
-  /// \brief States that the JSON rendering machine can be in.
-  enum JsonState { None, NonEmptyElement, EmptyElement };
-
-  /// \brief Tracks state of the JSON output.
-  std::stack<JsonState> State;
-
-  /// \brief Emit a serialized scalar.
-  void emitSerialized(const int64_t Value) { OS << Value; }
-
-  /// \brief Emit a serialized string.
-  void emitSerialized(const std::string &Value) {
-    OS << "\"";
-    for (char C : Value) {
-      if (C != '\\')
-        OS << C;
-      else
-        OS << "\\\\";
-    }
-    OS << "\"";
-  }
-
-  /// \brief Emit a comma if there is a previous element to delimit.
-  void emitComma() {
-    if (State.top() == JsonState::NonEmptyElement) {
-      OS << ",";
-    } else if (State.top() == JsonState::EmptyElement) {
-      State.pop();
-      assert((State.size() >= 1) && "Closed too many JSON elements");
-      State.push(JsonState::NonEmptyElement);
-    }
-  }
-
-  /// \brief Emit a starting dictionary/object character.
-  void emitDictStart() {
-    emitComma();
-    State.push(JsonState::EmptyElement);
-    OS << "{";
-  }
-
-  /// \brief Emit a dictionary/object key but no value.
-  void emitDictKey(const std::string &Key) {
-    emitComma();
-    emitSerialized(Key);
-    OS << ":";
-    State.pop();
-    assert((State.size() >= 1) && "Closed too many JSON elements");
-
-    // We do not want to emit a comma after this key.
-    State.push(JsonState::EmptyElement);
-  }
-
-  /// \brief Emit a dictionary/object key/value pair.
-  template <typename V>
-  void emitDictElement(const std::string &Key, const V &Value) {
-    emitComma();
-    emitSerialized(Key);
-    OS << ":";
-    emitSerialized(Value);
-  }
-
-  /// \brief Emit a closing dictionary/object character.
-  void emitDictEnd() {
-    State.pop();
-    assert((State.size() >= 1) && "Closed too many JSON elements");
-    OS << "}";
-  }
+CoverageExporterJson::CoverageExporterJson(
+    const coverage::CoverageMapping &CoverageMapping,
+    const CoverageViewOptions &Options, raw_ostream &OS)
+    : CoverageExporter(CoverageMapping, Options, OS) {
+  State.push(JsonState::None);
+}
 
-  /// \brief Emit a starting array character.
-  void emitArrayStart() {
-    emitComma();
-    State.push(JsonState::EmptyElement);
-    OS << "[";
-  }
+void CoverageExporterJson::emitSerialized(const int64_t Value) { OS << Value; }
 
-  /// \brief Emit an array element.
-  template <typename V> void emitArrayElement(const V &Value) {
-    emitComma();
-    emitSerialized(Value);
+void CoverageExporterJson::emitSerialized(const std::string &Value) {
+  OS << "\"";
+  for (char C : Value) {
+    if (C != '\\')
+      OS << C;
+    else
+      OS << "\\\\";
   }
+  OS << "\"";
+}
 
-  /// \brief emit a closing array character.
-  void emitArrayEnd() {
+void CoverageExporterJson::emitComma() {
+  if (State.top() == JsonState::NonEmptyElement) {
+    OS << ",";
+  } else if (State.top() == JsonState::EmptyElement) {
     State.pop();
     assert((State.size() >= 1) && "Closed too many JSON elements");
-    OS << "]";
+    State.push(JsonState::NonEmptyElement);
   }
+}
 
-  /// \brief Render the CoverageMapping object.
-  void renderRoot() {
-    // Start Root of JSON object.
-    emitDictStart();
-
-    emitDictElement("version", LLVM_COVERAGE_EXPORT_JSON_STR);
-    emitDictElement("type", LLVM_COVERAGE_EXPORT_JSON_TYPE_STR);
-    emitDictKey("data");
+void CoverageExporterJson::emitDictStart() {
+  emitComma();
+  State.push(JsonState::EmptyElement);
+  OS << "{";
+}
 
-    // Start List of Exports.
-    emitArrayStart();
+void CoverageExporterJson::emitDictKey(const std::string &Key) {
+  emitComma();
+  emitSerialized(Key);
+  OS << ":";
+  State.pop();
+  assert((State.size() >= 1) && "Closed too many JSON elements");
 
-    // Start Export.
-    emitDictStart();
+  // We do not want to emit a comma after this key.
+  State.push(JsonState::EmptyElement);
+}
 
-    emitDictKey("files");
+void CoverageExporterJson::emitDictEnd() {
+  State.pop();
+  assert((State.size() >= 1) && "Closed too many JSON elements");
+  OS << "}";
+}
 
-    FileCoverageSummary Totals = FileCoverageSummary("Totals");
-    std::vector<std::string> SourceFiles;
-    for (StringRef SF : Coverage.getUniqueSourceFiles())
-      SourceFiles.emplace_back(SF);
-    auto FileReports = CoverageReport::prepareFileReports(Coverage, Totals,
-                                                          SourceFiles, Options);
-    renderFiles(SourceFiles, FileReports);
-
-    // Skip functions-level information for summary-only export mode.
-    if (!Options.ExportSummaryOnly) {
-      emitDictKey("functions");
-      renderFunctions(Coverage.getCoveredFunctions());
-    }
+void CoverageExporterJson::emitArrayStart() {
+  emitComma();
+  State.push(JsonState::EmptyElement);
+  OS << "[";
+}
 
-    emitDictKey("totals");
-    renderSummary(Totals);
+void CoverageExporterJson::emitArrayEnd() {
+  State.pop();
+  assert((State.size() >= 1) && "Closed too many JSON elements");
+  OS << "]";
+}
 
-    // End Export.
-    emitDictEnd();
+void CoverageExporterJson::renderRoot() {
+  std::vector<std::string> SourceFiles;
+  for (StringRef SF : Coverage.getUniqueSourceFiles())
+    SourceFiles.emplace_back(SF);
+  renderRoot(SourceFiles);
+}
 
-    // End List of Exports.
-    emitArrayEnd();
+void CoverageExporterJson::renderRoot(
+    const std::vector<std::string> &SourceFiles) {
+  // Start Root of JSON object.
+  emitDictStart();
+
+  emitDictElement("version", LLVM_COVERAGE_EXPORT_JSON_STR);
+  emitDictElement("type", LLVM_COVERAGE_EXPORT_JSON_TYPE_STR);
+  emitDictKey("data");
+
+  // Start List of Exports.
+  emitArrayStart();
+
+  // Start Export.
+  emitDictStart();
+
+  emitDictKey("files");
+
+  FileCoverageSummary Totals = FileCoverageSummary("Totals");
+  auto FileReports = CoverageReport::prepareFileReports(Coverage, Totals,
+                                                        SourceFiles, Options);
+  renderFiles(SourceFiles, FileReports);
 
-    // End Root of JSON Object.
-    emitDictEnd();
-
-    assert((State.top() == JsonState::None) &&
-           "All Elements In JSON were Closed");
+  // Skip functions-level information for summary-only export mode.
+  if (!Options.ExportSummaryOnly) {
+    emitDictKey("functions");
+    renderFunctions(Coverage.getCoveredFunctions());
   }
 
-  /// \brief Render an array of all the given functions.
-  void
-  renderFunctions(const iterator_range<FunctionRecordIterator> &Functions) {
-    // Start List of Functions.
-    emitArrayStart();
+  emitDictKey("totals");
+  renderSummary(Totals);
 
-    for (const auto &Function : Functions) {
-      // Start Function.
-      emitDictStart();
+  // End Export.
+  emitDictEnd();
 
-      emitDictElement("name", Function.Name);
-      emitDictElement("count", Function.ExecutionCount);
-      emitDictKey("regions");
+  // End List of Exports.
+  emitArrayEnd();
 
-      renderRegions(Function.CountedRegions);
+  // End Root of JSON Object.
+  emitDictEnd();
 
-      emitDictKey("filenames");
+  assert((State.top() == JsonState::None) &&
+         "All Elements In JSON were Closed");
+}
 
-      // Start Filenames for Function.
-      emitArrayStart();
+void CoverageExporterJson::renderFunctions(
+    const iterator_range<coverage::FunctionRecordIterator> &Functions) {
+  // Start List of Functions.
+  emitArrayStart();
 
-      for (const auto &FileName : Function.Filenames)
-        emitArrayElement(FileName);
+  for (const auto &Function : Functions) {
+    // Start Function.
+    emitDictStart();
 
-      // End Filenames for Function.
-      emitArrayEnd();
+    emitDictElement("name", Function.Name);
+    emitDictElement("count", Function.ExecutionCount);
+    emitDictKey("regions");
 
-      // End Function.
-      emitDictEnd();
-    }
+    renderRegions(Function.CountedRegions);
 
-    // End List of Functions.
-    emitArrayEnd();
-  }
+    emitDictKey("filenames");
 
-  /// \brief Render an array of all the source files, also pass back a Summary.
-  void renderFiles(ArrayRef<std::string> SourceFiles,
-                   ArrayRef<FileCoverageSummary> FileReports) {
-    // Start List of Files.
+    // Start Filenames for Function.
     emitArrayStart();
 
-    for (unsigned I = 0, E = SourceFiles.size(); I < E; ++I) {
-      // Render the file.
-      auto FileCoverage = Coverage.getCoverageForFile(SourceFiles[I]);
-      renderFile(FileCoverage, FileReports[I]);
-    }
+    for (const auto &FileName : Function.Filenames)
+      emitArrayElement(FileName);
 
-    // End List of Files.
+    // End Filenames for Function.
     emitArrayEnd();
-  }
 
-  /// \brief Render a single file.
-  void renderFile(const CoverageData &FileCoverage,
-                  const FileCoverageSummary &FileReport) {
-    // Start File.
-    emitDictStart();
-
-    emitDictElement("filename", FileCoverage.getFilename());
-
-    // Skip segments and expansions for summary-only export mode.
-    if (!Options.ExportSummaryOnly) {
-      emitDictKey("segments");
-
-      // Start List of Segments.
-      emitArrayStart();
-
-      for (const auto &Segment : FileCoverage)
-        renderSegment(Segment);
-
-      // End List of Segments.
-      emitArrayEnd();
-
-      emitDictKey("expansions");
-
-      // Start List of Expansions.
-      emitArrayStart();
-
-      for (const auto &Expansion : FileCoverage.getExpansions())
-        renderExpansion(Expansion);
-
-      // End List of Expansions.
-      emitArrayEnd();
-    }
-
-    emitDictKey("summary");
-    renderSummary(FileReport);
-
-    // End File.
+    // End Function.
     emitDictEnd();
   }
 
-  /// \brief Render a CoverageSegment.
-  void renderSegment(const CoverageSegment &Segment) {
-    // Start Segment.
-    emitArrayStart();
-
-    emitArrayElement(Segment.Line);
-    emitArrayElement(Segment.Col);
-    emitArrayElement(Segment.Count);
-    emitArrayElement(Segment.HasCount);
-    emitArrayElement(Segment.IsRegionEntry);
+  // End List of Functions.
+  emitArrayEnd();
+}
 
-    // End Segment.
-    emitArrayEnd();
+void CoverageExporterJson::renderFiles(
+    ArrayRef<std::string> SourceFiles,
+    ArrayRef<FileCoverageSummary> FileReports) {
+  // Start List of Files.
+  emitArrayStart();
+
+  for (unsigned I = 0, E = SourceFiles.size(); I < E; ++I) {
+    // Render the file.
+    auto FileCoverage = Coverage.getCoverageForFile(SourceFiles[I]);
+    renderFile(FileCoverage, FileReports[I]);
   }
 
-  /// \brief Render an ExpansionRecord.
-  void renderExpansion(const ExpansionRecord &Expansion) {
-    // Start Expansion.
-    emitDictStart();
+  // End List of Files.
+  emitArrayEnd();
+}
 
-    // Mark the beginning and end of this expansion in the source file.
-    emitDictKey("source_region");
-    renderRegion(Expansion.Region);
-
-    // Enumerate the coverage information for the expansion.
-    emitDictKey("target_regions");
-    renderRegions(Expansion.Function.CountedRegions);
+void CoverageExporterJson::renderFile(
+    const coverage::CoverageData &FileCoverage,
+    const FileCoverageSummary &FileReport) {
+  // Start File.
+  emitDictStart();
+
+  emitDictElement("filename", FileCoverage.getFilename());
+
+  // Skip segments and expansions for summary-only export mode.
+  if (!Options.ExportSummaryOnly) {
+    emitDictKey("segments");
 
-    emitDictKey("filenames");
-    // Start List of Filenames to map the fileIDs.
+    // Start List of Segments.
     emitArrayStart();
-    for (const auto &Filename : Expansion.Function.Filenames)
-      emitArrayElement(Filename);
-    // End List of Filenames.
-    emitArrayEnd();
 
-    // End Expansion.
-    emitDictEnd();
-  }
-
-  /// \brief Render a list of CountedRegions.
-  void renderRegions(ArrayRef<CountedRegion> Regions) {
-    // Start List of Regions.
-    emitArrayStart();
+    for (const auto &Segment : FileCoverage)
+      renderSegment(Segment);
 
-    for (const auto &Region : Regions)
-      renderRegion(Region);
-
-    // End List of Regions.
+    // End List of Segments.
     emitArrayEnd();
-  }
 
-  /// \brief Render a single CountedRegion.
-  void renderRegion(const CountedRegion &Region) {
-    // Start CountedRegion.
+    emitDictKey("expansions");
+
+    // Start List of Expansions.
     emitArrayStart();
 
-    emitArrayElement(Region.LineStart);
-    emitArrayElement(Region.ColumnStart);
-    emitArrayElement(Region.LineEnd);
-    emitArrayElement(Region.ColumnEnd);
-    emitArrayElement(Region.ExecutionCount);
-    emitArrayElement(Region.FileID);
-    emitArrayElement(Region.ExpandedFileID);
-    emitArrayElement(Region.Kind);
+    for (const auto &Expansion : FileCoverage.getExpansions())
+      renderExpansion(Expansion);
 
-    // End CountedRegion.
+    // End List of Expansions.
     emitArrayEnd();
   }
 
-  /// \brief Render a FileCoverageSummary.
-  void renderSummary(const FileCoverageSummary &Summary) {
-    // Start Summary for the file.
-    emitDictStart();
+  emitDictKey("summary");
+  renderSummary(FileReport);
 
-    emitDictKey("lines");
+  // End File.
+  emitDictEnd();
+}
 
-    // Start Line Coverage Summary.
-    emitDictStart();
-    emitDictElement("count", Summary.LineCoverage.getNumLines());
-    emitDictElement("covered", Summary.LineCoverage.getCovered());
-    emitDictElement("percent", Summary.LineCoverage.getPercentCovered());
-    // End Line Coverage Summary.
-    emitDictEnd();
+void CoverageExporterJson::renderSegment(
+    const coverage::CoverageSegment &Segment) {
+  // Start Segment.
+  emitArrayStart();
+
+  emitArrayElement(Segment.Line);
+  emitArrayElement(Segment.Col);
+  emitArrayElement(Segment.Count);
+  emitArrayElement(Segment.HasCount);
+  emitArrayElement(Segment.IsRegionEntry);
 
-    emitDictKey("functions");
+  // End Segment.
+  emitArrayEnd();
+}
 
-    // Start Function Coverage Summary.
-    emitDictStart();
-    emitDictElement("count", Summary.FunctionCoverage.getNumFunctions());
-    emitDictElement("covered", Summary.FunctionCoverage.getExecuted());
-    emitDictElement("percent", Summary.FunctionCoverage.getPercentCovered());
-    // End Function Coverage Summary.
-    emitDictEnd();
+void CoverageExporterJson::renderExpansion(
+    const coverage::ExpansionRecord &Expansion) {
+  // Start Expansion.
+  emitDictStart();
+
+  // Mark the beginning and end of this expansion in the source file.
+  emitDictKey("source_region");
+  renderRegion(Expansion.Region);
+
+  // Enumerate the coverage information for the expansion.
+  emitDictKey("target_regions");
+  renderRegions(Expansion.Function.CountedRegions);
+
+  emitDictKey("filenames");
+  // Start List of Filenames to map the fileIDs.
+  emitArrayStart();
+  for (const auto &Filename : Expansion.Function.Filenames)
+    emitArrayElement(Filename);
+  // End List of Filenames.
+  emitArrayEnd();
 
-    emitDictKey("instantiations");
+  // End Expansion.
+  emitDictEnd();
+}
 
-    // Start Instantiation Coverage Summary.
-    emitDictStart();
-    emitDictElement("count", Summary.InstantiationCoverage.getNumFunctions());
-    emitDictElement("covered", Summary.InstantiationCoverage.getExecuted());
-    emitDictElement("percent",
-                    Summary.InstantiationCoverage.getPercentCovered());
-    // End Function Coverage Summary.
-    emitDictEnd();
+void CoverageExporterJson::renderRegions(
+    ArrayRef<coverage::CountedRegion> Regions) {
+  // Start List of Regions.
+  emitArrayStart();
 
-    emitDictKey("regions");
+  for (const auto &Region : Regions)
+    renderRegion(Region);
 
-    // Start Region Coverage Summary.
-    emitDictStart();
-    emitDictElement("count", Summary.RegionCoverage.getNumRegions());
-    emitDictElement("covered", Summary.RegionCoverage.getCovered());
-    emitDictElement("notcovered",
-                    Summary.RegionCoverage.getNumRegions() -
-                        Summary.RegionCoverage.getCovered());
-    emitDictElement("percent", Summary.RegionCoverage.getPercentCovered());
-    // End Region Coverage Summary.
-    emitDictEnd();
+  // End List of Regions.
+  emitArrayEnd();
+}
 
-    // End Summary for the file.
-    emitDictEnd();
-  }
+void CoverageExporterJson::renderRegion(const coverage::CountedRegion &Region) {
+  // Start CountedRegion.
+  emitArrayStart();
+
+  emitArrayElement(Region.LineStart);
+  emitArrayElement(Region.ColumnStart);
+  emitArrayElement(Region.LineEnd);
+  emitArrayElement(Region.ColumnEnd);
+  emitArrayElement(Region.ExecutionCount);
+  emitArrayElement(Region.FileID);
+  emitArrayElement(Region.ExpandedFileID);
+  emitArrayElement(Region.Kind);
 
-public:
-  CoverageExporterJson(const CoverageMapping &CoverageMapping,
-                       const CoverageViewOptions &Options, raw_ostream &OS)
-      : Options(Options), OS(OS), Coverage(CoverageMapping) {
-    State.push(JsonState::None);
-  }
+  // End CountedRegion.
+  emitArrayEnd();
+}
 
-  /// \brief Print the CoverageMapping.
-  void print() { renderRoot(); }
-};
-
-/// \brief Export the given CoverageMapping to a JSON Format.
-void exportCoverageDataToJson(const CoverageMapping &CoverageMapping,
-                              const CoverageViewOptions &Options,
-                              raw_ostream &OS) {
-  auto Exporter = CoverageExporterJson(CoverageMapping, Options, OS);
+void CoverageExporterJson::renderSummary(const FileCoverageSummary &Summary) {
+  // Start Summary for the file.
+  emitDictStart();
+
+  emitDictKey("lines");
+
+  // Start Line Coverage Summary.
+  emitDictStart();
+  emitDictElement("count", Summary.LineCoverage.getNumLines());
+  emitDictElement("covered", Summary.LineCoverage.getCovered());
+  emitDictElement("percent", Summary.LineCoverage.getPercentCovered());
+  // End Line Coverage Summary.
+  emitDictEnd();
+
+  emitDictKey("functions");
+
+  // Start Function Coverage Summary.
+  emitDictStart();
+  emitDictElement("count", Summary.FunctionCoverage.getNumFunctions());
+  emitDictElement("covered", Summary.FunctionCoverage.getExecuted());
+  emitDictElement("percent", Summary.FunctionCoverage.getPercentCovered());
+  // End Function Coverage Summary.
+  emitDictEnd();
+
+  emitDictKey("instantiations");
+
+  // Start Instantiation Coverage Summary.
+  emitDictStart();
+  emitDictElement("count", Summary.InstantiationCoverage.getNumFunctions());
+  emitDictElement("covered", Summary.InstantiationCoverage.getExecuted());
+  emitDictElement("percent", Summary.InstantiationCoverage.getPercentCovered());
+  // End Function Coverage Summary.
+  emitDictEnd();
+
+  emitDictKey("regions");
+
+  // Start Region Coverage Summary.
+  emitDictStart();
+  emitDictElement("count", Summary.RegionCoverage.getNumRegions());
+  emitDictElement("covered", Summary.RegionCoverage.getCovered());
+  emitDictElement("notcovered", Summary.RegionCoverage.getNumRegions() -
+                                    Summary.RegionCoverage.getCovered());
+  emitDictElement("percent", Summary.RegionCoverage.getPercentCovered());
+  // End Region Coverage Summary.
+  emitDictEnd();
 
-  Exporter.print();
+  // End Summary for the file.
+  emitDictEnd();
 }

Added: llvm/trunk/tools/llvm-cov/CoverageExporterJson.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CoverageExporterJson.h?rev=321815&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-cov/CoverageExporterJson.h (added)
+++ llvm/trunk/tools/llvm-cov/CoverageExporterJson.h Thu Jan  4 11:33:29 2018
@@ -0,0 +1,108 @@
+//===- CoverageExporterJson.h - Code coverage JSON exporter ---------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class implements a code coverage exporter for JSON format.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_COV_COVERAGEEXPORTERJSON_H
+#define LLVM_COV_COVERAGEEXPORTERJSON_H
+
+#include "CoverageExporter.h"
+#include <stack>
+
+namespace llvm {
+
+class CoverageExporterJson : public CoverageExporter {
+  /// \brief States that the JSON rendering machine can be in.
+  enum JsonState { None, NonEmptyElement, EmptyElement };
+
+  /// \brief Tracks state of the JSON output.
+  std::stack<JsonState> State;
+
+  /// \brief Emit a serialized scalar.
+  void emitSerialized(const int64_t Value);
+
+  /// \brief Emit a serialized string.
+  void emitSerialized(const std::string &Value);
+
+  /// \brief Emit a comma if there is a previous element to delimit.
+  void emitComma();
+
+  /// \brief Emit a starting dictionary/object character.
+  void emitDictStart();
+
+  /// \brief Emit a dictionary/object key but no value.
+  void emitDictKey(const std::string &Key);
+
+  /// \brief Emit a dictionary/object key/value pair.
+  template <typename V>
+  void emitDictElement(const std::string &Key, const V &Value) {
+    emitComma();
+    emitSerialized(Key);
+    OS << ":";
+    emitSerialized(Value);
+  }
+
+  /// \brief Emit a closing dictionary/object character.
+  void emitDictEnd();
+
+  /// \brief Emit a starting array character.
+  void emitArrayStart();
+
+  /// \brief Emit an array element.
+  template <typename V> void emitArrayElement(const V &Value) {
+    emitComma();
+    emitSerialized(Value);
+  }
+
+  /// \brief emit a closing array character.
+  void emitArrayEnd();
+
+  /// \brief Render an array of all the given functions.
+  void renderFunctions(
+      const iterator_range<coverage::FunctionRecordIterator> &Functions);
+
+  /// \brief Render an array of all the source files, also pass back a Summary.
+  void renderFiles(ArrayRef<std::string> SourceFiles,
+                   ArrayRef<FileCoverageSummary> FileReports);
+
+  /// \brief Render a single file.
+  void renderFile(const coverage::CoverageData &FileCoverage,
+                  const FileCoverageSummary &FileReport);
+
+  /// \brief Render a CoverageSegment.
+  void renderSegment(const coverage::CoverageSegment &Segment);
+
+  /// \brief Render an ExpansionRecord.
+  void renderExpansion(const coverage::ExpansionRecord &Expansion);
+
+  /// \brief Render a list of CountedRegions.
+  void renderRegions(ArrayRef<coverage::CountedRegion> Regions);
+
+  /// \brief Render a single CountedRegion.
+  void renderRegion(const coverage::CountedRegion &Region);
+
+  /// \brief Render a FileCoverageSummary.
+  void renderSummary(const FileCoverageSummary &Summary);
+
+public:
+  CoverageExporterJson(const coverage::CoverageMapping &CoverageMapping,
+                       const CoverageViewOptions &Options, raw_ostream &OS);
+
+  /// \brief Render the CoverageMapping object.
+  void renderRoot() override;
+
+  /// \brief Render the CoverageMapping object for specified source files.
+  void renderRoot(const std::vector<std::string> &SourceFiles) override;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_COV_COVERAGEEXPORTERJSON_H

Modified: llvm/trunk/tools/llvm-cov/CoverageReport.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CoverageReport.h?rev=321815&r1=321814&r2=321815&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/CoverageReport.h (original)
+++ llvm/trunk/tools/llvm-cov/CoverageReport.h Thu Jan  4 11:33:29 2018
@@ -1,4 +1,4 @@
-//===- CoverageReport.h - Code coverage report ---------------------------===//
+//===- CoverageReport.h - Code coverage report ----------------------------===//
 //
 //                     The LLVM Compiler Infrastructure
 //




More information about the llvm-commits mailing list