xref: /netbsd-src/external/apache2/llvm/dist/llvm/tools/llvm-cov/SourceCoverageView.h (revision 82d56013d7b633d116a93943de88e08335357a7c)
17330f729Sjoerg //===- SourceCoverageView.h - Code coverage view for source code ----------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg ///
97330f729Sjoerg /// \file This class implements rendering for code coverage of source code.
107330f729Sjoerg ///
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg 
137330f729Sjoerg #ifndef LLVM_COV_SOURCECOVERAGEVIEW_H
147330f729Sjoerg #define LLVM_COV_SOURCECOVERAGEVIEW_H
157330f729Sjoerg 
167330f729Sjoerg #include "CoverageViewOptions.h"
177330f729Sjoerg #include "CoverageSummaryInfo.h"
187330f729Sjoerg #include "llvm/ProfileData/Coverage/CoverageMapping.h"
197330f729Sjoerg #include "llvm/Support/MemoryBuffer.h"
207330f729Sjoerg #include <vector>
217330f729Sjoerg 
227330f729Sjoerg namespace llvm {
237330f729Sjoerg 
247330f729Sjoerg using namespace coverage;
257330f729Sjoerg 
267330f729Sjoerg class CoverageFiltersMatchAll;
277330f729Sjoerg class SourceCoverageView;
287330f729Sjoerg 
297330f729Sjoerg /// A view that represents a macro or include expansion.
307330f729Sjoerg struct ExpansionView {
317330f729Sjoerg   CounterMappingRegion Region;
327330f729Sjoerg   std::unique_ptr<SourceCoverageView> View;
337330f729Sjoerg 
ExpansionViewExpansionView347330f729Sjoerg   ExpansionView(const CounterMappingRegion &Region,
357330f729Sjoerg                 std::unique_ptr<SourceCoverageView> View)
367330f729Sjoerg       : Region(Region), View(std::move(View)) {}
ExpansionViewExpansionView377330f729Sjoerg   ExpansionView(ExpansionView &&RHS)
387330f729Sjoerg       : Region(std::move(RHS.Region)), View(std::move(RHS.View)) {}
397330f729Sjoerg   ExpansionView &operator=(ExpansionView &&RHS) {
407330f729Sjoerg     Region = std::move(RHS.Region);
417330f729Sjoerg     View = std::move(RHS.View);
427330f729Sjoerg     return *this;
437330f729Sjoerg   }
447330f729Sjoerg 
getLineExpansionView457330f729Sjoerg   unsigned getLine() const { return Region.LineStart; }
getStartColExpansionView467330f729Sjoerg   unsigned getStartCol() const { return Region.ColumnStart; }
getEndColExpansionView477330f729Sjoerg   unsigned getEndCol() const { return Region.ColumnEnd; }
487330f729Sjoerg 
497330f729Sjoerg   friend bool operator<(const ExpansionView &LHS, const ExpansionView &RHS) {
507330f729Sjoerg     return LHS.Region.startLoc() < RHS.Region.startLoc();
517330f729Sjoerg   }
527330f729Sjoerg };
537330f729Sjoerg 
547330f729Sjoerg /// A view that represents a function instantiation.
557330f729Sjoerg struct InstantiationView {
567330f729Sjoerg   StringRef FunctionName;
577330f729Sjoerg   unsigned Line;
587330f729Sjoerg   std::unique_ptr<SourceCoverageView> View;
597330f729Sjoerg 
InstantiationViewInstantiationView607330f729Sjoerg   InstantiationView(StringRef FunctionName, unsigned Line,
617330f729Sjoerg                     std::unique_ptr<SourceCoverageView> View)
627330f729Sjoerg       : FunctionName(FunctionName), Line(Line), View(std::move(View)) {}
637330f729Sjoerg 
647330f729Sjoerg   friend bool operator<(const InstantiationView &LHS,
657330f729Sjoerg                         const InstantiationView &RHS) {
667330f729Sjoerg     return LHS.Line < RHS.Line;
677330f729Sjoerg   }
687330f729Sjoerg };
697330f729Sjoerg 
70*82d56013Sjoerg /// A view that represents one or more branch regions on a given source line.
71*82d56013Sjoerg struct BranchView {
72*82d56013Sjoerg   std::vector<CountedRegion> Regions;
73*82d56013Sjoerg   std::unique_ptr<SourceCoverageView> View;
74*82d56013Sjoerg   unsigned Line;
75*82d56013Sjoerg 
BranchViewBranchView76*82d56013Sjoerg   BranchView(unsigned Line, ArrayRef<CountedRegion> Regions,
77*82d56013Sjoerg              std::unique_ptr<SourceCoverageView> View)
78*82d56013Sjoerg       : Regions(Regions), View(std::move(View)), Line(Line) {}
79*82d56013Sjoerg 
getLineBranchView80*82d56013Sjoerg   unsigned getLine() const { return Line; }
81*82d56013Sjoerg 
82*82d56013Sjoerg   friend bool operator<(const BranchView &LHS, const BranchView &RHS) {
83*82d56013Sjoerg     return LHS.Line < RHS.Line;
84*82d56013Sjoerg   }
85*82d56013Sjoerg };
86*82d56013Sjoerg 
877330f729Sjoerg /// A file manager that handles format-aware file creation.
887330f729Sjoerg class CoveragePrinter {
897330f729Sjoerg public:
907330f729Sjoerg   struct StreamDestructor {
917330f729Sjoerg     void operator()(raw_ostream *OS) const;
927330f729Sjoerg   };
937330f729Sjoerg 
947330f729Sjoerg   using OwnedStream = std::unique_ptr<raw_ostream, StreamDestructor>;
957330f729Sjoerg 
967330f729Sjoerg protected:
977330f729Sjoerg   const CoverageViewOptions &Opts;
987330f729Sjoerg 
CoveragePrinter(const CoverageViewOptions & Opts)997330f729Sjoerg   CoveragePrinter(const CoverageViewOptions &Opts) : Opts(Opts) {}
1007330f729Sjoerg 
1017330f729Sjoerg   /// Return `OutputDir/ToplevelDir/Path.Extension`. If \p InToplevel is
1027330f729Sjoerg   /// false, skip the ToplevelDir component. If \p Relative is false, skip the
1037330f729Sjoerg   /// OutputDir component.
1047330f729Sjoerg   std::string getOutputPath(StringRef Path, StringRef Extension,
1057330f729Sjoerg                             bool InToplevel, bool Relative = true) const;
1067330f729Sjoerg 
1077330f729Sjoerg   /// If directory output is enabled, create a file in that directory
1087330f729Sjoerg   /// at the path given by getOutputPath(). Otherwise, return stdout.
1097330f729Sjoerg   Expected<OwnedStream> createOutputStream(StringRef Path, StringRef Extension,
1107330f729Sjoerg                                            bool InToplevel) const;
1117330f729Sjoerg 
1127330f729Sjoerg   /// Return the sub-directory name for file coverage reports.
getCoverageDir()1137330f729Sjoerg   static StringRef getCoverageDir() { return "coverage"; }
1147330f729Sjoerg 
1157330f729Sjoerg public:
1167330f729Sjoerg   static std::unique_ptr<CoveragePrinter>
1177330f729Sjoerg   create(const CoverageViewOptions &Opts);
1187330f729Sjoerg 
~CoveragePrinter()1197330f729Sjoerg   virtual ~CoveragePrinter() {}
1207330f729Sjoerg 
1217330f729Sjoerg   /// @name File Creation Interface
1227330f729Sjoerg   /// @{
1237330f729Sjoerg 
1247330f729Sjoerg   /// Create a file to print a coverage view into.
1257330f729Sjoerg   virtual Expected<OwnedStream> createViewFile(StringRef Path,
1267330f729Sjoerg                                                bool InToplevel) = 0;
1277330f729Sjoerg 
1287330f729Sjoerg   /// Close a file which has been used to print a coverage view.
1297330f729Sjoerg   virtual void closeViewFile(OwnedStream OS) = 0;
1307330f729Sjoerg 
1317330f729Sjoerg   /// Create an index which lists reports for the given source files.
1327330f729Sjoerg   virtual Error createIndexFile(ArrayRef<std::string> SourceFiles,
1337330f729Sjoerg                                 const CoverageMapping &Coverage,
1347330f729Sjoerg                                 const CoverageFiltersMatchAll &Filters) = 0;
1357330f729Sjoerg 
1367330f729Sjoerg   /// @}
1377330f729Sjoerg };
1387330f729Sjoerg 
1397330f729Sjoerg /// A code coverage view of a source file or function.
1407330f729Sjoerg ///
1417330f729Sjoerg /// A source coverage view and its nested sub-views form a file-oriented
1427330f729Sjoerg /// representation of code coverage data. This view can be printed out by a
1437330f729Sjoerg /// renderer which implements the Rendering Interface.
1447330f729Sjoerg class SourceCoverageView {
1457330f729Sjoerg   /// A function or file name.
1467330f729Sjoerg   StringRef SourceName;
1477330f729Sjoerg 
1487330f729Sjoerg   /// A memory buffer backing the source on display.
1497330f729Sjoerg   const MemoryBuffer &File;
1507330f729Sjoerg 
1517330f729Sjoerg   /// Various options to guide the coverage renderer.
1527330f729Sjoerg   const CoverageViewOptions &Options;
1537330f729Sjoerg 
1547330f729Sjoerg   /// Complete coverage information about the source on display.
1557330f729Sjoerg   CoverageData CoverageInfo;
1567330f729Sjoerg 
1577330f729Sjoerg   /// A container for all expansions (e.g macros) in the source on display.
1587330f729Sjoerg   std::vector<ExpansionView> ExpansionSubViews;
1597330f729Sjoerg 
160*82d56013Sjoerg   /// A container for all branches in the source on display.
161*82d56013Sjoerg   std::vector<BranchView> BranchSubViews;
162*82d56013Sjoerg 
1637330f729Sjoerg   /// A container for all instantiations (e.g template functions) in the source
1647330f729Sjoerg   /// on display.
1657330f729Sjoerg   std::vector<InstantiationView> InstantiationSubViews;
1667330f729Sjoerg 
1677330f729Sjoerg   /// Get the first uncovered line number for the source file.
1687330f729Sjoerg   unsigned getFirstUncoveredLineNo();
1697330f729Sjoerg 
1707330f729Sjoerg protected:
1717330f729Sjoerg   struct LineRef {
1727330f729Sjoerg     StringRef Line;
1737330f729Sjoerg     int64_t LineNo;
1747330f729Sjoerg 
LineRefLineRef1757330f729Sjoerg     LineRef(StringRef Line, int64_t LineNo) : Line(Line), LineNo(LineNo) {}
1767330f729Sjoerg   };
1777330f729Sjoerg 
1787330f729Sjoerg   using CoverageSegmentArray = ArrayRef<const CoverageSegment *>;
1797330f729Sjoerg 
1807330f729Sjoerg   /// @name Rendering Interface
1817330f729Sjoerg   /// @{
1827330f729Sjoerg 
1837330f729Sjoerg   /// Render a header for the view.
1847330f729Sjoerg   virtual void renderViewHeader(raw_ostream &OS) = 0;
1857330f729Sjoerg 
1867330f729Sjoerg   /// Render a footer for the view.
1877330f729Sjoerg   virtual void renderViewFooter(raw_ostream &OS) = 0;
1887330f729Sjoerg 
1897330f729Sjoerg   /// Render the source name for the view.
1907330f729Sjoerg   virtual void renderSourceName(raw_ostream &OS, bool WholeFile) = 0;
1917330f729Sjoerg 
1927330f729Sjoerg   /// Render the line prefix at the given \p ViewDepth.
1937330f729Sjoerg   virtual void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) = 0;
1947330f729Sjoerg 
1957330f729Sjoerg   /// Render the line suffix at the given \p ViewDepth.
1967330f729Sjoerg   virtual void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) = 0;
1977330f729Sjoerg 
1987330f729Sjoerg   /// Render a view divider at the given \p ViewDepth.
1997330f729Sjoerg   virtual void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) = 0;
2007330f729Sjoerg 
2017330f729Sjoerg   /// Render a source line with highlighting.
2027330f729Sjoerg   virtual void renderLine(raw_ostream &OS, LineRef L,
2037330f729Sjoerg                           const LineCoverageStats &LCS, unsigned ExpansionCol,
2047330f729Sjoerg                           unsigned ViewDepth) = 0;
2057330f729Sjoerg 
2067330f729Sjoerg   /// Render the line's execution count column.
2077330f729Sjoerg   virtual void renderLineCoverageColumn(raw_ostream &OS,
2087330f729Sjoerg                                         const LineCoverageStats &Line) = 0;
2097330f729Sjoerg 
2107330f729Sjoerg   /// Render the line number column.
2117330f729Sjoerg   virtual void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) = 0;
2127330f729Sjoerg 
2137330f729Sjoerg   /// Render all the region's execution counts on a line.
2147330f729Sjoerg   virtual void renderRegionMarkers(raw_ostream &OS,
2157330f729Sjoerg                                    const LineCoverageStats &Line,
2167330f729Sjoerg                                    unsigned ViewDepth) = 0;
2177330f729Sjoerg 
2187330f729Sjoerg   /// Render the site of an expansion.
2197330f729Sjoerg   virtual void renderExpansionSite(raw_ostream &OS, LineRef L,
2207330f729Sjoerg                                    const LineCoverageStats &LCS,
2217330f729Sjoerg                                    unsigned ExpansionCol,
2227330f729Sjoerg                                    unsigned ViewDepth) = 0;
2237330f729Sjoerg 
2247330f729Sjoerg   /// Render an expansion view and any nested views.
2257330f729Sjoerg   virtual void renderExpansionView(raw_ostream &OS, ExpansionView &ESV,
2267330f729Sjoerg                                    unsigned ViewDepth) = 0;
2277330f729Sjoerg 
2287330f729Sjoerg   /// Render an instantiation view and any nested views.
2297330f729Sjoerg   virtual void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV,
2307330f729Sjoerg                                        unsigned ViewDepth) = 0;
2317330f729Sjoerg 
232*82d56013Sjoerg   /// Render a branch view and any nested views.
233*82d56013Sjoerg   virtual void renderBranchView(raw_ostream &OS, BranchView &BRV,
234*82d56013Sjoerg                                 unsigned ViewDepth) = 0;
235*82d56013Sjoerg 
2367330f729Sjoerg   /// Render \p Title, a project title if one is available, and the
2377330f729Sjoerg   /// created time.
2387330f729Sjoerg   virtual void renderTitle(raw_ostream &OS, StringRef CellText) = 0;
2397330f729Sjoerg 
2407330f729Sjoerg   /// Render the table header for a given source file.
2417330f729Sjoerg   virtual void renderTableHeader(raw_ostream &OS, unsigned FirstUncoveredLineNo,
2427330f729Sjoerg                                  unsigned IndentLevel) = 0;
2437330f729Sjoerg 
2447330f729Sjoerg   /// @}
2457330f729Sjoerg 
2467330f729Sjoerg   /// Format a count using engineering notation with 3 significant
2477330f729Sjoerg   /// digits.
2487330f729Sjoerg   static std::string formatCount(uint64_t N);
2497330f729Sjoerg 
2507330f729Sjoerg   /// Check if region marker output is expected for a line.
2517330f729Sjoerg   bool shouldRenderRegionMarkers(const LineCoverageStats &LCS) const;
2527330f729Sjoerg 
2537330f729Sjoerg   /// Check if there are any sub-views attached to this view.
2547330f729Sjoerg   bool hasSubViews() const;
2557330f729Sjoerg 
SourceCoverageView(StringRef SourceName,const MemoryBuffer & File,const CoverageViewOptions & Options,CoverageData && CoverageInfo)2567330f729Sjoerg   SourceCoverageView(StringRef SourceName, const MemoryBuffer &File,
2577330f729Sjoerg                      const CoverageViewOptions &Options,
2587330f729Sjoerg                      CoverageData &&CoverageInfo)
2597330f729Sjoerg       : SourceName(SourceName), File(File), Options(Options),
2607330f729Sjoerg         CoverageInfo(std::move(CoverageInfo)) {}
2617330f729Sjoerg 
2627330f729Sjoerg public:
2637330f729Sjoerg   static std::unique_ptr<SourceCoverageView>
2647330f729Sjoerg   create(StringRef SourceName, const MemoryBuffer &File,
2657330f729Sjoerg          const CoverageViewOptions &Options, CoverageData &&CoverageInfo);
2667330f729Sjoerg 
~SourceCoverageView()2677330f729Sjoerg   virtual ~SourceCoverageView() {}
2687330f729Sjoerg 
2697330f729Sjoerg   /// Return the source name formatted for the host OS.
2707330f729Sjoerg   std::string getSourceName() const;
2717330f729Sjoerg 
getOptions()2727330f729Sjoerg   const CoverageViewOptions &getOptions() const { return Options; }
2737330f729Sjoerg 
2747330f729Sjoerg   /// Add an expansion subview to this view.
2757330f729Sjoerg   void addExpansion(const CounterMappingRegion &Region,
2767330f729Sjoerg                     std::unique_ptr<SourceCoverageView> View);
2777330f729Sjoerg 
2787330f729Sjoerg   /// Add a function instantiation subview to this view.
2797330f729Sjoerg   void addInstantiation(StringRef FunctionName, unsigned Line,
2807330f729Sjoerg                         std::unique_ptr<SourceCoverageView> View);
2817330f729Sjoerg 
282*82d56013Sjoerg   /// Add a branch subview to this view.
283*82d56013Sjoerg   void addBranch(unsigned Line, ArrayRef<CountedRegion> Regions,
284*82d56013Sjoerg                  std::unique_ptr<SourceCoverageView> View);
285*82d56013Sjoerg 
2867330f729Sjoerg   /// Print the code coverage information for a specific portion of a
2877330f729Sjoerg   /// source file to the output stream.
2887330f729Sjoerg   void print(raw_ostream &OS, bool WholeFile, bool ShowSourceName,
2897330f729Sjoerg              bool ShowTitle, unsigned ViewDepth = 0);
2907330f729Sjoerg };
2917330f729Sjoerg 
2927330f729Sjoerg } // namespace llvm
2937330f729Sjoerg 
2947330f729Sjoerg #endif // LLVM_COV_SOURCECOVERAGEVIEW_H
295