llvm-cov: Distinguish expansion/instantiation from SourceCoverageView

SourceCoverageView currently has "Kind" and a list of child views, all
of which must have either an expansion or an instantiation Kind. In
addition to being an error-prone design, this makes it awkward to
differentiate between the two child types and adds a number of
optionally used members to the type.

Split the subview types into their own separate objects, and maintain
lists of each rather than one combined "Children" list.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217940 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Justin Bogner
2014-09-17 05:33:20 +00:00
parent d5f73530de
commit d1b4e60339
3 changed files with 108 additions and 113 deletions

View File

@ -282,8 +282,8 @@ void CodeCoverageTool::createExpansionSubView(
getSourceFile(Function.Filenames[ExpandedRegion.ExpandedFileID]); getSourceFile(Function.Filenames[ExpandedRegion.ExpandedFileID]);
if (!SourceBuffer) if (!SourceBuffer)
return; return;
auto SubView = llvm::make_unique<SourceCoverageView>( auto SubView = llvm::make_unique<SourceCoverageView>(SourceBuffer.get(),
SourceBuffer.get(), Parent.getOptions(), ExpandedRegion); Parent.getOptions());
SourceCoverageDataManager RegionManager; SourceCoverageDataManager RegionManager;
for (const auto &CR : Function.CountedRegions) { for (const auto &CR : Function.CountedRegions) {
if (CR.FileID == ExpandedRegion.ExpandedFileID) if (CR.FileID == ExpandedRegion.ExpandedFileID)
@ -291,7 +291,7 @@ void CodeCoverageTool::createExpansionSubView(
} }
SubView->load(RegionManager); SubView->load(RegionManager);
createExpansionSubViews(*SubView, ExpandedRegion.ExpandedFileID, Function); createExpansionSubViews(*SubView, ExpandedRegion.ExpandedFileID, Function);
Parent.addChild(std::move(SubView)); Parent.addExpansion(ExpandedRegion, std::move(SubView));
} }
void CodeCoverageTool::createExpansionSubViews( void CodeCoverageTool::createExpansionSubViews(
@ -362,10 +362,18 @@ bool CodeCoverageTool::createSourceFileView(
if (InstantiationSet.second.size() < 2) if (InstantiationSet.second.size() < 2)
continue; continue;
for (auto Function : InstantiationSet.second) { for (auto Function : InstantiationSet.second) {
auto SubView = unsigned FileID = Function->CountedRegions.front().FileID;
llvm::make_unique<SourceCoverageView>(View, Function->Name); unsigned Line = 0;
for (const auto &CR : Function->CountedRegions)
if (CR.FileID == FileID)
Line = std::max(CR.LineEnd, Line);
auto SourceBuffer = getSourceFile(Function->Filenames[FileID]);
if (!SourceBuffer)
continue;
auto SubView = llvm::make_unique<SourceCoverageView>(SourceBuffer.get(),
View.getOptions());
createInstantiationSubView(SourceFile, *Function, *SubView); createInstantiationSubView(SourceFile, *Function, *SubView);
View.addChild(std::move(SubView)); View.addInstantiation(Function->Name, Line, std::move(SubView));
} }
} }
return false; return false;

View File

@ -140,10 +140,12 @@ void SourceCoverageView::renderRegionMarkers(raw_ostream &OS,
/// \brief Insert a new highlighting range into the line's highlighting ranges /// \brief Insert a new highlighting range into the line's highlighting ranges
/// Return line's new highlighting ranges in result. /// Return line's new highlighting ranges in result.
static void insertHighlightRange( static void insertExpansionHighlightRange(
ArrayRef<SourceCoverageView::HighlightRange> Ranges, ArrayRef<SourceCoverageView::HighlightRange> Ranges,
SourceCoverageView::HighlightRange RangeToInsert, unsigned Line, unsigned StartCol, unsigned EndCol,
SmallVectorImpl<SourceCoverageView::HighlightRange> &Result) { SmallVectorImpl<SourceCoverageView::HighlightRange> &Result) {
auto RangeToInsert = SourceCoverageView::HighlightRange(
Line, StartCol, EndCol, SourceCoverageView::HighlightRange::Expanded);
Result.clear(); Result.clear();
size_t I = 0; size_t I = 0;
auto E = Ranges.size(); auto E = Ranges.size();
@ -189,22 +191,6 @@ static void insertHighlightRange(
Result.push_back(Ranges[I]); Result.push_back(Ranges[I]);
} }
void SourceCoverageView::sortChildren() {
for (auto &I : Children)
I->sortChildren();
std::sort(Children.begin(), Children.end(),
[](const std::unique_ptr<SourceCoverageView> &LHS,
const std::unique_ptr<SourceCoverageView> &RHS) {
return LHS->ExpansionRegion < RHS->ExpansionRegion;
});
}
SourceCoverageView::HighlightRange
SourceCoverageView::getExpansionHighlightRange() const {
return HighlightRange(ExpansionRegion.LineStart, ExpansionRegion.ColumnStart,
ExpansionRegion.ColumnEnd, HighlightRange::Expanded);
}
template <typename T> template <typename T>
ArrayRef<T> gatherLineItems(size_t &CurrentIdx, const std::vector<T> &Items, ArrayRef<T> gatherLineItems(size_t &CurrentIdx, const std::vector<T> &Items,
unsigned LineNo) { unsigned LineNo) {
@ -215,24 +201,8 @@ ArrayRef<T> gatherLineItems(size_t &CurrentIdx, const std::vector<T> &Items,
return ArrayRef<T>(Items.data() + PrevIdx, CurrentIdx - PrevIdx); return ArrayRef<T>(Items.data() + PrevIdx, CurrentIdx - PrevIdx);
} }
ArrayRef<std::unique_ptr<SourceCoverageView>>
gatherLineSubViews(size_t &CurrentIdx,
ArrayRef<std::unique_ptr<SourceCoverageView>> Items,
unsigned LineNo) {
auto PrevIdx = CurrentIdx;
auto E = Items.size();
while (CurrentIdx < E &&
Items[CurrentIdx]->getSubViewsExpansionLine() == LineNo)
++CurrentIdx;
return Items.slice(PrevIdx, CurrentIdx - PrevIdx);
}
void SourceCoverageView::render(raw_ostream &OS, unsigned IndentLevel) { void SourceCoverageView::render(raw_ostream &OS, unsigned IndentLevel) {
// Make sure that the children are in sorted order.
sortChildren();
SmallVector<HighlightRange, 8> AdjustedLineHighlightRanges; SmallVector<HighlightRange, 8> AdjustedLineHighlightRanges;
size_t CurrentChild = 0;
size_t CurrentHighlightRange = 0; size_t CurrentHighlightRange = 0;
size_t CurrentRegionMarker = 0; size_t CurrentRegionMarker = 0;
@ -249,12 +219,18 @@ void SourceCoverageView::render(raw_ostream &OS, unsigned IndentLevel) {
// subviews. // subviews.
unsigned DividerWidth = CombinedColumnWidth + 4; unsigned DividerWidth = CombinedColumnWidth + 4;
// We need the expansions and instantiations sorted so we can go through them
// while we iterate lines.
std::sort(ExpansionSubViews.begin(), ExpansionSubViews.end());
std::sort(InstantiationSubViews.begin(), InstantiationSubViews.end());
auto NextESV = ExpansionSubViews.begin();
auto EndESV = ExpansionSubViews.end();
auto NextISV = InstantiationSubViews.begin();
auto EndISV = InstantiationSubViews.end();
for (size_t I = 0, E = LineStats.size(); I < E; ++I) { for (size_t I = 0, E = LineStats.size(); I < E; ++I) {
unsigned LineNo = I + LineOffset; unsigned LineNo = I + LineOffset;
// Gather the child subviews that are visible on this line.
auto LineSubViews = gatherLineSubViews(CurrentChild, Children, LineNo);
renderIndent(OS, IndentLevel); renderIndent(OS, IndentLevel);
if (Options.ShowLineStats) if (Options.ShowLineStats)
renderLineCoverageColumn(OS, LineStats[I]); renderLineCoverageColumn(OS, LineStats[I]);
@ -267,11 +243,10 @@ void SourceCoverageView::render(raw_ostream &OS, unsigned IndentLevel) {
auto LineRanges = LineHighlightRanges; auto LineRanges = LineHighlightRanges;
// Highlight the expansion range if there is an expansion subview on this // Highlight the expansion range if there is an expansion subview on this
// line. // line.
if (!LineSubViews.empty() && LineSubViews.front()->isExpansionSubView() && if (NextESV != EndESV && NextESV->getLine() == LineNo && Options.Colors) {
Options.Colors) { insertExpansionHighlightRange(
insertHighlightRange(LineHighlightRanges, LineHighlightRanges, NextESV->getLine(), NextESV->getStartCol(),
LineSubViews.front()->getExpansionHighlightRange(), NextESV->getEndCol(), AdjustedLineHighlightRanges);
AdjustedLineHighlightRanges);
LineRanges = AdjustedLineHighlightRanges; LineRanges = AdjustedLineHighlightRanges;
} }
@ -294,40 +269,40 @@ void SourceCoverageView::render(raw_ostream &OS, unsigned IndentLevel) {
renderRegionMarkers(OS, LineMarkers); renderRegionMarkers(OS, LineMarkers);
} }
// Show the line's expanded child subviews. // Show the expansions and instantiations for this line.
bool FirstChildExpansion = true;
if (LineSubViews.empty())
continue;
unsigned NestedIndent = IndentLevel + 1; unsigned NestedIndent = IndentLevel + 1;
renderViewDivider(NestedIndent, DividerWidth, OS); bool RenderedSubView = false;
OS << "\n"; for (; NextESV != EndESV && NextESV->getLine() == LineNo; ++NextESV) {
for (const auto &Child : LineSubViews) { renderViewDivider(NestedIndent, DividerWidth, OS);
// If this subview shows a function instantiation, render the function's OS << "\n";
// name. if (RenderedSubView) {
if (Child->isInstantiationSubView()) { // Re-render the current line and highlight the expansion range for
renderIndent(OS, NestedIndent); // this subview.
OS << ' '; insertExpansionHighlightRange(
Options.colored_ostream(OS, raw_ostream::CYAN) << Child->FunctionName LineHighlightRanges, NextESV->getLine(), NextESV->getStartCol(),
<< ":"; NextESV->getEndCol(), AdjustedLineHighlightRanges);
renderIndent(OS, IndentLevel);
OS.indent(CombinedColumnWidth + (IndentLevel == 0 ? 0 : 1));
renderLine(OS, Line, AdjustedLineHighlightRanges);
renderViewDivider(NestedIndent, DividerWidth, OS);
OS << "\n"; OS << "\n";
} else {
if (!FirstChildExpansion) {
// Re-render the current line and highlight the expansion range for
// this
// subview.
insertHighlightRange(LineHighlightRanges,
Child->getExpansionHighlightRange(),
AdjustedLineHighlightRanges);
renderIndent(OS, IndentLevel);
OS.indent(CombinedColumnWidth + (IndentLevel == 0 ? 0 : 1));
renderLine(OS, Line, AdjustedLineHighlightRanges);
renderViewDivider(NestedIndent, DividerWidth, OS);
OS << "\n";
} else
FirstChildExpansion = false;
} }
// Render the child subview // Render the child subview
Child->render(OS, NestedIndent); NextESV->View->render(OS, NestedIndent);
RenderedSubView = true;
}
for (; NextISV != EndISV && NextISV->Line == LineNo; ++NextISV) {
renderViewDivider(NestedIndent, DividerWidth, OS);
OS << "\n";
renderIndent(OS, NestedIndent);
OS << ' ';
Options.colored_ostream(OS, raw_ostream::CYAN) << NextISV->FunctionName
<< ":";
OS << "\n";
NextISV->View->render(OS, NestedIndent);
RenderedSubView = true;
}
if (RenderedSubView) {
renderViewDivider(NestedIndent, DividerWidth, OS); renderViewDivider(NestedIndent, DividerWidth, OS);
OS << "\n"; OS << "\n";
} }

View File

@ -22,12 +22,46 @@
namespace llvm { 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)) {}
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)) {}
friend bool operator<(const InstantiationView &LHS,
const InstantiationView &RHS) {
return LHS.Line < RHS.Line;
}
};
/// \brief A code coverage view of a specific source file. /// \brief A code coverage view of a specific source file.
/// It can have embedded coverage views. /// It can have embedded coverage views.
class SourceCoverageView { class SourceCoverageView {
public: public:
enum SubViewKind { View, ExpansionView, InstantiationView };
/// \brief Coverage information for a single line. /// \brief Coverage information for a single line.
struct LineCoverageInfo { struct LineCoverageInfo {
uint64_t ExecutionCount; uint64_t ExecutionCount;
@ -111,13 +145,11 @@ private:
const MemoryBuffer &File; const MemoryBuffer &File;
const CoverageViewOptions &Options; const CoverageViewOptions &Options;
unsigned LineOffset; unsigned LineOffset;
SubViewKind Kind; std::vector<ExpansionView> ExpansionSubViews;
coverage::CounterMappingRegion ExpansionRegion; std::vector<InstantiationView> InstantiationSubViews;
std::vector<std::unique_ptr<SourceCoverageView>> Children;
std::vector<LineCoverageInfo> LineStats; std::vector<LineCoverageInfo> LineStats;
std::vector<HighlightRange> HighlightRanges; std::vector<HighlightRange> HighlightRanges;
std::vector<RegionMarker> Markers; std::vector<RegionMarker> Markers;
StringRef FunctionName;
/// \brief Initialize the visible source range for this view. /// \brief Initialize the visible source range for this view.
void setUpVisibleRange(SourceCoverageDataManager &Data); void setUpVisibleRange(SourceCoverageDataManager &Data);
@ -131,12 +163,6 @@ private:
/// \brief Create the region markers using the coverage data. /// \brief Create the region markers using the coverage data.
void createRegionMarkers(SourceCoverageDataManager &Data); void createRegionMarkers(SourceCoverageDataManager &Data);
/// \brief Sort children by the starting location.
void sortChildren();
/// \brief Return a highlight range for the expansion region of this view.
HighlightRange getExpansionHighlightRange() const;
/// \brief Render a source line with highlighting. /// \brief Render a source line with highlighting.
void renderLine(raw_ostream &OS, StringRef Line, void renderLine(raw_ostream &OS, StringRef Line,
ArrayRef<HighlightRange> Ranges); ArrayRef<HighlightRange> Ranges);
@ -160,34 +186,20 @@ private:
public: public:
SourceCoverageView(const MemoryBuffer &File, SourceCoverageView(const MemoryBuffer &File,
const CoverageViewOptions &Options) const CoverageViewOptions &Options)
: File(File), Options(Options), LineOffset(0), Kind(View), : File(File), Options(Options), LineOffset(0) {}
ExpansionRegion(coverage::Counter(), 0, 0, 0, 0, 0) {}
SourceCoverageView(SourceCoverageView &Parent, StringRef FunctionName)
: File(Parent.File), Options(Parent.Options), LineOffset(0),
Kind(InstantiationView),
ExpansionRegion(coverage::Counter(), 0, 0, 0, 0, 0),
FunctionName(FunctionName) {}
SourceCoverageView(const MemoryBuffer &File,
const CoverageViewOptions &Options,
const coverage::CounterMappingRegion &ExpansionRegion)
: File(File), Options(Options), LineOffset(0), Kind(ExpansionView),
ExpansionRegion(ExpansionRegion) {}
const CoverageViewOptions &getOptions() const { return Options; } const CoverageViewOptions &getOptions() const { return Options; }
bool isExpansionSubView() const { return Kind == ExpansionView; } /// \brief Add an expansion subview to this view.
void addExpansion(const coverage::CounterMappingRegion &Region,
bool isInstantiationSubView() const { return Kind == InstantiationView; } std::unique_ptr<SourceCoverageView> View) {
ExpansionSubViews.emplace_back(Region, std::move(View));
/// \brief Return the line number after which the subview expansion is shown.
unsigned getSubViewsExpansionLine() const {
return ExpansionRegion.LineStart;
} }
void addChild(std::unique_ptr<SourceCoverageView> View) { /// \brief Add a function instantiation subview to this view.
Children.push_back(std::move(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 /// \brief Print the code coverage information for a specific