[llvm] r274029 - [llvm-cov] Create an index of reports in -output-dir mode

Vedant Kumar via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 28 09:12:24 PDT 2016


Author: vedantk
Date: Tue Jun 28 11:12:24 2016
New Revision: 274029

URL: http://llvm.org/viewvc/llvm-project?rev=274029&view=rev
Log:
[llvm-cov] Create an index of reports in -output-dir mode

This index lists the reports available in the 'coverage' sub-directory.
This will help navigate coverage output from large projects.

This commit factors the file creation code out of SourceCoverageView and
into CoveragePrinter.

Modified:
    llvm/trunk/test/tools/llvm-cov/showLineExecutionCounts.cpp
    llvm/trunk/tools/llvm-cov/CodeCoverage.cpp
    llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp
    llvm/trunk/tools/llvm-cov/SourceCoverageView.h
    llvm/trunk/tools/llvm-cov/SourceCoverageViewText.cpp
    llvm/trunk/tools/llvm-cov/SourceCoverageViewText.h

Modified: llvm/trunk/test/tools/llvm-cov/showLineExecutionCounts.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-cov/showLineExecutionCounts.cpp?rev=274029&r1=274028&r2=274029&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-cov/showLineExecutionCounts.cpp (original)
+++ llvm/trunk/test/tools/llvm-cov/showLineExecutionCounts.cpp Tue Jun 28 11:12:24 2016
@@ -34,3 +34,7 @@ int main() {
 // RUN: llvm-cov show %S/Inputs/lineExecutionCounts.covmapping -output-dir %t.dir -instr-profile %t.profdata -filename-equivalence -name=main %s
 // RUN: FileCheck -check-prefixes=CHECK,WHOLE-FILE -input-file %t.dir/coverage/tmp/showLineExecutionCounts.cpp.txt %s
 // RUN: FileCheck -check-prefixes=CHECK,FILTER -input-file %t.dir/functions.txt %s
+//
+// Test index creation.
+// RUN: FileCheck -check-prefix=INDEX -input-file %t.dir/index.txt %s
+// INDEX: showLineExecutionCounts.cpp.txt

Modified: llvm/trunk/tools/llvm-cov/CodeCoverage.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CodeCoverage.cpp?rev=274029&r1=274028&r2=274029&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/CodeCoverage.cpp (original)
+++ llvm/trunk/tools/llvm-cov/CodeCoverage.cpp Tue Jun 28 11:12:24 2016
@@ -448,6 +448,8 @@ int CodeCoverageTool::show(int argc, con
   if (!Coverage)
     return 1;
 
+  auto Printer = CoveragePrinter::create(ViewOpts);
+
   if (!Filters.empty()) {
     // Show functions
     for (const auto &Function : Coverage->getCoveredFunctions()) {
@@ -462,15 +464,14 @@ int CodeCoverageTool::show(int argc, con
         continue;
       }
 
-      auto OSOrErr =
-          mainView->createOutputFile("functions", /*InToplevel=*/true);
+      auto OSOrErr = Printer->createViewFile("functions", /*InToplevel=*/true);
       if (Error E = OSOrErr.takeError()) {
         error(toString(std::move(E)));
         return 1;
       }
       auto OS = std::move(OSOrErr.get());
       mainView->print(*OS.get(), /*WholeFile=*/false, /*ShowSourceName=*/true);
-      mainView->closeOutputFile(std::move(OS));
+      Printer->closeViewFile(std::move(OS));
     }
     return 0;
   }
@@ -483,6 +484,14 @@ int CodeCoverageTool::show(int argc, con
     for (StringRef Filename : Coverage->getUniqueSourceFiles())
       SourceFiles.push_back(Filename);
 
+  // Create an index out of the source files.
+  if (ViewOpts.hasOutputDirectory()) {
+    if (Error E = Printer->createIndexFile(SourceFiles)) {
+      error(toString(std::move(E)));
+      return 1;
+    }
+  }
+
   for (const auto &SourceFile : SourceFiles) {
     auto mainView = createSourceFileView(SourceFile, *Coverage);
     if (!mainView) {
@@ -492,7 +501,7 @@ int CodeCoverageTool::show(int argc, con
       continue;
     }
 
-    auto OSOrErr = mainView->createOutputFile(SourceFile, /*InToplevel=*/false);
+    auto OSOrErr = Printer->createViewFile(SourceFile, /*InToplevel=*/false);
     if (Error E = OSOrErr.takeError()) {
       error(toString(std::move(E)));
       return 1;
@@ -500,7 +509,7 @@ int CodeCoverageTool::show(int argc, con
     auto OS = std::move(OSOrErr.get());
     mainView->print(*OS.get(), /*Wholefile=*/true,
                     /*ShowSourceName=*/ShowFilenames);
-    mainView->closeOutputFile(std::move(OS));
+    Printer->closeViewFile(std::move(OS));
   }
 
   return 0;

Modified: llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp?rev=274029&r1=274028&r2=274029&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp (original)
+++ llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp Tue Jun 28 11:12:24 2016
@@ -21,76 +21,70 @@
 
 using namespace llvm;
 
-std::string SourceCoverageView::formatCount(uint64_t N) {
-  std::string Number = utostr(N);
-  int Len = Number.size();
-  if (Len <= 3)
-    return Number;
-  int IntLen = Len % 3 == 0 ? 3 : Len % 3;
-  std::string Result(Number.data(), IntLen);
-  if (IntLen != 3) {
-    Result.push_back('.');
-    Result += Number.substr(IntLen, 3 - IntLen);
-  }
-  Result.push_back(" kMGTPEZY"[(Len - 1) / 3]);
-  return Result;
-}
-
-void SourceCoverageView::StreamDestructor::operator()(raw_ostream *OS) const {
+void CoveragePrinter::StreamDestructor::operator()(raw_ostream *OS) const {
   if (OS == &outs())
     return;
   delete OS;
 }
 
-/// \brief Create a file at ``Dir/ToplevelDir/@Path.Extension``. If
-/// \p ToplevelDir is empty, its path component is skipped.
-static Expected<SourceCoverageView::OwnedStream>
-createFileInDirectory(StringRef Dir, StringRef ToplevelDir, StringRef Path,
-                      StringRef Extension) {
+std::string CoveragePrinter::getOutputPath(StringRef Path, StringRef Extension,
+                                           bool InToplevel) {
   assert(Extension.size() && "The file extension may not be empty");
 
-  SmallString<256> FullPath(Dir);
-  if (!ToplevelDir.empty())
-    sys::path::append(FullPath, ToplevelDir);
+  SmallString<256> FullPath(Opts.ShowOutputDirectory);
+  if (!InToplevel)
+    sys::path::append(FullPath, getCoverageDir());
 
   auto PathBaseDir = sys::path::relative_path(sys::path::parent_path(Path));
   sys::path::append(FullPath, PathBaseDir);
 
-  if (auto E = sys::fs::create_directories(FullPath))
-    return errorCodeToError(E);
-
   auto PathFilename = (sys::path::filename(Path) + "." + Extension).str();
   sys::path::append(FullPath, PathFilename);
 
-  std::error_code E;
-  auto OS = SourceCoverageView::OwnedStream(
-      new raw_fd_ostream(FullPath, E, sys::fs::F_RW));
-  if (E)
-    return errorCodeToError(E);
-  return std::move(OS);
+  return FullPath.str();
 }
 
-Expected<SourceCoverageView::OwnedStream>
-SourceCoverageView::createOutputStream(const CoverageViewOptions &Opts,
-                                       StringRef Path, StringRef Extension,
-                                       bool InToplevel) {
+Expected<CoveragePrinter::OwnedStream>
+CoveragePrinter::createOutputStream(StringRef Path, StringRef Extension,
+                                    bool InToplevel) {
   if (!Opts.hasOutputDirectory())
     return OwnedStream(&outs());
 
-  return createFileInDirectory(Opts.ShowOutputDirectory,
-                               InToplevel ? "" : "coverage", Path, Extension);
+  std::string FullPath = getOutputPath(Path, Extension, InToplevel);
+
+  auto ParentDir = sys::path::parent_path(FullPath);
+  if (auto E = sys::fs::create_directories(ParentDir))
+    return errorCodeToError(E);
+
+  std::error_code E;
+  raw_ostream *RawStream = new raw_fd_ostream(FullPath, E, sys::fs::F_RW);
+  auto OS = CoveragePrinter::OwnedStream(RawStream);
+  if (E)
+    return errorCodeToError(E);
+  return std::move(OS);
 }
 
-void SourceCoverageView::addExpansion(
-    const coverage::CounterMappingRegion &Region,
-    std::unique_ptr<SourceCoverageView> View) {
-  ExpansionSubViews.emplace_back(Region, std::move(View));
+std::unique_ptr<CoveragePrinter>
+CoveragePrinter::create(const CoverageViewOptions &Opts) {
+  switch (Opts.Format) {
+  case CoverageViewOptions::OutputFormat::Text:
+    return llvm::make_unique<CoveragePrinterText>(Opts);
+  }
 }
 
-void SourceCoverageView::addInstantiation(
-    StringRef FunctionName, unsigned Line,
-    std::unique_ptr<SourceCoverageView> View) {
-  InstantiationSubViews.emplace_back(FunctionName, Line, std::move(View));
+std::string SourceCoverageView::formatCount(uint64_t N) {
+  std::string Number = utostr(N);
+  int Len = Number.size();
+  if (Len <= 3)
+    return Number;
+  int IntLen = Len % 3 == 0 ? 3 : Len % 3;
+  std::string Result(Number.data(), IntLen);
+  if (IntLen != 3) {
+    Result.push_back('.');
+    Result += Number.substr(IntLen, 3 - IntLen);
+  }
+  Result.push_back(" kMGTPEZY"[(Len - 1) / 3]);
+  return Result;
 }
 
 std::unique_ptr<SourceCoverageView>
@@ -105,6 +99,18 @@ SourceCoverageView::create(StringRef Sou
   llvm_unreachable("Unknown coverage output format!");
 }
 
+void SourceCoverageView::addExpansion(
+    const coverage::CounterMappingRegion &Region,
+    std::unique_ptr<SourceCoverageView> View) {
+  ExpansionSubViews.emplace_back(Region, std::move(View));
+}
+
+void SourceCoverageView::addInstantiation(
+    StringRef FunctionName, unsigned Line,
+    std::unique_ptr<SourceCoverageView> View) {
+  InstantiationSubViews.emplace_back(FunctionName, Line, std::move(View));
+}
+
 void SourceCoverageView::print(raw_ostream &OS, bool WholeFile,
                                bool ShowSourceName, unsigned ViewDepth) {
   if (ShowSourceName)

Modified: llvm/trunk/tools/llvm-cov/SourceCoverageView.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/SourceCoverageView.h?rev=274029&r1=274028&r2=274029&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/SourceCoverageView.h (original)
+++ llvm/trunk/tools/llvm-cov/SourceCoverageView.h Tue Jun 28 11:12:24 2016
@@ -97,11 +97,59 @@ struct LineCoverageStats {
   }
 };
 
+/// \brief A file manager that handles format-aware file creation.
+class CoveragePrinter {
+  const CoverageViewOptions &Opts;
+
+public:
+  struct StreamDestructor {
+    void operator()(raw_ostream *OS) const;
+  };
+
+  using OwnedStream = std::unique_ptr<raw_ostream, StreamDestructor>;
+
+protected:
+  CoveragePrinter(const CoverageViewOptions &Opts) : Opts(Opts) {}
+
+  /// \brief Return `OutputDir/ToplevelDir/Path.Extension`.
+  std::string getOutputPath(StringRef Path, StringRef Extension,
+                            bool InToplevel);
+
+  /// \brief If directory output is enabled, create a file in that directory
+  /// at the path given by getOutputPath(). Otherwise, return stdout.
+  Expected<OwnedStream> createOutputStream(StringRef Path, StringRef Extension,
+                                           bool InToplevel);
+
+  /// \brief Return the sub-directory name for file coverage reports.
+  static StringRef getCoverageDir() { return "coverage"; }
+
+public:
+  static std::unique_ptr<CoveragePrinter>
+  create(const CoverageViewOptions &Opts);
+
+  virtual ~CoveragePrinter() {}
+
+  /// @name File Creation Interface
+  /// @{
+
+  /// \brief Create a file to print a coverage view into.
+  virtual Expected<OwnedStream> createViewFile(StringRef Path,
+                                               bool InToplevel) = 0;
+
+  /// \brief Close a file which has been used to print a coverage view.
+  virtual void closeViewFile(OwnedStream OS) = 0;
+
+  /// \brief Create an index which lists reports for the given source files.
+  virtual Error createIndexFile(ArrayRef<StringRef> SourceFiles) = 0;
+
+  /// @}
+};
+
 /// \brief A code coverage view of a source file or function.
 ///
 /// A source coverage view and its nested sub-views form a file-oriented
 /// representation of code coverage data. This view can be printed out by a
-/// renderer which implements both the File Creation and Rendering interfaces.
+/// renderer which implements the Rendering Interface.
 class SourceCoverageView {
   /// A function or file name.
   StringRef SourceName;
@@ -122,25 +170,6 @@ class SourceCoverageView {
   /// on display.
   std::vector<InstantiationView> InstantiationSubViews;
 
-public:
-  struct StreamDestructor {
-    void operator()(raw_ostream *OS) const;
-  };
-
-  using OwnedStream = std::unique_ptr<raw_ostream, StreamDestructor>;
-
-  /// @name File Creation Interface
-  /// @{
-
-  /// \brief Create a file to print a coverage view into.
-  virtual Expected<OwnedStream> createOutputFile(StringRef Path,
-                                                 bool InToplevel) = 0;
-
-  /// \brief Close a file which has been used to print a coverage view.
-  virtual void closeOutputFile(OwnedStream OS) = 0;
-
-  /// @}
-
 protected:
   struct LineRef {
     StringRef Line;
@@ -202,12 +231,6 @@ protected:
   /// digits.
   static std::string formatCount(uint64_t N);
 
-  /// \brief If directory output is enabled, create a file with \p Path as the
-  /// suffix. Otherwise, return stdout.
-  static Expected<OwnedStream>
-  createOutputStream(const CoverageViewOptions &Opts, StringRef Path,
-                     StringRef Extension, bool InToplevel);
-
   SourceCoverageView(StringRef SourceName, const MemoryBuffer &File,
                      const CoverageViewOptions &Options,
                      coverage::CoverageData &&CoverageInfo)

Modified: llvm/trunk/tools/llvm-cov/SourceCoverageViewText.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/SourceCoverageViewText.cpp?rev=274029&r1=274028&r2=274029&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/SourceCoverageViewText.cpp (original)
+++ llvm/trunk/tools/llvm-cov/SourceCoverageViewText.cpp Tue Jun 28 11:12:24 2016
@@ -18,6 +18,28 @@
 
 using namespace llvm;
 
+Expected<CoveragePrinter::OwnedStream>
+CoveragePrinterText::createViewFile(StringRef Path, bool InToplevel) {
+  return createOutputStream(Path, "txt", InToplevel);
+}
+
+void CoveragePrinterText::closeViewFile(OwnedStream OS) {
+  OS->operator<<('\n');
+}
+
+Error CoveragePrinterText::createIndexFile(ArrayRef<StringRef> SourceFiles) {
+  auto OSOrErr = createOutputStream("index", "txt", /*InToplevel=*/true);
+  if (Error E = OSOrErr.takeError())
+    return E;
+  auto OS = std::move(OSOrErr.get());
+  raw_ostream &OSRef = *OS.get();
+
+  for (StringRef SF : SourceFiles)
+    OSRef << getOutputPath(SF, "txt", /*InToplevel=*/false) << '\n';
+
+  return Error::success();
+}
+
 namespace {
 
 static const unsigned LineCoverageColumnWidth = 7;
@@ -37,15 +59,6 @@ unsigned getDividerWidth(const CoverageV
 
 } // anonymous namespace
 
-Expected<SourceCoverageView::OwnedStream>
-SourceCoverageViewText::createOutputFile(StringRef Path, bool InToplevel) {
-  return createOutputStream(getOptions(), Path, "txt", InToplevel);
-}
-
-void SourceCoverageViewText::closeOutputFile(OwnedStream OS) {
-  OS->operator<<('\n');
-}
-
 void SourceCoverageViewText::renderSourceName(raw_ostream &OS) {
   getOptions().colored_ostream(OS, raw_ostream::CYAN) << getSourceName()
                                                       << ":\n";

Modified: llvm/trunk/tools/llvm-cov/SourceCoverageViewText.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/SourceCoverageViewText.h?rev=274029&r1=274028&r2=274029&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/SourceCoverageViewText.h (original)
+++ llvm/trunk/tools/llvm-cov/SourceCoverageViewText.h Tue Jun 28 11:12:24 2016
@@ -18,15 +18,22 @@
 
 namespace llvm {
 
-/// \brief A code coverage view which supports text-based rendering.
-class SourceCoverageViewText : public SourceCoverageView {
+/// \brief A coverage printer for text output.
+class CoveragePrinterText : public CoveragePrinter {
 public:
-  Expected<OwnedStream> createOutputFile(StringRef Path,
-                                         bool InToplevel) override;
+  Expected<OwnedStream> createViewFile(StringRef Path,
+                                       bool InToplevel) override;
+
+  void closeViewFile(OwnedStream OS) override;
 
-  void closeOutputFile(OwnedStream OS) override;
+  Error createIndexFile(ArrayRef<StringRef> SourceFiles) override;
 
-private:
+  CoveragePrinterText(const CoverageViewOptions &Opts)
+      : CoveragePrinter(Opts) {}
+};
+
+/// \brief A code coverage view which supports text-based rendering.
+class SourceCoverageViewText : public SourceCoverageView {
   void renderSourceName(raw_ostream &OS) override;
 
   void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) override;




More information about the llvm-commits mailing list