diff options
Diffstat (limited to 'llvm/tools')
-rw-r--r-- | llvm/tools/llvm-cov/CodeCoverage.cpp | 19 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/SourceCoverageView.cpp | 100 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/SourceCoverageView.h | 75 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/SourceCoverageViewText.cpp | 31 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/SourceCoverageViewText.h | 19 |
5 files changed, 151 insertions, 93 deletions
diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp index 240acffa779..f2f97163ef1 100644 --- a/llvm/tools/llvm-cov/CodeCoverage.cpp +++ b/llvm/tools/llvm-cov/CodeCoverage.cpp @@ -448,6 +448,8 @@ int CodeCoverageTool::show(int argc, const char **argv, 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, const char **argv, 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, const char **argv, 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, const char **argv, 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, const char **argv, 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; diff --git a/llvm/tools/llvm-cov/SourceCoverageView.cpp b/llvm/tools/llvm-cov/SourceCoverageView.cpp index d6de961c70b..6b7f50ffc7e 100644 --- a/llvm/tools/llvm-cov/SourceCoverageView.cpp +++ b/llvm/tools/llvm-cov/SourceCoverageView.cpp @@ -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 SourceName, const MemoryBuffer &File, 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) diff --git a/llvm/tools/llvm-cov/SourceCoverageView.h b/llvm/tools/llvm-cov/SourceCoverageView.h index def5c6ad71d..3244dc8e8bb 100644 --- a/llvm/tools/llvm-cov/SourceCoverageView.h +++ b/llvm/tools/llvm-cov/SourceCoverageView.h @@ -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) diff --git a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp index 65169519c30..848b5f899cd 100644 --- a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp +++ b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp @@ -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 CoverageViewOptions &Opts) { } // 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"; diff --git a/llvm/tools/llvm-cov/SourceCoverageViewText.h b/llvm/tools/llvm-cov/SourceCoverageViewText.h index 769bfa1a652..29a64b522cd 100644 --- a/llvm/tools/llvm-cov/SourceCoverageViewText.h +++ b/llvm/tools/llvm-cov/SourceCoverageViewText.h @@ -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 closeOutputFile(OwnedStream OS) override; + void closeViewFile(OwnedStream OS) override; -private: + Error createIndexFile(ArrayRef<StringRef> SourceFiles) override; + + 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; |