blob: e3a2f9e5c0b43fe864f90c52d7e3dda429e33f1e [file] [log] [blame]
Alex Lorenz6c7a6a12014-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 Kumara6154f92016-06-25 05:48:54 +00009///
10/// \file This class implements rendering for code coverage of source code.
11///
Alex Lorenz6c7a6a12014-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 Kumar1ef0d5a2017-09-19 02:00:12 +000018#include "CoverageSummaryInfo.h"
Easwaran Ramana96d53702016-04-29 18:53:05 +000019#include "llvm/ProfileData/Coverage/CoverageMapping.h"
Alex Lorenz6c7a6a12014-08-22 22:56:03 +000020#include "llvm/Support/MemoryBuffer.h"
21#include <vector>
22
23namespace llvm {
24
Vedant Kumar34ea0de2017-10-18 23:58:27 +000025using namespace coverage;
26
Sean Evesonb863c402017-10-03 11:05:28 +000027class CoverageFiltersMatchAll;
Justin Bognerd1b4e602014-09-17 05:33:20 +000028class SourceCoverageView;
29
Adrian Prantl26b584c2018-05-01 15:54:18 +000030/// A view that represents a macro or include expansion.
Justin Bognerd1b4e602014-09-17 05:33:20 +000031struct ExpansionView {
Vedant Kumar34ea0de2017-10-18 23:58:27 +000032 CounterMappingRegion Region;
Justin Bognerd1b4e602014-09-17 05:33:20 +000033 std::unique_ptr<SourceCoverageView> View;
34
Vedant Kumar34ea0de2017-10-18 23:58:27 +000035 ExpansionView(const CounterMappingRegion &Region,
Justin Bognerd1b4e602014-09-17 05:33:20 +000036 std::unique_ptr<SourceCoverageView> View)
37 : Region(Region), View(std::move(View)) {}
Justin Bognercc0c4e72014-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 Bognerd1b4e602014-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
Adrian Prantl26b584c2018-05-01 15:54:18 +000055/// A view that represents a function instantiation.
Justin Bognerd1b4e602014-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
Adrian Prantl26b584c2018-05-01 15:54:18 +000071/// A file manager that handles format-aware file creation.
Vedant Kumar028d73c2016-06-28 16:12:24 +000072class CoveragePrinter {
Vedant Kumar028d73c2016-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 Kumar6aa68be2016-07-21 23:26:15 +000081 const CoverageViewOptions &Opts;
82
Vedant Kumar028d73c2016-06-28 16:12:24 +000083 CoveragePrinter(const CoverageViewOptions &Opts) : Opts(Opts) {}
84
Adrian Prantl26b584c2018-05-01 15:54:18 +000085 /// Return `OutputDir/ToplevelDir/Path.Extension`. If \p InToplevel is
Vedant Kumard378d972016-06-29 21:55:46 +000086 /// false, skip the ToplevelDir component. If \p Relative is false, skip the
87 /// OutputDir component.
Vedant Kumar028d73c2016-06-28 16:12:24 +000088 std::string getOutputPath(StringRef Path, StringRef Extension,
Vedant Kumar85e096d2016-09-09 01:32:51 +000089 bool InToplevel, bool Relative = true) const;
Vedant Kumar028d73c2016-06-28 16:12:24 +000090
Adrian Prantl26b584c2018-05-01 15:54:18 +000091 /// If directory output is enabled, create a file in that directory
Vedant Kumar028d73c2016-06-28 16:12:24 +000092 /// at the path given by getOutputPath(). Otherwise, return stdout.
93 Expected<OwnedStream> createOutputStream(StringRef Path, StringRef Extension,
Vedant Kumar85e096d2016-09-09 01:32:51 +000094 bool InToplevel) const;
Vedant Kumar028d73c2016-06-28 16:12:24 +000095
Adrian Prantl26b584c2018-05-01 15:54:18 +000096 /// Return the sub-directory name for file coverage reports.
Vedant Kumar028d73c2016-06-28 16:12:24 +000097 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
Adrian Prantl26b584c2018-05-01 15:54:18 +0000108 /// Create a file to print a coverage view into.
Vedant Kumar028d73c2016-06-28 16:12:24 +0000109 virtual Expected<OwnedStream> createViewFile(StringRef Path,
110 bool InToplevel) = 0;
111
Adrian Prantl26b584c2018-05-01 15:54:18 +0000112 /// Close a file which has been used to print a coverage view.
Vedant Kumar028d73c2016-06-28 16:12:24 +0000113 virtual void closeViewFile(OwnedStream OS) = 0;
114
Adrian Prantl26b584c2018-05-01 15:54:18 +0000115 /// Create an index which lists reports for the given source files.
Vedant Kumarfd066352016-09-23 18:57:32 +0000116 virtual Error createIndexFile(ArrayRef<std::string> SourceFiles,
Vedant Kumar34ea0de2017-10-18 23:58:27 +0000117 const CoverageMapping &Coverage,
Sean Evesonb863c402017-10-03 11:05:28 +0000118 const CoverageFiltersMatchAll &Filters) = 0;
Vedant Kumar028d73c2016-06-28 16:12:24 +0000119
120 /// @}
121};
122
Adrian Prantl26b584c2018-05-01 15:54:18 +0000123/// A code coverage view of a source file or function.
Vedant Kumara6154f92016-06-25 05:48:54 +0000124///
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 Kumar028d73c2016-06-28 16:12:24 +0000127/// renderer which implements the Rendering Interface.
Alex Lorenz6c7a6a12014-08-22 22:56:03 +0000128class SourceCoverageView {
Vedant Kumarcc9ef122016-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 Lorenz6c7a6a12014-08-22 22:56:03 +0000133 const MemoryBuffer &File;
Vedant Kumarcc9ef122016-06-24 00:34:51 +0000134
135 /// Various options to guide the coverage renderer.
Alex Lorenz6c7a6a12014-08-22 22:56:03 +0000136 const CoverageViewOptions &Options;
Vedant Kumarcc9ef122016-06-24 00:34:51 +0000137
138 /// Complete coverage information about the source on display.
Vedant Kumar34ea0de2017-10-18 23:58:27 +0000139 CoverageData CoverageInfo;
Vedant Kumarcc9ef122016-06-24 00:34:51 +0000140
141 /// A container for all expansions (e.g macros) in the source on display.
Justin Bognerd1b4e602014-09-17 05:33:20 +0000142 std::vector<ExpansionView> ExpansionSubViews;
Vedant Kumarcc9ef122016-06-24 00:34:51 +0000143
144 /// A container for all instantiations (e.g template functions) in the source
145 /// on display.
Justin Bognerd1b4e602014-09-17 05:33:20 +0000146 std::vector<InstantiationView> InstantiationSubViews;
Alex Lorenz6c7a6a12014-08-22 22:56:03 +0000147
Ying Yif73cd142016-09-06 19:31:18 +0000148 /// Get the first uncovered line number for the source file.
149 unsigned getFirstUncoveredLineNo();
150
Vedant Kumara9bf3122016-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 Kumar34ea0de2017-10-18 23:58:27 +0000159 using CoverageSegmentArray = ArrayRef<const CoverageSegment *>;
Vedant Kumara9bf3122016-06-25 02:58:30 +0000160
161 /// @name Rendering Interface
162 /// @{
163
Adrian Prantl26b584c2018-05-01 15:54:18 +0000164 /// Render a header for the view.
Vedant Kumarcd29c6b2016-06-29 00:38:21 +0000165 virtual void renderViewHeader(raw_ostream &OS) = 0;
166
Adrian Prantl26b584c2018-05-01 15:54:18 +0000167 /// Render a footer for the view.
Vedant Kumarcd29c6b2016-06-29 00:38:21 +0000168 virtual void renderViewFooter(raw_ostream &OS) = 0;
169
Adrian Prantl26b584c2018-05-01 15:54:18 +0000170 /// Render the source name for the view.
Vedant Kumara8edd762016-09-10 19:37:26 +0000171 virtual void renderSourceName(raw_ostream &OS, bool WholeFile) = 0;
Vedant Kumara9bf3122016-06-25 02:58:30 +0000172
Adrian Prantl26b584c2018-05-01 15:54:18 +0000173 /// Render the line prefix at the given \p ViewDepth.
Vedant Kumara9bf3122016-06-25 02:58:30 +0000174 virtual void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) = 0;
175
Adrian Prantl26b584c2018-05-01 15:54:18 +0000176 /// Render the line suffix at the given \p ViewDepth.
Vedant Kumarcd29c6b2016-06-29 00:38:21 +0000177 virtual void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) = 0;
178
Adrian Prantl26b584c2018-05-01 15:54:18 +0000179 /// Render a view divider at the given \p ViewDepth.
Vedant Kumara9bf3122016-06-25 02:58:30 +0000180 virtual void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) = 0;
181
Adrian Prantl26b584c2018-05-01 15:54:18 +0000182 /// Render a source line with highlighting.
Vedant Kumara9bf3122016-06-25 02:58:30 +0000183 virtual void renderLine(raw_ostream &OS, LineRef L,
Vedant Kumard35bb382017-10-18 18:52:28 +0000184 const LineCoverageStats &LCS, unsigned ExpansionCol,
Vedant Kumara9bf3122016-06-25 02:58:30 +0000185 unsigned ViewDepth) = 0;
Alex Lorenz6c7a6a12014-08-22 22:56:03 +0000186
Adrian Prantl26b584c2018-05-01 15:54:18 +0000187 /// Render the line's execution count column.
Vedant Kumara9bf3122016-06-25 02:58:30 +0000188 virtual void renderLineCoverageColumn(raw_ostream &OS,
189 const LineCoverageStats &Line) = 0;
Alex Lorenz6c7a6a12014-08-22 22:56:03 +0000190
Adrian Prantl26b584c2018-05-01 15:54:18 +0000191 /// Render the line number column.
Vedant Kumara9bf3122016-06-25 02:58:30 +0000192 virtual void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) = 0;
Alex Lorenz6c7a6a12014-08-22 22:56:03 +0000193
Adrian Prantl26b584c2018-05-01 15:54:18 +0000194 /// Render all the region's execution counts on a line.
Vedant Kumara9bf3122016-06-25 02:58:30 +0000195 virtual void renderRegionMarkers(raw_ostream &OS,
Vedant Kumard35bb382017-10-18 18:52:28 +0000196 const LineCoverageStats &Line,
Vedant Kumara9bf3122016-06-25 02:58:30 +0000197 unsigned ViewDepth) = 0;
Alex Lorenz6c7a6a12014-08-22 22:56:03 +0000198
Adrian Prantl26b584c2018-05-01 15:54:18 +0000199 /// Render the site of an expansion.
Vedant Kumard35bb382017-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 Lorenz6c7a6a12014-08-22 22:56:03 +0000204
Adrian Prantl26b584c2018-05-01 15:54:18 +0000205 /// Render an expansion view and any nested views.
Vedant Kumare4356612016-06-26 02:45:13 +0000206 virtual void renderExpansionView(raw_ostream &OS, ExpansionView &ESV,
207 unsigned ViewDepth) = 0;
208
Adrian Prantl26b584c2018-05-01 15:54:18 +0000209 /// Render an instantiation view and any nested views.
Vedant Kumara9bf3122016-06-25 02:58:30 +0000210 virtual void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV,
211 unsigned ViewDepth) = 0;
212
Adrian Prantl26b584c2018-05-01 15:54:18 +0000213 /// Render \p Title, a project title if one is available, and the
Vedant Kumar7551d482016-09-15 04:45:59 +0000214 /// created time.
215 virtual void renderTitle(raw_ostream &OS, StringRef CellText) = 0;
Ying Yi1461e992016-08-24 14:27:23 +0000216
Adrian Prantl26b584c2018-05-01 15:54:18 +0000217 /// Render the table header for a given source file.
Vedant Kumara8edd762016-09-10 19:37:26 +0000218 virtual void renderTableHeader(raw_ostream &OS, unsigned FirstUncoveredLineNo,
219 unsigned IndentLevel) = 0;
Ying Yi1461e992016-08-24 14:27:23 +0000220
Vedant Kumara9bf3122016-06-25 02:58:30 +0000221 /// @}
222
Adrian Prantl26b584c2018-05-01 15:54:18 +0000223 /// Format a count using engineering notation with 3 significant
Vedant Kumara9bf3122016-06-25 02:58:30 +0000224 /// digits.
225 static std::string formatCount(uint64_t N);
226
Adrian Prantl26b584c2018-05-01 15:54:18 +0000227 /// Check if region marker output is expected for a line.
Vedant Kumar5a74fe72017-11-09 02:33:44 +0000228 bool shouldRenderRegionMarkers(const LineCoverageStats &LCS) const;
Vedant Kumarcd29c6b2016-06-29 00:38:21 +0000229
Adrian Prantl26b584c2018-05-01 15:54:18 +0000230 /// Check if there are any sub-views attached to this view.
Vedant Kumarcd29c6b2016-06-29 00:38:21 +0000231 bool hasSubViews() const;
232
Vedant Kumarcc9ef122016-06-24 00:34:51 +0000233 SourceCoverageView(StringRef SourceName, const MemoryBuffer &File,
Justin Bogner9eb38162014-09-20 15:31:56 +0000234 const CoverageViewOptions &Options,
Vedant Kumar34ea0de2017-10-18 23:58:27 +0000235 CoverageData &&CoverageInfo)
Vedant Kumarcc9ef122016-06-24 00:34:51 +0000236 : SourceName(SourceName), File(File), Options(Options),
Vedant Kumard2e36ca2016-09-08 00:56:48 +0000237 CoverageInfo(std::move(CoverageInfo)) {}
Vedant Kumarcc9ef122016-06-24 00:34:51 +0000238
Vedant Kumara9bf3122016-06-25 02:58:30 +0000239public:
240 static std::unique_ptr<SourceCoverageView>
241 create(StringRef SourceName, const MemoryBuffer &File,
Vedant Kumar34ea0de2017-10-18 23:58:27 +0000242 const CoverageViewOptions &Options, CoverageData &&CoverageInfo);
Vedant Kumara9bf3122016-06-25 02:58:30 +0000243
244 virtual ~SourceCoverageView() {}
245
Adrian Prantl26b584c2018-05-01 15:54:18 +0000246 /// Return the source name formatted for the host OS.
Vedant Kumard2e36ca2016-09-08 00:56:48 +0000247 std::string getSourceName() const;
Ying Yi84f34c02016-09-06 21:41:38 +0000248
Alex Lorenz6c7a6a12014-08-22 22:56:03 +0000249 const CoverageViewOptions &getOptions() const { return Options; }
250
Adrian Prantl26b584c2018-05-01 15:54:18 +0000251 /// Add an expansion subview to this view.
Vedant Kumar34ea0de2017-10-18 23:58:27 +0000252 void addExpansion(const CounterMappingRegion &Region,
Vedant Kumara9bf3122016-06-25 02:58:30 +0000253 std::unique_ptr<SourceCoverageView> View);
Alex Lorenz6c7a6a12014-08-22 22:56:03 +0000254
Adrian Prantl26b584c2018-05-01 15:54:18 +0000255 /// Add a function instantiation subview to this view.
Justin Bognerd1b4e602014-09-17 05:33:20 +0000256 void addInstantiation(StringRef FunctionName, unsigned Line,
Vedant Kumara9bf3122016-06-25 02:58:30 +0000257 std::unique_ptr<SourceCoverageView> View);
Alex Lorenz6c7a6a12014-08-22 22:56:03 +0000258
Adrian Prantl26b584c2018-05-01 15:54:18 +0000259 /// Print the code coverage information for a specific portion of a
Vedant Kumara9bf3122016-06-25 02:58:30 +0000260 /// source file to the output stream.
261 void print(raw_ostream &OS, bool WholeFile, bool ShowSourceName,
Sean Eveson078c2c32017-09-28 10:07:30 +0000262 bool ShowTitle, unsigned ViewDepth = 0);
Alex Lorenz6c7a6a12014-08-22 22:56:03 +0000263};
264
265} // namespace llvm
266
267#endif // LLVM_COV_SOURCECOVERAGEVIEW_H