1277323Sdim//===- SourceCoverageView.h - Code coverage view for source code ----------===//
2277323Sdim//
3277323Sdim//                     The LLVM Compiler Infrastructure
4277323Sdim//
5277323Sdim// This file is distributed under the University of Illinois Open Source
6277323Sdim// License. See LICENSE.TXT for details.
7277323Sdim//
8277323Sdim//===----------------------------------------------------------------------===//
9277323Sdim//
10277323Sdim// This class implements rendering for code coverage of source code.
11277323Sdim//
12277323Sdim//===----------------------------------------------------------------------===//
13277323Sdim
14277323Sdim#ifndef LLVM_COV_SOURCECOVERAGEVIEW_H
15277323Sdim#define LLVM_COV_SOURCECOVERAGEVIEW_H
16277323Sdim
17277323Sdim#include "CoverageViewOptions.h"
18277323Sdim#include "llvm/ProfileData/CoverageMapping.h"
19277323Sdim#include "llvm/Support/MemoryBuffer.h"
20277323Sdim#include <vector>
21277323Sdim
22277323Sdimnamespace llvm {
23277323Sdim
24277323Sdimclass SourceCoverageView;
25277323Sdim
26277323Sdim/// \brief A view that represents a macro or include expansion
27277323Sdimstruct ExpansionView {
28277323Sdim  coverage::CounterMappingRegion Region;
29277323Sdim  std::unique_ptr<SourceCoverageView> View;
30277323Sdim
31277323Sdim  ExpansionView(const coverage::CounterMappingRegion &Region,
32277323Sdim                std::unique_ptr<SourceCoverageView> View)
33277323Sdim      : Region(Region), View(std::move(View)) {}
34277323Sdim  ExpansionView(ExpansionView &&RHS)
35277323Sdim      : Region(std::move(RHS.Region)), View(std::move(RHS.View)) {}
36277323Sdim  ExpansionView &operator=(ExpansionView &&RHS) {
37277323Sdim    Region = std::move(RHS.Region);
38277323Sdim    View = std::move(RHS.View);
39277323Sdim    return *this;
40277323Sdim  }
41277323Sdim
42277323Sdim  unsigned getLine() const { return Region.LineStart; }
43277323Sdim  unsigned getStartCol() const { return Region.ColumnStart; }
44277323Sdim  unsigned getEndCol() const { return Region.ColumnEnd; }
45277323Sdim
46277323Sdim  friend bool operator<(const ExpansionView &LHS, const ExpansionView &RHS) {
47277323Sdim    return LHS.Region.startLoc() < RHS.Region.startLoc();
48277323Sdim  }
49277323Sdim};
50277323Sdim
51277323Sdim/// \brief A view that represents a function instantiation
52277323Sdimstruct InstantiationView {
53277323Sdim  StringRef FunctionName;
54277323Sdim  unsigned Line;
55277323Sdim  std::unique_ptr<SourceCoverageView> View;
56277323Sdim
57277323Sdim  InstantiationView(StringRef FunctionName, unsigned Line,
58277323Sdim                    std::unique_ptr<SourceCoverageView> View)
59277323Sdim      : FunctionName(FunctionName), Line(Line), View(std::move(View)) {}
60277323Sdim  InstantiationView(InstantiationView &&RHS)
61277323Sdim      : FunctionName(std::move(RHS.FunctionName)), Line(std::move(RHS.Line)),
62277323Sdim        View(std::move(RHS.View)) {}
63277323Sdim  InstantiationView &operator=(InstantiationView &&RHS) {
64277323Sdim    FunctionName = std::move(RHS.FunctionName);
65277323Sdim    Line = std::move(RHS.Line);
66277323Sdim    View = std::move(RHS.View);
67277323Sdim    return *this;
68277323Sdim  }
69277323Sdim
70277323Sdim  friend bool operator<(const InstantiationView &LHS,
71277323Sdim                        const InstantiationView &RHS) {
72277323Sdim    return LHS.Line < RHS.Line;
73277323Sdim  }
74277323Sdim};
75277323Sdim
76277323Sdim/// \brief A code coverage view of a specific source file.
77277323Sdim/// It can have embedded coverage views.
78277323Sdimclass SourceCoverageView {
79277323Sdimprivate:
80277323Sdim  /// \brief Coverage information for a single line.
81277323Sdim  struct LineCoverageInfo {
82277323Sdim    uint64_t ExecutionCount;
83277323Sdim    unsigned RegionCount;
84277323Sdim    bool Mapped;
85277323Sdim
86277323Sdim    LineCoverageInfo() : ExecutionCount(0), RegionCount(0), Mapped(false) {}
87277323Sdim
88277323Sdim    bool isMapped() const { return Mapped; }
89277323Sdim
90277323Sdim    bool hasMultipleRegions() const { return RegionCount > 1; }
91277323Sdim
92277323Sdim    void addRegionStartCount(uint64_t Count) {
93288943Sdim      // The max of all region starts is the most interesting value.
94288943Sdim      addRegionCount(RegionCount ? std::max(ExecutionCount, Count) : Count);
95277323Sdim      ++RegionCount;
96277323Sdim    }
97277323Sdim
98277323Sdim    void addRegionCount(uint64_t Count) {
99277323Sdim      Mapped = true;
100288943Sdim      ExecutionCount = Count;
101277323Sdim    }
102277323Sdim  };
103277323Sdim
104277323Sdim  const MemoryBuffer &File;
105277323Sdim  const CoverageViewOptions &Options;
106277323Sdim  coverage::CoverageData CoverageInfo;
107277323Sdim  std::vector<ExpansionView> ExpansionSubViews;
108277323Sdim  std::vector<InstantiationView> InstantiationSubViews;
109277323Sdim
110277323Sdim  /// \brief Render a source line with highlighting.
111277323Sdim  void renderLine(raw_ostream &OS, StringRef Line, int64_t LineNumber,
112277323Sdim                  const coverage::CoverageSegment *WrappedSegment,
113277323Sdim                  ArrayRef<const coverage::CoverageSegment *> Segments,
114277323Sdim                  unsigned ExpansionCol);
115277323Sdim
116277323Sdim  void renderIndent(raw_ostream &OS, unsigned Level);
117277323Sdim
118277323Sdim  void renderViewDivider(unsigned Offset, unsigned Length, raw_ostream &OS);
119277323Sdim
120277323Sdim  /// \brief Render the line's execution count column.
121277323Sdim  void renderLineCoverageColumn(raw_ostream &OS, const LineCoverageInfo &Line);
122277323Sdim
123277323Sdim  /// \brief Render the line number column.
124277323Sdim  void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo);
125277323Sdim
126277323Sdim  /// \brief Render all the region's execution counts on a line.
127277323Sdim  void
128277323Sdim  renderRegionMarkers(raw_ostream &OS,
129277323Sdim                      ArrayRef<const coverage::CoverageSegment *> Segments);
130277323Sdim
131277323Sdim  static const unsigned LineCoverageColumnWidth = 7;
132277323Sdim  static const unsigned LineNumberColumnWidth = 5;
133277323Sdim
134277323Sdimpublic:
135277323Sdim  SourceCoverageView(const MemoryBuffer &File,
136277323Sdim                     const CoverageViewOptions &Options,
137277323Sdim                     coverage::CoverageData &&CoverageInfo)
138277323Sdim      : File(File), Options(Options), CoverageInfo(std::move(CoverageInfo)) {}
139277323Sdim
140277323Sdim  const CoverageViewOptions &getOptions() const { return Options; }
141277323Sdim
142277323Sdim  /// \brief Add an expansion subview to this view.
143277323Sdim  void addExpansion(const coverage::CounterMappingRegion &Region,
144277323Sdim                    std::unique_ptr<SourceCoverageView> View) {
145277323Sdim    ExpansionSubViews.emplace_back(Region, std::move(View));
146277323Sdim  }
147277323Sdim
148277323Sdim  /// \brief Add a function instantiation subview to this view.
149277323Sdim  void addInstantiation(StringRef FunctionName, unsigned Line,
150277323Sdim                        std::unique_ptr<SourceCoverageView> View) {
151277323Sdim    InstantiationSubViews.emplace_back(FunctionName, Line, std::move(View));
152277323Sdim  }
153277323Sdim
154277323Sdim  /// \brief Print the code coverage information for a specific
155277323Sdim  /// portion of a source file to the output stream.
156277323Sdim  void render(raw_ostream &OS, bool WholeFile, unsigned IndentLevel = 0);
157277323Sdim};
158277323Sdim
159277323Sdim} // namespace llvm
160277323Sdim
161277323Sdim#endif // LLVM_COV_SOURCECOVERAGEVIEW_H
162