blob: 35dea591bf049651dc8682d5ab4b0188ffe80c58 [file] [log] [blame]
Alex Lorenze82d89c2014-08-22 22:56:03 +00001//===- 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//===----------------------------------------------------------------------===//
Vedant Kumaree5a5e92016-06-25 05:48:54 +00009///
10/// \file This class implements rendering for code coverage of source code.
11///
Alex Lorenze82d89c2014-08-22 22:56:03 +000012//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_COV_SOURCECOVERAGEVIEW_H
15#define LLVM_COV_SOURCECOVERAGEVIEW_H
16
17#include "CoverageViewOptions.h"
Vedant Kumarb7fdaf22017-09-19 02:00:12 +000018#include "CoverageSummaryInfo.h"
Easwaran Ramandc707122016-04-29 18:53:05 +000019#include "llvm/ProfileData/Coverage/CoverageMapping.h"
Alex Lorenze82d89c2014-08-22 22:56:03 +000020#include "llvm/Support/MemoryBuffer.h"
21#include <vector>
22
23namespace llvm {
24
Vedant Kumare955f612017-10-18 23:58:27 +000025using namespace coverage;
26
Sean Evesond932b2d2017-10-03 11:05:28 +000027class CoverageFiltersMatchAll;
Justin Bogner5e1400a2014-09-17 05:33:20 +000028class SourceCoverageView;
29
Vedant Kumaree5a5e92016-06-25 05:48:54 +000030/// \brief A view that represents a macro or include expansion.
Justin Bogner5e1400a2014-09-17 05:33:20 +000031struct ExpansionView {
Vedant Kumare955f612017-10-18 23:58:27 +000032 CounterMappingRegion Region;
Justin Bogner5e1400a2014-09-17 05:33:20 +000033 std::unique_ptr<SourceCoverageView> View;
34
Vedant Kumare955f612017-10-18 23:58:27 +000035 ExpansionView(const CounterMappingRegion &Region,
Justin Bogner5e1400a2014-09-17 05:33:20 +000036 std::unique_ptr<SourceCoverageView> View)
37 : Region(Region), View(std::move(View)) {}
Justin Bogner99e95182014-09-17 06:32:48 +000038 ExpansionView(ExpansionView &&RHS)
39 : Region(std::move(RHS.Region)), View(std::move(RHS.View)) {}
40 ExpansionView &operator=(ExpansionView &&RHS) {
41 Region = std::move(RHS.Region);
42 View = std::move(RHS.View);
43 return *this;
44 }
Justin Bogner5e1400a2014-09-17 05:33:20 +000045
46 unsigned getLine() const { return Region.LineStart; }
47 unsigned getStartCol() const { return Region.ColumnStart; }
48 unsigned getEndCol() const { return Region.ColumnEnd; }
49
50 friend bool operator<(const ExpansionView &LHS, const ExpansionView &RHS) {
51 return LHS.Region.startLoc() < RHS.Region.startLoc();
52 }
53};
54
Vedant Kumaree5a5e92016-06-25 05:48:54 +000055/// \brief A view that represents a function instantiation.
Justin Bogner5e1400a2014-09-17 05:33:20 +000056struct InstantiationView {
57 StringRef FunctionName;
58 unsigned Line;
59 std::unique_ptr<SourceCoverageView> View;
60
61 InstantiationView(StringRef FunctionName, unsigned Line,
62 std::unique_ptr<SourceCoverageView> View)
63 : FunctionName(FunctionName), Line(Line), View(std::move(View)) {}
64
65 friend bool operator<(const InstantiationView &LHS,
66 const InstantiationView &RHS) {
67 return LHS.Line < RHS.Line;
68 }
69};
70
Vedant Kumar9cbad2c2016-06-28 16:12:24 +000071/// \brief A file manager that handles format-aware file creation.
72class CoveragePrinter {
Vedant Kumar9cbad2c2016-06-28 16:12:24 +000073public:
74 struct StreamDestructor {
75 void operator()(raw_ostream *OS) const;
76 };
77
78 using OwnedStream = std::unique_ptr<raw_ostream, StreamDestructor>;
79
80protected:
Vedant Kumarc076c492016-07-21 23:26:15 +000081 const CoverageViewOptions &Opts;
82
Vedant Kumar9cbad2c2016-06-28 16:12:24 +000083 CoveragePrinter(const CoverageViewOptions &Opts) : Opts(Opts) {}
84
Vedant Kumard6d192c2016-06-29 21:55:46 +000085 /// \brief Return `OutputDir/ToplevelDir/Path.Extension`. If \p InToplevel is
86 /// false, skip the ToplevelDir component. If \p Relative is false, skip the
87 /// OutputDir component.
Vedant Kumar9cbad2c2016-06-28 16:12:24 +000088 std::string getOutputPath(StringRef Path, StringRef Extension,
Vedant Kumaraae0ba72016-09-09 01:32:51 +000089 bool InToplevel, bool Relative = true) const;
Vedant Kumar9cbad2c2016-06-28 16:12:24 +000090
91 /// \brief If directory output is enabled, create a file in that directory
92 /// at the path given by getOutputPath(). Otherwise, return stdout.
93 Expected<OwnedStream> createOutputStream(StringRef Path, StringRef Extension,
Vedant Kumaraae0ba72016-09-09 01:32:51 +000094 bool InToplevel) const;
Vedant Kumar9cbad2c2016-06-28 16:12:24 +000095
96 /// \brief Return the sub-directory name for file coverage reports.
97 static StringRef getCoverageDir() { return "coverage"; }
98
99public:
100 static std::unique_ptr<CoveragePrinter>
101 create(const CoverageViewOptions &Opts);
102
103 virtual ~CoveragePrinter() {}
104
105 /// @name File Creation Interface
106 /// @{
107
108 /// \brief Create a file to print a coverage view into.
109 virtual Expected<OwnedStream> createViewFile(StringRef Path,
110 bool InToplevel) = 0;
111
112 /// \brief Close a file which has been used to print a coverage view.
113 virtual void closeViewFile(OwnedStream OS) = 0;
114
115 /// \brief Create an index which lists reports for the given source files.
Vedant Kumarbc647982016-09-23 18:57:32 +0000116 virtual Error createIndexFile(ArrayRef<std::string> SourceFiles,
Vedant Kumare955f612017-10-18 23:58:27 +0000117 const CoverageMapping &Coverage,
Sean Evesond932b2d2017-10-03 11:05:28 +0000118 const CoverageFiltersMatchAll &Filters) = 0;
Vedant Kumar9cbad2c2016-06-28 16:12:24 +0000119
120 /// @}
121};
122
Vedant Kumaree5a5e92016-06-25 05:48:54 +0000123/// \brief A code coverage view of a source file or function.
124///
125/// A source coverage view and its nested sub-views form a file-oriented
126/// representation of code coverage data. This view can be printed out by a
Vedant Kumar9cbad2c2016-06-28 16:12:24 +0000127/// renderer which implements the Rendering Interface.
Alex Lorenze82d89c2014-08-22 22:56:03 +0000128class SourceCoverageView {
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000129 /// A function or file name.
130 StringRef SourceName;
131
132 /// A memory buffer backing the source on display.
Alex Lorenze82d89c2014-08-22 22:56:03 +0000133 const MemoryBuffer &File;
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000134
135 /// Various options to guide the coverage renderer.
Alex Lorenze82d89c2014-08-22 22:56:03 +0000136 const CoverageViewOptions &Options;
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000137
138 /// Complete coverage information about the source on display.
Vedant Kumare955f612017-10-18 23:58:27 +0000139 CoverageData CoverageInfo;
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000140
141 /// A container for all expansions (e.g macros) in the source on display.
Justin Bogner5e1400a2014-09-17 05:33:20 +0000142 std::vector<ExpansionView> ExpansionSubViews;
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000143
144 /// A container for all instantiations (e.g template functions) in the source
145 /// on display.
Justin Bogner5e1400a2014-09-17 05:33:20 +0000146 std::vector<InstantiationView> InstantiationSubViews;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000147
Ying Yid36b47c2016-09-06 19:31:18 +0000148 /// Get the first uncovered line number for the source file.
149 unsigned getFirstUncoveredLineNo();
150
Vedant Kumarf9151b92016-06-25 02:58:30 +0000151protected:
152 struct LineRef {
153 StringRef Line;
154 int64_t LineNo;
155
156 LineRef(StringRef Line, int64_t LineNo) : Line(Line), LineNo(LineNo) {}
157 };
158
Vedant Kumare955f612017-10-18 23:58:27 +0000159 using CoverageSegmentArray = ArrayRef<const CoverageSegment *>;
Vedant Kumarf9151b92016-06-25 02:58:30 +0000160
161 /// @name Rendering Interface
162 /// @{
163
Vedant Kumar8d74cb22016-06-29 00:38:21 +0000164 /// \brief Render a header for the view.
165 virtual void renderViewHeader(raw_ostream &OS) = 0;
166
167 /// \brief Render a footer for the view.
168 virtual void renderViewFooter(raw_ostream &OS) = 0;
169
Vedant Kumarf9151b92016-06-25 02:58:30 +0000170 /// \brief Render the source name for the view.
Vedant Kumarb1c174a2016-09-10 19:37:26 +0000171 virtual void renderSourceName(raw_ostream &OS, bool WholeFile) = 0;
Vedant Kumarf9151b92016-06-25 02:58:30 +0000172
173 /// \brief Render the line prefix at the given \p ViewDepth.
174 virtual void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) = 0;
175
Vedant Kumar8d74cb22016-06-29 00:38:21 +0000176 /// \brief Render the line suffix at the given \p ViewDepth.
177 virtual void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) = 0;
178
Vedant Kumarf9151b92016-06-25 02:58:30 +0000179 /// \brief Render a view divider at the given \p ViewDepth.
180 virtual void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) = 0;
181
Alex Lorenze82d89c2014-08-22 22:56:03 +0000182 /// \brief Render a source line with highlighting.
Vedant Kumarf9151b92016-06-25 02:58:30 +0000183 virtual void renderLine(raw_ostream &OS, LineRef L,
Vedant Kumar08a0a312017-10-18 18:52:28 +0000184 const LineCoverageStats &LCS, unsigned ExpansionCol,
Vedant Kumarf9151b92016-06-25 02:58:30 +0000185 unsigned ViewDepth) = 0;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000186
187 /// \brief Render the line's execution count column.
Vedant Kumarf9151b92016-06-25 02:58:30 +0000188 virtual void renderLineCoverageColumn(raw_ostream &OS,
189 const LineCoverageStats &Line) = 0;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000190
191 /// \brief Render the line number column.
Vedant Kumarf9151b92016-06-25 02:58:30 +0000192 virtual void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) = 0;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000193
194 /// \brief Render all the region's execution counts on a line.
Vedant Kumarf9151b92016-06-25 02:58:30 +0000195 virtual void renderRegionMarkers(raw_ostream &OS,
Vedant Kumar08a0a312017-10-18 18:52:28 +0000196 const LineCoverageStats &Line,
Vedant Kumarf9151b92016-06-25 02:58:30 +0000197 unsigned ViewDepth) = 0;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000198
Vedant Kumar861a19c2016-06-26 02:45:13 +0000199 /// \brief Render the site of an expansion.
Vedant Kumar08a0a312017-10-18 18:52:28 +0000200 virtual void renderExpansionSite(raw_ostream &OS, LineRef L,
201 const LineCoverageStats &LCS,
202 unsigned ExpansionCol,
203 unsigned ViewDepth) = 0;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000204
Vedant Kumar861a19c2016-06-26 02:45:13 +0000205 /// \brief Render an expansion view and any nested views.
206 virtual void renderExpansionView(raw_ostream &OS, ExpansionView &ESV,
207 unsigned ViewDepth) = 0;
208
209 /// \brief Render an instantiation view and any nested views.
Vedant Kumarf9151b92016-06-25 02:58:30 +0000210 virtual void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV,
211 unsigned ViewDepth) = 0;
212
Vedant Kumarb2edd112016-09-15 04:45:59 +0000213 /// \brief Render \p Title, a project title if one is available, and the
214 /// created time.
215 virtual void renderTitle(raw_ostream &OS, StringRef CellText) = 0;
Ying Yi84dc9712016-08-24 14:27:23 +0000216
Vedant Kumarb1c174a2016-09-10 19:37:26 +0000217 /// \brief Render the table header for a given source file.
218 virtual void renderTableHeader(raw_ostream &OS, unsigned FirstUncoveredLineNo,
219 unsigned IndentLevel) = 0;
Ying Yi84dc9712016-08-24 14:27:23 +0000220
Vedant Kumarf9151b92016-06-25 02:58:30 +0000221 /// @}
222
223 /// \brief Format a count using engineering notation with 3 significant
224 /// digits.
225 static std::string formatCount(uint64_t N);
226
Vedant Kumar8d74cb22016-06-29 00:38:21 +0000227 /// \brief Check if region marker output is expected for a line.
Vedant Kumar933b37f2017-09-08 18:44:46 +0000228 bool shouldRenderRegionMarkers(CoverageSegmentArray Segments) const;
Vedant Kumar8d74cb22016-06-29 00:38:21 +0000229
230 /// \brief Check if there are any sub-views attached to this view.
231 bool hasSubViews() const;
232
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000233 SourceCoverageView(StringRef SourceName, const MemoryBuffer &File,
Justin Bogner953e2402014-09-20 15:31:56 +0000234 const CoverageViewOptions &Options,
Vedant Kumare955f612017-10-18 23:58:27 +0000235 CoverageData &&CoverageInfo)
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000236 : SourceName(SourceName), File(File), Options(Options),
Vedant Kumar0053c0b2016-09-08 00:56:48 +0000237 CoverageInfo(std::move(CoverageInfo)) {}
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000238
Vedant Kumarf9151b92016-06-25 02:58:30 +0000239public:
240 static std::unique_ptr<SourceCoverageView>
241 create(StringRef SourceName, const MemoryBuffer &File,
Vedant Kumare955f612017-10-18 23:58:27 +0000242 const CoverageViewOptions &Options, CoverageData &&CoverageInfo);
Vedant Kumarf9151b92016-06-25 02:58:30 +0000243
244 virtual ~SourceCoverageView() {}
245
Ying Yi24e91bd2016-09-06 21:41:38 +0000246 /// \brief Return the source name formatted for the host OS.
Vedant Kumar0053c0b2016-09-08 00:56:48 +0000247 std::string getSourceName() const;
Ying Yi24e91bd2016-09-06 21:41:38 +0000248
Alex Lorenze82d89c2014-08-22 22:56:03 +0000249 const CoverageViewOptions &getOptions() const { return Options; }
250
Justin Bogner5e1400a2014-09-17 05:33:20 +0000251 /// \brief Add an expansion subview to this view.
Vedant Kumare955f612017-10-18 23:58:27 +0000252 void addExpansion(const CounterMappingRegion &Region,
Vedant Kumarf9151b92016-06-25 02:58:30 +0000253 std::unique_ptr<SourceCoverageView> View);
Alex Lorenze82d89c2014-08-22 22:56:03 +0000254
Justin Bogner5e1400a2014-09-17 05:33:20 +0000255 /// \brief Add a function instantiation subview to this view.
256 void addInstantiation(StringRef FunctionName, unsigned Line,
Vedant Kumarf9151b92016-06-25 02:58:30 +0000257 std::unique_ptr<SourceCoverageView> View);
Alex Lorenze82d89c2014-08-22 22:56:03 +0000258
Vedant Kumarf9151b92016-06-25 02:58:30 +0000259 /// \brief Print the code coverage information for a specific portion of a
260 /// source file to the output stream.
261 void print(raw_ostream &OS, bool WholeFile, bool ShowSourceName,
Sean Evesonfa8ef352017-09-28 10:07:30 +0000262 bool ShowTitle, unsigned ViewDepth = 0);
Alex Lorenze82d89c2014-08-22 22:56:03 +0000263};
264
265} // namespace llvm
266
267#endif // LLVM_COV_SOURCECOVERAGEVIEW_H