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