blob: 24080284d8b43d6c6dbad7380d6a607a32735805 [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
Sean Evesond932b2d2017-10-03 11:05:28 +000025class CoverageFiltersMatchAll;
Justin Bogner5e1400a2014-09-17 05:33:20 +000026class SourceCoverageView;
27
Vedant Kumaree5a5e92016-06-25 05:48:54 +000028/// \brief A view that represents a macro or include expansion.
Justin Bogner5e1400a2014-09-17 05:33:20 +000029struct ExpansionView {
30 coverage::CounterMappingRegion Region;
31 std::unique_ptr<SourceCoverageView> View;
32
33 ExpansionView(const coverage::CounterMappingRegion &Region,
34 std::unique_ptr<SourceCoverageView> View)
35 : Region(Region), View(std::move(View)) {}
Justin Bogner99e95182014-09-17 06:32:48 +000036 ExpansionView(ExpansionView &&RHS)
37 : Region(std::move(RHS.Region)), View(std::move(RHS.View)) {}
38 ExpansionView &operator=(ExpansionView &&RHS) {
39 Region = std::move(RHS.Region);
40 View = std::move(RHS.View);
41 return *this;
42 }
Justin Bogner5e1400a2014-09-17 05:33:20 +000043
44 unsigned getLine() const { return Region.LineStart; }
45 unsigned getStartCol() const { return Region.ColumnStart; }
46 unsigned getEndCol() const { return Region.ColumnEnd; }
47
48 friend bool operator<(const ExpansionView &LHS, const ExpansionView &RHS) {
49 return LHS.Region.startLoc() < RHS.Region.startLoc();
50 }
51};
52
Vedant Kumaree5a5e92016-06-25 05:48:54 +000053/// \brief A view that represents a function instantiation.
Justin Bogner5e1400a2014-09-17 05:33:20 +000054struct InstantiationView {
55 StringRef FunctionName;
56 unsigned Line;
57 std::unique_ptr<SourceCoverageView> View;
58
59 InstantiationView(StringRef FunctionName, unsigned Line,
60 std::unique_ptr<SourceCoverageView> View)
61 : FunctionName(FunctionName), Line(Line), View(std::move(View)) {}
62
63 friend bool operator<(const InstantiationView &LHS,
64 const InstantiationView &RHS) {
65 return LHS.Line < RHS.Line;
66 }
67};
68
Vedant Kumar9cbad2c2016-06-28 16:12:24 +000069/// \brief A file manager that handles format-aware file creation.
70class CoveragePrinter {
Vedant Kumar9cbad2c2016-06-28 16:12:24 +000071public:
72 struct StreamDestructor {
73 void operator()(raw_ostream *OS) const;
74 };
75
76 using OwnedStream = std::unique_ptr<raw_ostream, StreamDestructor>;
77
78protected:
Vedant Kumarc076c492016-07-21 23:26:15 +000079 const CoverageViewOptions &Opts;
80
Vedant Kumar9cbad2c2016-06-28 16:12:24 +000081 CoveragePrinter(const CoverageViewOptions &Opts) : Opts(Opts) {}
82
Vedant Kumard6d192c2016-06-29 21:55:46 +000083 /// \brief Return `OutputDir/ToplevelDir/Path.Extension`. If \p InToplevel is
84 /// false, skip the ToplevelDir component. If \p Relative is false, skip the
85 /// OutputDir component.
Vedant Kumar9cbad2c2016-06-28 16:12:24 +000086 std::string getOutputPath(StringRef Path, StringRef Extension,
Vedant Kumaraae0ba72016-09-09 01:32:51 +000087 bool InToplevel, bool Relative = true) const;
Vedant Kumar9cbad2c2016-06-28 16:12:24 +000088
89 /// \brief If directory output is enabled, create a file in that directory
90 /// at the path given by getOutputPath(). Otherwise, return stdout.
91 Expected<OwnedStream> createOutputStream(StringRef Path, StringRef Extension,
Vedant Kumaraae0ba72016-09-09 01:32:51 +000092 bool InToplevel) const;
Vedant Kumar9cbad2c2016-06-28 16:12:24 +000093
94 /// \brief Return the sub-directory name for file coverage reports.
95 static StringRef getCoverageDir() { return "coverage"; }
96
97public:
98 static std::unique_ptr<CoveragePrinter>
99 create(const CoverageViewOptions &Opts);
100
101 virtual ~CoveragePrinter() {}
102
103 /// @name File Creation Interface
104 /// @{
105
106 /// \brief Create a file to print a coverage view into.
107 virtual Expected<OwnedStream> createViewFile(StringRef Path,
108 bool InToplevel) = 0;
109
110 /// \brief Close a file which has been used to print a coverage view.
111 virtual void closeViewFile(OwnedStream OS) = 0;
112
113 /// \brief Create an index which lists reports for the given source files.
Vedant Kumarbc647982016-09-23 18:57:32 +0000114 virtual Error createIndexFile(ArrayRef<std::string> SourceFiles,
Sean Evesonfa8ef352017-09-28 10:07:30 +0000115 const coverage::CoverageMapping &Coverage,
Sean Evesond932b2d2017-10-03 11:05:28 +0000116 const CoverageFiltersMatchAll &Filters) = 0;
Vedant Kumar9cbad2c2016-06-28 16:12:24 +0000117
118 /// @}
119};
120
Vedant Kumaree5a5e92016-06-25 05:48:54 +0000121/// \brief A code coverage view of a source file or function.
122///
123/// A source coverage view and its nested sub-views form a file-oriented
124/// representation of code coverage data. This view can be printed out by a
Vedant Kumar9cbad2c2016-06-28 16:12:24 +0000125/// renderer which implements the Rendering Interface.
Alex Lorenze82d89c2014-08-22 22:56:03 +0000126class SourceCoverageView {
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000127 /// A function or file name.
128 StringRef SourceName;
129
130 /// A memory buffer backing the source on display.
Alex Lorenze82d89c2014-08-22 22:56:03 +0000131 const MemoryBuffer &File;
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000132
133 /// Various options to guide the coverage renderer.
Alex Lorenze82d89c2014-08-22 22:56:03 +0000134 const CoverageViewOptions &Options;
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000135
136 /// Complete coverage information about the source on display.
Justin Bogner953e2402014-09-20 15:31:56 +0000137 coverage::CoverageData CoverageInfo;
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000138
139 /// A container for all expansions (e.g macros) in the source on display.
Justin Bogner5e1400a2014-09-17 05:33:20 +0000140 std::vector<ExpansionView> ExpansionSubViews;
Vedant Kumar9d70d0b2016-06-24 00:34:51 +0000141
142 /// A container for all instantiations (e.g template functions) in the source
143 /// on display.
Justin Bogner5e1400a2014-09-17 05:33:20 +0000144 std::vector<InstantiationView> InstantiationSubViews;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000145
Ying Yid36b47c2016-09-06 19:31:18 +0000146 /// Get the first uncovered line number for the source file.
147 unsigned getFirstUncoveredLineNo();
148
Vedant Kumarf9151b92016-06-25 02:58:30 +0000149protected:
150 struct LineRef {
151 StringRef Line;
152 int64_t LineNo;
153
154 LineRef(StringRef Line, int64_t LineNo) : Line(Line), LineNo(LineNo) {}
155 };
156
157 using CoverageSegmentArray = ArrayRef<const coverage::CoverageSegment *>;
158
159 /// @name Rendering Interface
160 /// @{
161
Vedant Kumar8d74cb22016-06-29 00:38:21 +0000162 /// \brief Render a header for the view.
163 virtual void renderViewHeader(raw_ostream &OS) = 0;
164
165 /// \brief Render a footer for the view.
166 virtual void renderViewFooter(raw_ostream &OS) = 0;
167
Vedant Kumarf9151b92016-06-25 02:58:30 +0000168 /// \brief Render the source name for the view.
Vedant Kumarb1c174a2016-09-10 19:37:26 +0000169 virtual void renderSourceName(raw_ostream &OS, bool WholeFile) = 0;
Vedant Kumarf9151b92016-06-25 02:58:30 +0000170
171 /// \brief Render the line prefix at the given \p ViewDepth.
172 virtual void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) = 0;
173
Vedant Kumar8d74cb22016-06-29 00:38:21 +0000174 /// \brief Render the line suffix at the given \p ViewDepth.
175 virtual void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) = 0;
176
Vedant Kumarf9151b92016-06-25 02:58:30 +0000177 /// \brief Render a view divider at the given \p ViewDepth.
178 virtual void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) = 0;
179
Alex Lorenze82d89c2014-08-22 22:56:03 +0000180 /// \brief Render a source line with highlighting.
Vedant Kumarf9151b92016-06-25 02:58:30 +0000181 virtual void renderLine(raw_ostream &OS, LineRef L,
182 const coverage::CoverageSegment *WrappedSegment,
183 CoverageSegmentArray Segments, unsigned ExpansionCol,
184 unsigned ViewDepth) = 0;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000185
186 /// \brief Render the line's execution count column.
Vedant Kumarf9151b92016-06-25 02:58:30 +0000187 virtual void renderLineCoverageColumn(raw_ostream &OS,
188 const LineCoverageStats &Line) = 0;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000189
190 /// \brief Render the line number column.
Vedant Kumarf9151b92016-06-25 02:58:30 +0000191 virtual void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) = 0;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000192
193 /// \brief Render all the region's execution counts on a line.
Vedant Kumarf9151b92016-06-25 02:58:30 +0000194 virtual void renderRegionMarkers(raw_ostream &OS,
195 CoverageSegmentArray Segments,
196 unsigned ViewDepth) = 0;
Alex Lorenze82d89c2014-08-22 22:56:03 +0000197
Vedant Kumar861a19c2016-06-26 02:45:13 +0000198 /// \brief Render the site of an expansion.
199 virtual void
Vedant Kumar8d74cb22016-06-29 00:38:21 +0000200 renderExpansionSite(raw_ostream &OS, LineRef L,
Vedant Kumar8b12ecb2016-06-25 05:48:59 +0000201 const coverage::CoverageSegment *WrappedSegment,
202 CoverageSegmentArray Segments, 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 Kumar0053c0b2016-09-08 00:56:48 +0000235 coverage::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,
242 const CoverageViewOptions &Options,
Vedant Kumar0053c0b2016-09-08 00:56:48 +0000243 coverage::CoverageData &&CoverageInfo);
Vedant Kumarf9151b92016-06-25 02:58:30 +0000244
245 virtual ~SourceCoverageView() {}
246
Ying Yi24e91bd2016-09-06 21:41:38 +0000247 /// \brief Return the source name formatted for the host OS.
Vedant Kumar0053c0b2016-09-08 00:56:48 +0000248 std::string getSourceName() const;
Ying Yi24e91bd2016-09-06 21:41:38 +0000249
Alex Lorenze82d89c2014-08-22 22:56:03 +0000250 const CoverageViewOptions &getOptions() const { return Options; }
251
Justin Bogner5e1400a2014-09-17 05:33:20 +0000252 /// \brief Add an expansion subview to this view.
253 void addExpansion(const coverage::CounterMappingRegion &Region,
Vedant Kumarf9151b92016-06-25 02:58:30 +0000254 std::unique_ptr<SourceCoverageView> View);
Alex Lorenze82d89c2014-08-22 22:56:03 +0000255
Justin Bogner5e1400a2014-09-17 05:33:20 +0000256 /// \brief Add a function instantiation subview to this view.
257 void addInstantiation(StringRef FunctionName, unsigned Line,
Vedant Kumarf9151b92016-06-25 02:58:30 +0000258 std::unique_ptr<SourceCoverageView> View);
Alex Lorenze82d89c2014-08-22 22:56:03 +0000259
Vedant Kumarf9151b92016-06-25 02:58:30 +0000260 /// \brief Print the code coverage information for a specific portion of a
261 /// source file to the output stream.
262 void print(raw_ostream &OS, bool WholeFile, bool ShowSourceName,
Sean Evesonfa8ef352017-09-28 10:07:30 +0000263 bool ShowTitle, unsigned ViewDepth = 0);
Alex Lorenze82d89c2014-08-22 22:56:03 +0000264};
265
266} // namespace llvm
267
268#endif // LLVM_COV_SOURCECOVERAGEVIEW_H