llvm-6502/tools/llvm-cov/SourceCoverageView.h
Justin Bogner b3edb56485 llvm-cov: Rework the API for getting the coverage of a file (NFC)
This encapsulates how we handle the coverage regions of a file or
function. In the old model, the user had to deal with nested regions,
so they needed to maintain their own auxiliary data structures to get
any useful information out of this. The new API provides a sequence of
non-overlapping coverage segments, which makes it possible to render
coverage information in a single pass and avoids a fair amount of
extra work.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217975 91177308-0d34-0410-b5e6-96231b3b80d8
2014-09-17 18:23:47 +00:00

168 lines
5.6 KiB
C++

//===- SourceCoverageView.h - Code coverage view for source code ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class implements rendering for code coverage of source code.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_COV_SOURCECOVERAGEVIEW_H
#define LLVM_COV_SOURCECOVERAGEVIEW_H
#include "CoverageViewOptions.h"
#include "SourceCoverageDataManager.h"
#include "llvm/ProfileData/CoverageMapping.h"
#include "llvm/Support/MemoryBuffer.h"
#include <vector>
namespace llvm {
class SourceCoverageView;
/// \brief A view that represents a macro or include expansion
struct ExpansionView {
coverage::CounterMappingRegion Region;
std::unique_ptr<SourceCoverageView> View;
ExpansionView(const coverage::CounterMappingRegion &Region,
std::unique_ptr<SourceCoverageView> View)
: Region(Region), View(std::move(View)) {}
ExpansionView(ExpansionView &&RHS)
: Region(std::move(RHS.Region)), View(std::move(RHS.View)) {}
ExpansionView &operator=(ExpansionView &&RHS) {
Region = std::move(RHS.Region);
View = std::move(RHS.View);
return *this;
}
unsigned getLine() const { return Region.LineStart; }
unsigned getStartCol() const { return Region.ColumnStart; }
unsigned getEndCol() const { return Region.ColumnEnd; }
friend bool operator<(const ExpansionView &LHS, const ExpansionView &RHS) {
return LHS.Region.startLoc() < RHS.Region.startLoc();
}
};
/// \brief A view that represents a function instantiation
struct InstantiationView {
StringRef FunctionName;
unsigned Line;
std::unique_ptr<SourceCoverageView> View;
InstantiationView(StringRef FunctionName, unsigned Line,
std::unique_ptr<SourceCoverageView> View)
: FunctionName(FunctionName), Line(Line), View(std::move(View)) {}
InstantiationView(InstantiationView &&RHS)
: FunctionName(std::move(RHS.FunctionName)), Line(std::move(RHS.Line)),
View(std::move(RHS.View)) {}
InstantiationView &operator=(InstantiationView &&RHS) {
FunctionName = std::move(RHS.FunctionName);
Line = std::move(RHS.Line);
View = std::move(RHS.View);
return *this;
}
friend bool operator<(const InstantiationView &LHS,
const InstantiationView &RHS) {
return LHS.Line < RHS.Line;
}
};
/// \brief A code coverage view of a specific source file.
/// It can have embedded coverage views.
class SourceCoverageView {
private:
/// \brief Coverage information for a single line.
struct LineCoverageInfo {
uint64_t ExecutionCount;
unsigned RegionCount;
bool Mapped;
LineCoverageInfo() : ExecutionCount(0), RegionCount(0), Mapped(false) {}
bool isMapped() const { return Mapped; }
bool hasMultipleRegions() const { return RegionCount > 1; }
void addRegionStartCount(uint64_t Count) {
Mapped = true;
ExecutionCount = Count;
++RegionCount;
}
void addRegionCount(uint64_t Count) {
Mapped = true;
if (!RegionCount)
ExecutionCount = Count;
}
};
const MemoryBuffer &File;
const CoverageViewOptions &Options;
std::unique_ptr<SourceCoverageDataManager> RegionManager;
std::vector<ExpansionView> ExpansionSubViews;
std::vector<InstantiationView> InstantiationSubViews;
/// \brief Render a source line with highlighting.
void renderLine(raw_ostream &OS, StringRef Line, int64_t LineNumber,
const CoverageSegment *WrappedSegment,
ArrayRef<const CoverageSegment *> Segments,
unsigned ExpansionCol);
void renderIndent(raw_ostream &OS, unsigned Level);
void renderViewDivider(unsigned Offset, unsigned Length, raw_ostream &OS);
/// \brief Render the line's execution count column.
void renderLineCoverageColumn(raw_ostream &OS, const LineCoverageInfo &Line);
/// \brief Render the line number column.
void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo);
/// \brief Render all the region's execution counts on a line.
void renderRegionMarkers(raw_ostream &OS,
ArrayRef<const CoverageSegment *> Segments);
static const unsigned LineCoverageColumnWidth = 7;
static const unsigned LineNumberColumnWidth = 5;
public:
SourceCoverageView(const MemoryBuffer &File,
const CoverageViewOptions &Options)
: File(File), Options(Options) {}
const CoverageViewOptions &getOptions() const { return Options; }
/// \brief Add an expansion subview to this view.
void addExpansion(const coverage::CounterMappingRegion &Region,
std::unique_ptr<SourceCoverageView> View) {
ExpansionSubViews.emplace_back(Region, std::move(View));
}
/// \brief Add a function instantiation subview to this view.
void addInstantiation(StringRef FunctionName, unsigned Line,
std::unique_ptr<SourceCoverageView> View) {
InstantiationSubViews.emplace_back(FunctionName, Line, std::move(View));
}
/// \brief Print the code coverage information for a specific
/// portion of a source file to the output stream.
void render(raw_ostream &OS, bool WholeFile, unsigned IndentLevel = 0);
/// \brief Load the coverage information required for rendering
/// from the mapping regions in the data manager.
void load(std::unique_ptr<SourceCoverageDataManager> Data) {
RegionManager = std::move(Data);
}
};
} // namespace llvm
#endif // LLVM_COV_SOURCECOVERAGEVIEW_H