SourceCoverageView.h 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. //===- SourceCoverageView.h - Code coverage view for source code ----------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. ///
  10. /// \file This class implements rendering for code coverage of source code.
  11. ///
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_COV_SOURCECOVERAGEVIEW_H
  14. #define LLVM_COV_SOURCECOVERAGEVIEW_H
  15. #include "CoverageViewOptions.h"
  16. #include "llvm/ProfileData/Coverage/CoverageMapping.h"
  17. #include "llvm/Support/MemoryBuffer.h"
  18. #include <vector>
  19. namespace llvm {
  20. class SourceCoverageView;
  21. /// \brief A view that represents a macro or include expansion.
  22. struct ExpansionView {
  23. coverage::CounterMappingRegion Region;
  24. std::unique_ptr<SourceCoverageView> View;
  25. ExpansionView(const coverage::CounterMappingRegion &Region,
  26. std::unique_ptr<SourceCoverageView> View)
  27. : Region(Region), View(std::move(View)) {}
  28. ExpansionView(ExpansionView &&RHS)
  29. : Region(std::move(RHS.Region)), View(std::move(RHS.View)) {}
  30. ExpansionView &operator=(ExpansionView &&RHS) {
  31. Region = std::move(RHS.Region);
  32. View = std::move(RHS.View);
  33. return *this;
  34. }
  35. unsigned getLine() const { return Region.LineStart; }
  36. unsigned getStartCol() const { return Region.ColumnStart; }
  37. unsigned getEndCol() const { return Region.ColumnEnd; }
  38. friend bool operator<(const ExpansionView &LHS, const ExpansionView &RHS) {
  39. return LHS.Region.startLoc() < RHS.Region.startLoc();
  40. }
  41. };
  42. /// \brief A view that represents a function instantiation.
  43. struct InstantiationView {
  44. StringRef FunctionName;
  45. unsigned Line;
  46. std::unique_ptr<SourceCoverageView> View;
  47. InstantiationView(StringRef FunctionName, unsigned Line,
  48. std::unique_ptr<SourceCoverageView> View)
  49. : FunctionName(FunctionName), Line(Line), View(std::move(View)) {}
  50. friend bool operator<(const InstantiationView &LHS,
  51. const InstantiationView &RHS) {
  52. return LHS.Line < RHS.Line;
  53. }
  54. };
  55. /// \brief Coverage statistics for a single line.
  56. struct LineCoverageStats {
  57. uint64_t ExecutionCount;
  58. bool HasMultipleRegions;
  59. bool Mapped;
  60. LineCoverageStats(ArrayRef<const coverage::CoverageSegment *> LineSegments,
  61. const coverage::CoverageSegment *WrappedSegment);
  62. bool isMapped() const { return Mapped; }
  63. bool hasMultipleRegions() const { return HasMultipleRegions; }
  64. };
  65. /// \brief A file manager that handles format-aware file creation.
  66. class CoveragePrinter {
  67. public:
  68. struct StreamDestructor {
  69. void operator()(raw_ostream *OS) const;
  70. };
  71. using OwnedStream = std::unique_ptr<raw_ostream, StreamDestructor>;
  72. protected:
  73. const CoverageViewOptions &Opts;
  74. CoveragePrinter(const CoverageViewOptions &Opts) : Opts(Opts) {}
  75. /// \brief Return `OutputDir/ToplevelDir/Path.Extension`. If \p InToplevel is
  76. /// false, skip the ToplevelDir component. If \p Relative is false, skip the
  77. /// OutputDir component.
  78. std::string getOutputPath(StringRef Path, StringRef Extension,
  79. bool InToplevel, bool Relative = true) const;
  80. /// \brief If directory output is enabled, create a file in that directory
  81. /// at the path given by getOutputPath(). Otherwise, return stdout.
  82. Expected<OwnedStream> createOutputStream(StringRef Path, StringRef Extension,
  83. bool InToplevel) const;
  84. /// \brief Return the sub-directory name for file coverage reports.
  85. static StringRef getCoverageDir() { return "coverage"; }
  86. public:
  87. static std::unique_ptr<CoveragePrinter>
  88. create(const CoverageViewOptions &Opts);
  89. virtual ~CoveragePrinter() {}
  90. /// @name File Creation Interface
  91. /// @{
  92. /// \brief Create a file to print a coverage view into.
  93. virtual Expected<OwnedStream> createViewFile(StringRef Path,
  94. bool InToplevel) = 0;
  95. /// \brief Close a file which has been used to print a coverage view.
  96. virtual void closeViewFile(OwnedStream OS) = 0;
  97. /// \brief Create an index which lists reports for the given source files.
  98. virtual Error createIndexFile(ArrayRef<std::string> SourceFiles,
  99. const coverage::CoverageMapping &Coverage) = 0;
  100. /// @}
  101. };
  102. /// \brief A code coverage view of a source file or function.
  103. ///
  104. /// A source coverage view and its nested sub-views form a file-oriented
  105. /// representation of code coverage data. This view can be printed out by a
  106. /// renderer which implements the Rendering Interface.
  107. class SourceCoverageView {
  108. /// A function or file name.
  109. StringRef SourceName;
  110. /// A memory buffer backing the source on display.
  111. const MemoryBuffer &File;
  112. /// Various options to guide the coverage renderer.
  113. const CoverageViewOptions &Options;
  114. /// Complete coverage information about the source on display.
  115. coverage::CoverageData CoverageInfo;
  116. /// A container for all expansions (e.g macros) in the source on display.
  117. std::vector<ExpansionView> ExpansionSubViews;
  118. /// A container for all instantiations (e.g template functions) in the source
  119. /// on display.
  120. std::vector<InstantiationView> InstantiationSubViews;
  121. /// Get the first uncovered line number for the source file.
  122. unsigned getFirstUncoveredLineNo();
  123. protected:
  124. struct LineRef {
  125. StringRef Line;
  126. int64_t LineNo;
  127. LineRef(StringRef Line, int64_t LineNo) : Line(Line), LineNo(LineNo) {}
  128. };
  129. using CoverageSegmentArray = ArrayRef<const coverage::CoverageSegment *>;
  130. /// @name Rendering Interface
  131. /// @{
  132. /// \brief Render a header for the view.
  133. virtual void renderViewHeader(raw_ostream &OS) = 0;
  134. /// \brief Render a footer for the view.
  135. virtual void renderViewFooter(raw_ostream &OS) = 0;
  136. /// \brief Render the source name for the view.
  137. virtual void renderSourceName(raw_ostream &OS, bool WholeFile) = 0;
  138. /// \brief Render the line prefix at the given \p ViewDepth.
  139. virtual void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) = 0;
  140. /// \brief Render the line suffix at the given \p ViewDepth.
  141. virtual void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) = 0;
  142. /// \brief Render a view divider at the given \p ViewDepth.
  143. virtual void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) = 0;
  144. /// \brief Render a source line with highlighting.
  145. virtual void renderLine(raw_ostream &OS, LineRef L,
  146. const coverage::CoverageSegment *WrappedSegment,
  147. CoverageSegmentArray Segments, unsigned ExpansionCol,
  148. unsigned ViewDepth) = 0;
  149. /// \brief Render the line's execution count column.
  150. virtual void renderLineCoverageColumn(raw_ostream &OS,
  151. const LineCoverageStats &Line) = 0;
  152. /// \brief Render the line number column.
  153. virtual void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) = 0;
  154. /// \brief Render all the region's execution counts on a line.
  155. virtual void renderRegionMarkers(raw_ostream &OS,
  156. CoverageSegmentArray Segments,
  157. unsigned ViewDepth) = 0;
  158. /// \brief Render the site of an expansion.
  159. virtual void
  160. renderExpansionSite(raw_ostream &OS, LineRef L,
  161. const coverage::CoverageSegment *WrappedSegment,
  162. CoverageSegmentArray Segments, unsigned ExpansionCol,
  163. unsigned ViewDepth) = 0;
  164. /// \brief Render an expansion view and any nested views.
  165. virtual void renderExpansionView(raw_ostream &OS, ExpansionView &ESV,
  166. unsigned ViewDepth) = 0;
  167. /// \brief Render an instantiation view and any nested views.
  168. virtual void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV,
  169. unsigned ViewDepth) = 0;
  170. /// \brief Render \p Title, a project title if one is available, and the
  171. /// created time.
  172. virtual void renderTitle(raw_ostream &OS, StringRef CellText) = 0;
  173. /// \brief Render the table header for a given source file.
  174. virtual void renderTableHeader(raw_ostream &OS, unsigned FirstUncoveredLineNo,
  175. unsigned IndentLevel) = 0;
  176. /// @}
  177. /// \brief Format a count using engineering notation with 3 significant
  178. /// digits.
  179. static std::string formatCount(uint64_t N);
  180. /// \brief Check if region marker output is expected for a line.
  181. bool shouldRenderRegionMarkers(CoverageSegmentArray Segments) const;
  182. /// \brief Check if there are any sub-views attached to this view.
  183. bool hasSubViews() const;
  184. SourceCoverageView(StringRef SourceName, const MemoryBuffer &File,
  185. const CoverageViewOptions &Options,
  186. coverage::CoverageData &&CoverageInfo)
  187. : SourceName(SourceName), File(File), Options(Options),
  188. CoverageInfo(std::move(CoverageInfo)) {}
  189. public:
  190. static std::unique_ptr<SourceCoverageView>
  191. create(StringRef SourceName, const MemoryBuffer &File,
  192. const CoverageViewOptions &Options,
  193. coverage::CoverageData &&CoverageInfo);
  194. virtual ~SourceCoverageView() {}
  195. /// \brief Return the source name formatted for the host OS.
  196. std::string getSourceName() const;
  197. const CoverageViewOptions &getOptions() const { return Options; }
  198. /// \brief Add an expansion subview to this view.
  199. void addExpansion(const coverage::CounterMappingRegion &Region,
  200. std::unique_ptr<SourceCoverageView> View);
  201. /// \brief Add a function instantiation subview to this view.
  202. void addInstantiation(StringRef FunctionName, unsigned Line,
  203. std::unique_ptr<SourceCoverageView> View);
  204. /// \brief Print the code coverage information for a specific portion of a
  205. /// source file to the output stream.
  206. void print(raw_ostream &OS, bool WholeFile, bool ShowSourceName,
  207. unsigned ViewDepth = 0);
  208. };
  209. } // namespace llvm
  210. #endif // LLVM_COV_SOURCECOVERAGEVIEW_H