llvm-cov: Rework the API for getting the coverage of a file (NFC)
[oota-llvm.git] / tools / llvm-cov / SourceCoverageView.h
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 // This class implements rendering for code coverage of source code.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_COV_SOURCECOVERAGEVIEW_H
15 #define LLVM_COV_SOURCECOVERAGEVIEW_H
16
17 #include "CoverageViewOptions.h"
18 #include "SourceCoverageDataManager.h"
19 #include "llvm/ProfileData/CoverageMapping.h"
20 #include "llvm/Support/MemoryBuffer.h"
21 #include <vector>
22
23 namespace llvm {
24
25 class SourceCoverageView;
26
27 /// \brief A view that represents a macro or include expansion
28 struct 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)) {}
35   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   }
42
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
52 /// \brief A view that represents a function instantiation
53 struct 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   InstantiationView(InstantiationView &&RHS)
62       : FunctionName(std::move(RHS.FunctionName)), Line(std::move(RHS.Line)),
63         View(std::move(RHS.View)) {}
64   InstantiationView &operator=(InstantiationView &&RHS) {
65     FunctionName = std::move(RHS.FunctionName);
66     Line = std::move(RHS.Line);
67     View = std::move(RHS.View);
68     return *this;
69   }
70
71   friend bool operator<(const InstantiationView &LHS,
72                         const InstantiationView &RHS) {
73     return LHS.Line < RHS.Line;
74   }
75 };
76
77 /// \brief A code coverage view of a specific source file.
78 /// It can have embedded coverage views.
79 class SourceCoverageView {
80 private:
81   /// \brief Coverage information for a single line.
82   struct LineCoverageInfo {
83     uint64_t ExecutionCount;
84     unsigned RegionCount;
85     bool Mapped;
86
87     LineCoverageInfo() : ExecutionCount(0), RegionCount(0), Mapped(false) {}
88
89     bool isMapped() const { return Mapped; }
90
91     bool hasMultipleRegions() const { return RegionCount > 1; }
92
93     void addRegionStartCount(uint64_t Count) {
94       Mapped = true;
95       ExecutionCount = Count;
96       ++RegionCount;
97     }
98
99     void addRegionCount(uint64_t Count) {
100       Mapped = true;
101       if (!RegionCount)
102         ExecutionCount = Count;
103     }
104   };
105
106   const MemoryBuffer &File;
107   const CoverageViewOptions &Options;
108   std::unique_ptr<SourceCoverageDataManager> RegionManager;
109   std::vector<ExpansionView> ExpansionSubViews;
110   std::vector<InstantiationView> InstantiationSubViews;
111
112   /// \brief Render a source line with highlighting.
113   void renderLine(raw_ostream &OS, StringRef Line, int64_t LineNumber,
114                   const CoverageSegment *WrappedSegment,
115                   ArrayRef<const CoverageSegment *> Segments,
116                   unsigned ExpansionCol);
117
118   void renderIndent(raw_ostream &OS, unsigned Level);
119
120   void renderViewDivider(unsigned Offset, unsigned Length, raw_ostream &OS);
121
122   /// \brief Render the line's execution count column.
123   void renderLineCoverageColumn(raw_ostream &OS, const LineCoverageInfo &Line);
124
125   /// \brief Render the line number column.
126   void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo);
127
128   /// \brief Render all the region's execution counts on a line.
129   void renderRegionMarkers(raw_ostream &OS,
130                            ArrayRef<const CoverageSegment *> Segments);
131
132   static const unsigned LineCoverageColumnWidth = 7;
133   static const unsigned LineNumberColumnWidth = 5;
134
135 public:
136   SourceCoverageView(const MemoryBuffer &File,
137                      const CoverageViewOptions &Options)
138       : File(File), Options(Options) {}
139
140   const CoverageViewOptions &getOptions() const { return Options; }
141
142   /// \brief Add an expansion subview to this view.
143   void addExpansion(const coverage::CounterMappingRegion &Region,
144                     std::unique_ptr<SourceCoverageView> View) {
145     ExpansionSubViews.emplace_back(Region, std::move(View));
146   }
147
148   /// \brief Add a function instantiation subview to this view.
149   void addInstantiation(StringRef FunctionName, unsigned Line,
150                         std::unique_ptr<SourceCoverageView> View) {
151     InstantiationSubViews.emplace_back(FunctionName, Line, std::move(View));
152   }
153
154   /// \brief Print the code coverage information for a specific
155   /// portion of a source file to the output stream.
156   void render(raw_ostream &OS, bool WholeFile, unsigned IndentLevel = 0);
157
158   /// \brief Load the coverage information required for rendering
159   /// from the mapping regions in the data manager.
160   void load(std::unique_ptr<SourceCoverageDataManager> Data) {
161     RegionManager = std::move(Data);
162   }
163 };
164
165 } // namespace llvm
166
167 #endif // LLVM_COV_SOURCECOVERAGEVIEW_H