blob: 72d6866ed7dfd945d0bd9d545b734f8a46a0f083 [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
Justin Bogner5e1400a2014-09-17 05:33:20 +000025class SourceCoverageView;
26
Vedant Kumaree5a5e92016-06-25 05:48:54 +000027/// \brief A view that represents a macro or include expansion.
Justin Bogner5e1400a2014-09-17 05:33:20 +000028struct ExpansionView {
29 coverage::CounterMappingRegion Region;
30 std::unique_ptr<SourceCoverageView> View;
31
32 ExpansionView(const coverage::CounterMappingRegion &Region,
33 std::unique_ptr<SourceCoverageView> View)
34 : Region(Region), View(std::move(View)) {}
Justin Bogner99e95182014-09-17 06:32:48 +000035 ExpansionView(ExpansionView &&RHS)
36 : Region(std::move(RHS.Region)), View(std::move(RHS.View)) {}
37 ExpansionView &operator=(ExpansionView &&RHS) {
38 Region = std::move(RHS.Region);
39 View = std::move(RHS.View);
40 return *this;
41 }
Justin Bogner5e1400a2014-09-17 05:33:20 +000042
43 unsigned getLine() const { return Region.LineStart; }
44 unsigned getStartCol() const { return Region.ColumnStart; }
45 unsigned getEndCol() const { return Region.ColumnEnd; }
46
47 friend bool operator<(const ExpansionView &LHS, const ExpansionView &RHS) {
48 return LHS.Region.startLoc() < RHS.Region.startLoc();
49 }
50};
51
Vedant Kumaree5a5e92016-06-25 05:48:54 +000052/// \brief A view that represents a function instantiation.
Justin Bogner5e1400a2014-09-17 05:33:20 +000053struct InstantiationView {
54 StringRef FunctionName;
55 unsigned Line;
56 std::unique_ptr<SourceCoverageView> View;
57
58 InstantiationView(StringRef FunctionName, unsigned Line,
59 std::unique_ptr<SourceCoverageView> View)
60 : FunctionName(FunctionName), Line(Line), View(std::move(View)) {}
61
62 friend bool operator<(const InstantiationView &LHS,
63 const InstantiationView &RHS) {
64 return LHS.Line < RHS.Line;
65 }
66};
67
Vedant Kumar9cbad2c2016-06-28 16:12:24 +000068/// \brief A file manager that handles format-aware file creation.
69class CoveragePrinter {
Vedant Kumar9cbad2c2016-06-28 16:12:24 +000070public:
71 struct StreamDestructor {
72 void operator()(raw_ostream *OS) const;
73 };
74
75 using OwnedStream = std::unique_ptr<raw_ostream, StreamDestructor>;
76
77protected:
Vedant Kumarc076c492016-07-21 23:26:15 +000078 const CoverageViewOptions &Opts;
79
Vedant Kumar9cbad2c2016-06-28 16:12:24 +000080 CoveragePrinter(const CoverageViewOptions &Opts) : Opts(Opts) {}
81
Vedant Kumard6d192c2016-06-29 21:55:46 +000082 /// \brief Return `OutputDir/ToplevelDir/Path.Extension`. If \p InToplevel is
83 /// false, skip the ToplevelDir component. If \p Relative is false, skip the
84 /// OutputDir component.
Vedant Kumar9cbad2c2016-06-28 16:12:24 +000085 std::string getOutputPath(StringRef Path, StringRef Extension,
Vedant Kumaraae0ba72016-09-09 01:32:51 +000086 bool InToplevel, bool Relative = true) const;
Vedant Kumar9cbad2c2016-06-28 16:12:24 +000087
88 /// \brief If directory output is enabled, create a file in that directory
89 /// at the path given by getOutputPath(). Otherwise, return stdout.
90 Expected<OwnedStream> createOutputStream(StringRef Path, StringRef Extension,
Vedant Kumaraae0ba72016-09-09 01:32:51 +000091 bool InToplevel) const;
Vedant Kumar9cbad2c2016-06-28 16:12:24 +000092
93 /// \brief Return the sub-directory name for file coverage reports.
94 static StringRef getCoverageDir() { return "coverage"; }
95
96public:
97 static std::unique_ptr<CoveragePrinter>
98 create(const CoverageViewOptions &Opts);
99
100 virtual ~CoveragePrinter() {}
101
102 /// @name File Creation Interface
103 /// @{
104
105 /// \brief Create a file to print a coverage view into.
106 virtual Expected<OwnedStream> createViewFile(StringRef Path,
107 bool InToplevel) = 0;
108
109 /// \brief Close a file which has been used to print a coverage view.
110 virtual void closeViewFile(OwnedStream OS) = 0;
111
112 /// \brief Create an index which lists reports for the given source files.
Vedant Kumarbc647982016-09-23 18:57:32 +0000113 virtual Error createIndexFile(ArrayRef<std::string> SourceFiles,
Sean Eveson1439fa62017-09-27 16:20:07 +0000114 const coverage::CoverageMapping &Coverage) = 0;
Vedant Kumar9cbad2c2016-06-28 16:12:24 +0000115
116 /// @}
117};
118
Vedant Kumaree5a5e92016-06-25 05:48:54 +0000119/// \brief A code coverage view of a source file or function.
120///
121/// A source coverage view and its nested sub-views form a file-oriented
122/// representation of code coverage data. This view can be printed out by a
Vedant Kumar9cbad2c2016-06-28 16:12:24 +0000123/// renderer which implements the Rendering Interface.
Alex Lorenze82d89c2014-08-22 22:56:03 +0000124class SourceCoverageView {
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000125 /// A function or file name.
126 StringRef SourceName;
127
128 /// A memory buffer backing the source on display.
Alex Lorenze82d89c2014-08-22 22:56:03 +0000129 const MemoryBuffer &File;
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000130
131 /// Various options to guide the coverage renderer.
Alex Lorenze82d89c2014-08-22 22:56:03 +0000132 const CoverageViewOptions &Options;
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000133
134 /// Complete coverage information about the source on display.
Justin Bogner953e2402014-09-20 15:31:56 +0000135 coverage::CoverageData CoverageInfo;
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000136
137 /// A container for all expansions (e.g macros) in the source on display.
Justin Bogner5e1400a2014-09-17 05:33:20 +0000138 std::vector<ExpansionView> ExpansionSubViews;
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000139
140 /// A container for all instantiations (e.g template functions) in the source
141 /// on display.
Justin Bogner5e1400a2014-09-17 05:33:20 +0000142 std::vector<InstantiationView> InstantiationSubViews;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000143
Ying Yid36b47c2016-09-06 19:31:18 +0000144 /// Get the first uncovered line number for the source file.
145 unsigned getFirstUncoveredLineNo();
146
Vedant Kumarf9151b92016-06-25 02:58:30 +0000147protected:
148 struct LineRef {
149 StringRef Line;
150 int64_t LineNo;
151
152 LineRef(StringRef Line, int64_t LineNo) : Line(Line), LineNo(LineNo) {}
153 };
154
155 using CoverageSegmentArray = ArrayRef<const coverage::CoverageSegment *>;
156
157 /// @name Rendering Interface
158 /// @{
159
Vedant Kumar8d74cb22016-06-29 00:38:21 +0000160 /// \brief Render a header for the view.
161 virtual void renderViewHeader(raw_ostream &OS) = 0;
162
163 /// \brief Render a footer for the view.
164 virtual void renderViewFooter(raw_ostream &OS) = 0;
165
Vedant Kumarf9151b92016-06-25 02:58:30 +0000166 /// \brief Render the source name for the view.
Vedant Kumarb1c174a2016-09-10 19:37:26 +0000167 virtual void renderSourceName(raw_ostream &OS, bool WholeFile) = 0;
Vedant Kumarf9151b92016-06-25 02:58:30 +0000168
169 /// \brief Render the line prefix at the given \p ViewDepth.
170 virtual void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) = 0;
171
Vedant Kumar8d74cb22016-06-29 00:38:21 +0000172 /// \brief Render the line suffix at the given \p ViewDepth.
173 virtual void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) = 0;
174
Vedant Kumarf9151b92016-06-25 02:58:30 +0000175 /// \brief Render a view divider at the given \p ViewDepth.
176 virtual void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) = 0;
177
Alex Lorenze82d89c2014-08-22 22:56:03 +0000178 /// \brief Render a source line with highlighting.
Vedant Kumarf9151b92016-06-25 02:58:30 +0000179 virtual void renderLine(raw_ostream &OS, LineRef L,
180 const coverage::CoverageSegment *WrappedSegment,
181 CoverageSegmentArray Segments, unsigned ExpansionCol,
182 unsigned ViewDepth) = 0;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000183
184 /// \brief Render the line's execution count column.
Vedant Kumarf9151b92016-06-25 02:58:30 +0000185 virtual void renderLineCoverageColumn(raw_ostream &OS,
186 const LineCoverageStats &Line) = 0;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000187
188 /// \brief Render the line number column.
Vedant Kumarf9151b92016-06-25 02:58:30 +0000189 virtual void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) = 0;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000190
191 /// \brief Render all the region's execution counts on a line.
Vedant Kumarf9151b92016-06-25 02:58:30 +0000192 virtual void renderRegionMarkers(raw_ostream &OS,
193 CoverageSegmentArray Segments,
194 unsigned ViewDepth) = 0;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000195
Vedant Kumar861a19c2016-06-26 02:45:13 +0000196 /// \brief Render the site of an expansion.
197 virtual void
Vedant Kumar8d74cb22016-06-29 00:38:21 +0000198 renderExpansionSite(raw_ostream &OS, LineRef L,
Vedant Kumar8b12ecb2016-06-25 05:48:59 +0000199 const coverage::CoverageSegment *WrappedSegment,
200 CoverageSegmentArray Segments, unsigned ExpansionCol,
201 unsigned ViewDepth) = 0;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000202
Vedant Kumar861a19c2016-06-26 02:45:13 +0000203 /// \brief Render an expansion view and any nested views.
204 virtual void renderExpansionView(raw_ostream &OS, ExpansionView &ESV,
205 unsigned ViewDepth) = 0;
206
207 /// \brief Render an instantiation view and any nested views.
Vedant Kumarf9151b92016-06-25 02:58:30 +0000208 virtual void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV,
209 unsigned ViewDepth) = 0;
210
Vedant Kumarb2edd112016-09-15 04:45:59 +0000211 /// \brief Render \p Title, a project title if one is available, and the
212 /// created time.
213 virtual void renderTitle(raw_ostream &OS, StringRef CellText) = 0;
Ying Yi84dc9712016-08-24 14:27:23 +0000214
Vedant Kumarb1c174a2016-09-10 19:37:26 +0000215 /// \brief Render the table header for a given source file.
216 virtual void renderTableHeader(raw_ostream &OS, unsigned FirstUncoveredLineNo,
217 unsigned IndentLevel) = 0;
Ying Yi84dc9712016-08-24 14:27:23 +0000218
Vedant Kumarf9151b92016-06-25 02:58:30 +0000219 /// @}
220
221 /// \brief Format a count using engineering notation with 3 significant
222 /// digits.
223 static std::string formatCount(uint64_t N);
224
Vedant Kumar8d74cb22016-06-29 00:38:21 +0000225 /// \brief Check if region marker output is expected for a line.
Vedant Kumar933b37f2017-09-08 18:44:46 +0000226 bool shouldRenderRegionMarkers(CoverageSegmentArray Segments) const;
Vedant Kumar8d74cb22016-06-29 00:38:21 +0000227
228 /// \brief Check if there are any sub-views attached to this view.
229 bool hasSubViews() const;
230
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000231 SourceCoverageView(StringRef SourceName, const MemoryBuffer &File,
Justin Bogner953e2402014-09-20 15:31:56 +0000232 const CoverageViewOptions &Options,
Vedant Kumar0053c0b2016-09-08 00:56:48 +0000233 coverage::CoverageData &&CoverageInfo)
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000234 : SourceName(SourceName), File(File), Options(Options),
Vedant Kumar0053c0b2016-09-08 00:56:48 +0000235 CoverageInfo(std::move(CoverageInfo)) {}
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000236
Vedant Kumarf9151b92016-06-25 02:58:30 +0000237public:
238 static std::unique_ptr<SourceCoverageView>
239 create(StringRef SourceName, const MemoryBuffer &File,
240 const CoverageViewOptions &Options,
Vedant Kumar0053c0b2016-09-08 00:56:48 +0000241 coverage::CoverageData &&CoverageInfo);
Vedant Kumarf9151b92016-06-25 02:58:30 +0000242
243 virtual ~SourceCoverageView() {}
244
Ying Yi24e91bd2016-09-06 21:41:38 +0000245 /// \brief Return the source name formatted for the host OS.
Vedant Kumar0053c0b2016-09-08 00:56:48 +0000246 std::string getSourceName() const;
Ying Yi24e91bd2016-09-06 21:41:38 +0000247
Alex Lorenze82d89c2014-08-22 22:56:03 +0000248 const CoverageViewOptions &getOptions() const { return Options; }
249
Justin Bogner5e1400a2014-09-17 05:33:20 +0000250 /// \brief Add an expansion subview to this view.
251 void addExpansion(const coverage::CounterMappingRegion &Region,
Vedant Kumarf9151b92016-06-25 02:58:30 +0000252 std::unique_ptr<SourceCoverageView> View);
Alex Lorenze82d89c2014-08-22 22:56:03 +0000253
Justin Bogner5e1400a2014-09-17 05:33:20 +0000254 /// \brief Add a function instantiation subview to this view.
255 void addInstantiation(StringRef FunctionName, unsigned Line,
Vedant Kumarf9151b92016-06-25 02:58:30 +0000256 std::unique_ptr<SourceCoverageView> View);
Alex Lorenze82d89c2014-08-22 22:56:03 +0000257
Vedant Kumarf9151b92016-06-25 02:58:30 +0000258 /// \brief Print the code coverage information for a specific portion of a
259 /// source file to the output stream.
260 void print(raw_ostream &OS, bool WholeFile, bool ShowSourceName,
Sean Eveson1439fa62017-09-27 16:20:07 +0000261 unsigned ViewDepth = 0);
Alex Lorenze82d89c2014-08-22 22:56:03 +0000262};
263
264} // namespace llvm
265
266#endif // LLVM_COV_SOURCECOVERAGEVIEW_H