void SourceCoverageDataManager::insert(const CountedRegion &CR) {
Regions.push_back(CR);
- Uniqued = false;
+ Segments.clear();
}
-ArrayRef<CountedRegion> SourceCoverageDataManager::getSourceRegions() {
- if (Uniqued || Regions.size() <= 1)
- return Regions;
-
- // Sort the regions given that they're all in the same file at this point.
- std::sort(Regions.begin(), Regions.end(),
- [](const CountedRegion &LHS, const CountedRegion &RHS) {
- return LHS.startLoc() < RHS.startLoc();
- });
-
- // Merge duplicate source ranges and sum their execution counts.
- auto Prev = Regions.begin();
- for (auto I = Prev + 1, E = Regions.end(); I != E; ++I) {
- if (I->startLoc() == Prev->startLoc() && I->endLoc() == Prev->endLoc()) {
- Prev->ExecutionCount += I->ExecutionCount;
- continue;
+namespace {
+class SegmentBuilder {
+ std::vector<CoverageSegment> Segments;
+ SmallVector<const CountedRegion *, 8> ActiveRegions;
+
+ /// Start a segment with no count specified.
+ void startSegment(unsigned Line, unsigned Col, bool IsRegionEntry) {
+ Segments.emplace_back(Line, Col, IsRegionEntry);
+ }
+
+ /// Start a segment with the given Region's count.
+ void startSegment(unsigned Line, unsigned Col, bool IsRegionEntry,
+ const CountedRegion &Region) {
+ if (Segments.empty())
+ Segments.emplace_back(Line, Col, IsRegionEntry);
+ CoverageSegment S = Segments.back();
+ // Avoid creating empty regions.
+ if (S.Line != Line || S.Col != Col) {
+ Segments.emplace_back(Line, Col, IsRegionEntry);
+ S = Segments.back();
+ }
+ // Set this region's count.
+ if (Region.Kind != coverage::CounterMappingRegion::SkippedRegion)
+ Segments.back().setCount(Region.ExecutionCount);
+ }
+
+ /// Start a segment for the given region.
+ void startSegment(const CountedRegion &Region) {
+ startSegment(Region.LineStart, Region.ColumnStart, true, Region);
+ }
+
+ /// Pop the top region off of the active stack, starting a new segment with
+ /// the containing Region's count.
+ void popRegion() {
+ const CountedRegion *Active = ActiveRegions.back();
+ unsigned Line = Active->LineEnd, Col = Active->ColumnEnd;
+ ActiveRegions.pop_back();
+ if (ActiveRegions.empty())
+ startSegment(Line, Col, /*IsRegionEntry=*/false);
+ else
+ startSegment(Line, Col, /*IsRegionEntry=*/false, *ActiveRegions.back());
+ }
+
+public:
+ /// Build a list of CoverageSegments from a sorted list of Regions.
+ std::vector<CoverageSegment>
+ buildSegments(ArrayRef<CountedRegion> Regions) {
+ for (const auto &Region : Regions) {
+ // Pop any regions that end before this one starts.
+ while (!ActiveRegions.empty() &&
+ ActiveRegions.back()->endLoc() <= Region.startLoc())
+ popRegion();
+ // Add this region to the stack.
+ ActiveRegions.push_back(&Region);
+ startSegment(Region);
}
- ++Prev;
- *Prev = *I;
+ // Pop any regions that are left in the stack.
+ while (!ActiveRegions.empty())
+ popRegion();
+ return Segments;
+ }
+};
+}
+
+ArrayRef<CoverageSegment> SourceCoverageDataManager::getCoverageSegments() {
+ if (Segments.empty()) {
+ // Sort the regions given that they're all in the same file at this point.
+ std::sort(Regions.begin(), Regions.end(),
+ [](const CountedRegion &LHS, const CountedRegion &RHS) {
+ if (LHS.startLoc() == RHS.startLoc())
+ // When LHS completely contains RHS, we sort LHS first.
+ return RHS.endLoc() < LHS.endLoc();
+ return LHS.startLoc() < RHS.startLoc();
+ });
+
+ Segments = SegmentBuilder().buildSegments(Regions);
}
- ++Prev;
- Regions.erase(Prev, Regions.end());
- Uniqued = true;
- return Regions;
+ return Segments;
}
//===----------------------------------------------------------------------===//
#include "SourceCoverageView.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/LineIterator.h"
using namespace llvm;
void SourceCoverageView::renderLine(raw_ostream &OS, StringRef Line,
- ArrayRef<HighlightRange> Ranges) {
- if (Ranges.empty()) {
- OS << Line << "\n";
- return;
- }
- if (Line.empty())
- Line = " ";
-
- unsigned PrevColumnStart = 0;
- unsigned Start = 1;
- for (const auto &Range : Ranges) {
- if (PrevColumnStart == Range.ColumnStart)
- continue;
-
- // Show the unhighlighted part
- unsigned ColumnStart = PrevColumnStart = Range.ColumnStart;
- OS << Line.substr(Start - 1, ColumnStart - Start);
-
- // Show the highlighted part
- auto Color = Range.Kind == HighlightRange::NotCovered ? raw_ostream::RED
- : raw_ostream::CYAN;
- OS.changeColor(Color, false, true);
- unsigned ColumnEnd = std::min(Range.ColumnEnd, (unsigned)Line.size() + 1);
- OS << Line.substr(ColumnStart - 1, ColumnEnd - ColumnStart);
- Start = ColumnEnd;
- OS.resetColor();
+ int64_t LineNumber,
+ const CoverageSegment *WrappedSegment,
+ ArrayRef<const CoverageSegment *> Segments,
+ unsigned ExpansionCol) {
+ Optional<raw_ostream::Colors> Highlight;
+ SmallVector<std::pair<unsigned, unsigned>, 2> HighlightedRanges;
+
+ // The first segment overlaps from a previous line, so we treat it specially.
+ if (WrappedSegment && WrappedSegment->HasCount && WrappedSegment->Count == 0)
+ Highlight = raw_ostream::RED;
+
+ // Output each segment of the line, possibly highlighted.
+ unsigned Col = 1;
+ for (const auto *S : Segments) {
+ unsigned End = std::min(S->Col, static_cast<unsigned>(Line.size()) + 1);
+ colored_ostream(OS, Highlight ? *Highlight : raw_ostream::SAVEDCOLOR,
+ Options.Colors && Highlight, /*Bold=*/false, /*BG=*/true)
+ << Line.substr(Col - 1, End - Col);
+ if (Options.Debug && Highlight)
+ HighlightedRanges.push_back(std::make_pair(Col, End));
+ Col = End;
+ if (Col == ExpansionCol)
+ Highlight = raw_ostream::CYAN;
+ else if (S->HasCount && S->Count == 0)
+ Highlight = raw_ostream::RED;
+ else
+ Highlight = None;
}
// Show the rest of the line
- OS << Line.substr(Start - 1, Line.size() - Start + 1);
+ colored_ostream(OS, Highlight ? *Highlight : raw_ostream::SAVEDCOLOR,
+ Options.Colors && Highlight, /*Bold=*/false, /*BG=*/true)
+ << Line.substr(Col - 1, Line.size() - Col + 1);
OS << "\n";
if (Options.Debug) {
- for (const auto &Range : Ranges) {
- errs() << "Highlighted line " << Range.Line << ", " << Range.ColumnStart
- << " -> ";
- if (Range.ColumnEnd == std::numeric_limits<unsigned>::max()) {
- errs() << "?\n";
- } else {
- errs() << Range.ColumnEnd << "\n";
- }
- }
+ for (const auto &Range : HighlightedRanges)
+ errs() << "Highlighted line " << LineNumber << ", " << Range.first
+ << " -> " << Range.second << "\n";
+ if (Highlight)
+ errs() << "Highlighted line " << LineNumber << ", " << Col << " -> ?\n";
}
}
OS.indent(LineNumberColumnWidth - Str.size()) << Str << '|';
}
-void SourceCoverageView::renderRegionMarkers(raw_ostream &OS,
- ArrayRef<RegionMarker> Regions) {
+void SourceCoverageView::renderRegionMarkers(
+ raw_ostream &OS, ArrayRef<const CoverageSegment *> Segments) {
SmallString<32> Buffer;
raw_svector_ostream BufferOS(Buffer);
unsigned PrevColumn = 1;
- for (const auto &Region : Regions) {
+ for (const auto *S : Segments) {
+ if (!S->IsRegionEntry)
+ continue;
// Skip to the new region
- if (Region.Column > PrevColumn)
- OS.indent(Region.Column - PrevColumn);
- PrevColumn = Region.Column + 1;
- BufferOS << Region.ExecutionCount;
+ if (S->Col > PrevColumn)
+ OS.indent(S->Col - PrevColumn);
+ PrevColumn = S->Col + 1;
+ BufferOS << S->Count;
StringRef Str = BufferOS.str();
// Trim the execution count
Str = Str.substr(0, std::min(Str.size(), (size_t)7));
}
OS << "\n";
- if (Options.Debug) {
- for (const auto &Region : Regions) {
- errs() << "Marker at " << Region.Line << ":" << Region.Column << " = "
- << Region.ExecutionCount << "\n";
- }
- }
+ if (Options.Debug)
+ for (const auto *S : Segments)
+ errs() << "Marker at " << S->Line << ":" << S->Col << " = " << S->Count
+ << (S->IsRegionEntry ? "\n" : " (pop)\n");
}
-/// \brief Insert a new highlighting range into the line's highlighting ranges
-/// Return line's new highlighting ranges in result.
-static void insertExpansionHighlightRange(
- ArrayRef<SourceCoverageView::HighlightRange> Ranges,
- unsigned Line, unsigned StartCol, unsigned EndCol,
- SmallVectorImpl<SourceCoverageView::HighlightRange> &Result) {
- auto RangeToInsert = SourceCoverageView::HighlightRange(
- Line, StartCol, EndCol, SourceCoverageView::HighlightRange::Expanded);
- Result.clear();
- size_t I = 0;
- auto E = Ranges.size();
- for (; I < E; ++I) {
- if (RangeToInsert.ColumnStart < Ranges[I].ColumnEnd) {
- const auto &Range = Ranges[I];
- bool NextRangeContainsInserted = false;
- // If the next range starts before the inserted range, move the end of the
- // next range to the start of the inserted range.
- if (Range.ColumnStart < RangeToInsert.ColumnStart) {
- if (RangeToInsert.ColumnStart != Range.ColumnStart)
- Result.push_back(SourceCoverageView::HighlightRange(
- Range.Line, Range.ColumnStart, RangeToInsert.ColumnStart,
- Range.Kind));
- // If the next range also ends after the inserted range, keep this range
- // and create a new range that starts at the inserted range and ends
- // at the next range later.
- if (Range.ColumnEnd > RangeToInsert.ColumnEnd)
- NextRangeContainsInserted = true;
- }
- if (!NextRangeContainsInserted) {
- ++I;
- // Ignore ranges that are contained in inserted range
- while (I < E && RangeToInsert.contains(Ranges[I]))
- ++I;
- }
- break;
- }
- Result.push_back(Ranges[I]);
- }
- Result.push_back(RangeToInsert);
- // If the next range starts before the inserted range end, move the start
- // of the next range to the end of the inserted range.
- if (I < E && Ranges[I].ColumnStart < RangeToInsert.ColumnEnd) {
- const auto &Range = Ranges[I];
- if (RangeToInsert.ColumnEnd != Range.ColumnEnd)
- Result.push_back(SourceCoverageView::HighlightRange(
- Range.Line, RangeToInsert.ColumnEnd, Range.ColumnEnd, Range.Kind));
- ++I;
- }
- // Add the remaining ranges that are located after the inserted range
- for (; I < E; ++I)
- Result.push_back(Ranges[I]);
-}
-
-template <typename T>
-ArrayRef<T> gatherLineItems(size_t &CurrentIdx, const std::vector<T> &Items,
- unsigned LineNo) {
- auto PrevIdx = CurrentIdx;
- auto E = Items.size();
- while (CurrentIdx < E && Items[CurrentIdx].Line == LineNo)
- ++CurrentIdx;
- return ArrayRef<T>(Items.data() + PrevIdx, CurrentIdx - PrevIdx);
-}
-
-void SourceCoverageView::render(raw_ostream &OS, unsigned IndentLevel) {
- SmallVector<HighlightRange, 8> AdjustedLineHighlightRanges;
- size_t CurrentHighlightRange = 0;
- size_t CurrentRegionMarker = 0;
-
- line_iterator Lines(File, /*SkipBlanks=*/false);
- // Advance the line iterator to the first line.
- while (Lines.line_number() < LineOffset)
- ++Lines;
-
+void SourceCoverageView::render(raw_ostream &OS, bool WholeFile,
+ unsigned IndentLevel) {
// The width of the leading columns
unsigned CombinedColumnWidth =
(Options.ShowLineStats ? LineCoverageColumnWidth + 1 : 0) +
auto NextISV = InstantiationSubViews.begin();
auto EndISV = InstantiationSubViews.end();
- for (size_t I = 0, E = LineStats.size(); I < E && !Lines.is_at_eof();
- ++I, ++Lines) {
- unsigned LineNo = Lines.line_number();
+ // Get the coverage information for the file.
+ auto CoverageSegments = RegionManager->getCoverageSegments();
+ assert(CoverageSegments.size() && "View with no coverage?");
+ auto NextSegment = CoverageSegments.begin();
+ auto EndSegment = CoverageSegments.end();
+
+ const CoverageSegment *WrappedSegment = nullptr;
+ SmallVector<const CoverageSegment *, 8> LineSegments;
+ for (line_iterator LI(File, /*SkipBlanks=*/false); !LI.is_at_eof(); ++LI) {
+ // If we aren't rendering the whole file, we need to filter out the prologue
+ // and epilogue.
+ if (!WholeFile) {
+ if (NextSegment == EndSegment)
+ break;
+ else if (LI.line_number() < NextSegment->Line)
+ continue;
+ }
+ // Collect the coverage information relevant to this line.
+ if (LineSegments.size())
+ WrappedSegment = LineSegments.back();
+ LineSegments.clear();
+ while (NextSegment != EndSegment && NextSegment->Line == LI.line_number())
+ LineSegments.push_back(&*NextSegment++);
+
+ // Calculate a count to be for the line as a whole.
+ LineCoverageInfo LineCount;
+ if (WrappedSegment && WrappedSegment->HasCount)
+ LineCount.addRegionCount(WrappedSegment->Count);
+ for (const auto *S : LineSegments)
+ if (S->HasCount && S->IsRegionEntry)
+ LineCount.addRegionStartCount(S->Count);
+
+ // Render the line prefix.
renderIndent(OS, IndentLevel);
if (Options.ShowLineStats)
- renderLineCoverageColumn(OS, LineStats[I]);
+ renderLineCoverageColumn(OS, LineCount);
if (Options.ShowLineNumbers)
- renderLineNumberColumn(OS, LineNo);
+ renderLineNumberColumn(OS, LI.line_number());
- // Gather highlighting ranges.
- auto LineHighlightRanges =
- gatherLineItems(CurrentHighlightRange, HighlightRanges, LineNo);
- auto LineRanges = LineHighlightRanges;
- // Highlight the expansion range if there is an expansion subview on this
- // line.
- if (NextESV != EndESV && NextESV->getLine() == LineNo && Options.Colors) {
- insertExpansionHighlightRange(
- LineHighlightRanges, NextESV->getLine(), NextESV->getStartCol(),
- NextESV->getEndCol(), AdjustedLineHighlightRanges);
- LineRanges = AdjustedLineHighlightRanges;
- }
+ // If there are expansion subviews, we want to highlight the first one.
+ unsigned ExpansionColumn = 0;
+ if (NextESV != EndESV && NextESV->getLine() == LI.line_number() &&
+ Options.Colors)
+ ExpansionColumn = NextESV->getStartCol();
// Display the source code for the current line.
- StringRef Line = *Lines;
- renderLine(OS, Line, LineRanges);
+ renderLine(OS, *LI, LI.line_number(), WrappedSegment, LineSegments,
+ ExpansionColumn);
// Show the region markers.
- bool ShowMarkers = !Options.ShowLineStatsOrRegionMarkers ||
- LineStats[I].hasMultipleRegions();
- auto LineMarkers = gatherLineItems(CurrentRegionMarker, Markers, LineNo);
- if (ShowMarkers && !LineMarkers.empty()) {
+ if (Options.ShowRegionMarkers && (!Options.ShowLineStatsOrRegionMarkers ||
+ LineCount.hasMultipleRegions()) &&
+ !LineSegments.empty()) {
renderIndent(OS, IndentLevel);
OS.indent(CombinedColumnWidth);
- renderRegionMarkers(OS, LineMarkers);
+ renderRegionMarkers(OS, LineSegments);
}
// Show the expansions and instantiations for this line.
unsigned NestedIndent = IndentLevel + 1;
bool RenderedSubView = false;
- for (; NextESV != EndESV && NextESV->getLine() == LineNo; ++NextESV) {
+ for (; NextESV != EndESV && NextESV->getLine() == LI.line_number();
+ ++NextESV) {
renderViewDivider(NestedIndent, DividerWidth, OS);
OS << "\n";
if (RenderedSubView) {
// Re-render the current line and highlight the expansion range for
// this subview.
- insertExpansionHighlightRange(
- LineHighlightRanges, NextESV->getLine(), NextESV->getStartCol(),
- NextESV->getEndCol(), AdjustedLineHighlightRanges);
+ ExpansionColumn = NextESV->getStartCol();
renderIndent(OS, IndentLevel);
OS.indent(CombinedColumnWidth + (IndentLevel == 0 ? 0 : 1));
- renderLine(OS, Line, AdjustedLineHighlightRanges);
+ renderLine(OS, *LI, LI.line_number(), WrappedSegment, LineSegments,
+ ExpansionColumn);
renderViewDivider(NestedIndent, DividerWidth, OS);
OS << "\n";
}
// Render the child subview
- NextESV->View->render(OS, NestedIndent);
+ NextESV->View->render(OS, false, NestedIndent);
RenderedSubView = true;
}
- for (; NextISV != EndISV && NextISV->Line == LineNo; ++NextISV) {
+ for (; NextISV != EndISV && NextISV->Line == LI.line_number(); ++NextISV) {
renderViewDivider(NestedIndent, DividerWidth, OS);
OS << "\n";
renderIndent(OS, NestedIndent);
Options.colored_ostream(OS, raw_ostream::CYAN) << NextISV->FunctionName
<< ":";
OS << "\n";
- NextISV->View->render(OS, NestedIndent);
+ NextISV->View->render(OS, false, NestedIndent);
RenderedSubView = true;
}
if (RenderedSubView) {
}
}
}
-
-void SourceCoverageView::setUpVisibleRange(SourceCoverageDataManager &Data) {
- auto CountedRegions = Data.getSourceRegions();
- if (!CountedRegions.size())
- return;
-
- unsigned Start = CountedRegions.front().LineStart, End = 0;
- for (const auto &CR : CountedRegions) {
- Start = std::min(Start, CR.LineStart);
- End = std::max(End, CR.LineEnd);
- }
- LineOffset = Start;
- LineStats.resize(End - Start + 1);
-}
-
-void
-SourceCoverageView::createLineCoverageInfo(SourceCoverageDataManager &Data) {
- auto CountedRegions = Data.getSourceRegions();
- for (const auto &CR : CountedRegions) {
- if (CR.Kind == coverage::CounterMappingRegion::SkippedRegion) {
- // Reset the line stats for skipped regions.
- for (unsigned Line = CR.LineStart; Line <= CR.LineEnd;
- ++Line)
- LineStats[Line - LineOffset] = LineCoverageInfo();
- continue;
- }
- LineStats[CR.LineStart - LineOffset].addRegionStartCount(CR.ExecutionCount);
- for (unsigned Line = CR.LineStart + 1; Line <= CR.LineEnd; ++Line)
- LineStats[Line - LineOffset].addRegionCount(CR.ExecutionCount);
- }
-}
-
-void
-SourceCoverageView::createHighlightRanges(SourceCoverageDataManager &Data) {
- auto CountedRegions = Data.getSourceRegions();
- std::vector<bool> AlreadyHighlighted;
- AlreadyHighlighted.resize(CountedRegions.size(), false);
-
- for (size_t I = 0, S = CountedRegions.size(); I < S; ++I) {
- const auto &CR = CountedRegions[I];
- if (CR.Kind == coverage::CounterMappingRegion::SkippedRegion ||
- CR.ExecutionCount != 0)
- continue;
- if (AlreadyHighlighted[I])
- continue;
- for (size_t J = 0; J < S; ++J) {
- if (CR.contains(CountedRegions[J])) {
- AlreadyHighlighted[J] = true;
- }
- }
- if (CR.LineStart == CR.LineEnd) {
- HighlightRanges.push_back(HighlightRange(
- CR.LineStart, CR.ColumnStart, CR.ColumnEnd));
- continue;
- }
- HighlightRanges.push_back(
- HighlightRange(CR.LineStart, CR.ColumnStart,
- std::numeric_limits<unsigned>::max()));
- HighlightRanges.push_back(
- HighlightRange(CR.LineEnd, 1, CR.ColumnEnd));
- for (unsigned Line = CR.LineStart + 1; Line < CR.LineEnd;
- ++Line) {
- HighlightRanges.push_back(
- HighlightRange(Line, 1, std::numeric_limits<unsigned>::max()));
- }
- }
-
- std::sort(HighlightRanges.begin(), HighlightRanges.end());
-}
-
-void SourceCoverageView::createRegionMarkers(SourceCoverageDataManager &Data) {
- for (const auto &CR : Data.getSourceRegions())
- if (CR.Kind != coverage::CounterMappingRegion::SkippedRegion)
- Markers.push_back(
- RegionMarker(CR.LineStart, CR.ColumnStart, CR.ExecutionCount));
-}
-
-void SourceCoverageView::load(SourceCoverageDataManager &Data) {
- setUpVisibleRange(Data);
- if (Options.ShowLineStats)
- createLineCoverageInfo(Data);
- if (Options.Colors)
- createHighlightRanges(Data);
- if (Options.ShowRegionMarkers)
- createRegionMarkers(Data);
-}
/// \brief A code coverage view of a specific source file.
/// It can have embedded coverage views.
class SourceCoverageView {
-public:
+private:
/// \brief Coverage information for a single line.
struct LineCoverageInfo {
uint64_t ExecutionCount;
void addRegionCount(uint64_t Count) {
Mapped = true;
- ExecutionCount = Count;
- }
- };
-
- /// \brief A marker that points at the start
- /// of a specific mapping region.
- struct RegionMarker {
- unsigned Line, Column;
- uint64_t ExecutionCount;
-
- RegionMarker(unsigned Line, unsigned Column, uint64_t Value)
- : Line(Line), Column(Column), ExecutionCount(Value) {}
- };
-
- /// \brief A single line source range used to
- /// render highlighted text.
- struct HighlightRange {
- enum HighlightKind {
- /// The code that wasn't executed.
- NotCovered,
-
- /// The region of code that was expanded.
- Expanded
- };
- HighlightKind Kind;
- unsigned Line;
- unsigned ColumnStart;
- unsigned ColumnEnd;
-
- HighlightRange(unsigned Line, unsigned ColumnStart, unsigned ColumnEnd,
- HighlightKind Kind = NotCovered)
- : Kind(Kind), Line(Line), ColumnStart(ColumnStart),
- ColumnEnd(ColumnEnd) {}
-
- bool operator<(const HighlightRange &Other) const {
- if (Line == Other.Line)
- return ColumnStart < Other.ColumnStart;
- return Line < Other.Line;
- }
-
- bool columnStartOverlaps(const HighlightRange &Other) const {
- return ColumnStart <= Other.ColumnStart && ColumnEnd > Other.ColumnStart;
- }
- bool columnEndOverlaps(const HighlightRange &Other) const {
- return ColumnEnd >= Other.ColumnEnd && ColumnStart < Other.ColumnEnd;
- }
- bool contains(const HighlightRange &Other) const {
- if (Line != Other.Line)
- return false;
- return ColumnStart <= Other.ColumnStart && ColumnEnd >= Other.ColumnEnd;
- }
-
- bool overlaps(const HighlightRange &Other) const {
- if (Line != Other.Line)
- return false;
- return columnStartOverlaps(Other) || columnEndOverlaps(Other);
+ if (!RegionCount)
+ ExecutionCount = Count;
}
};
-private:
const MemoryBuffer &File;
const CoverageViewOptions &Options;
- unsigned LineOffset;
+ std::unique_ptr<SourceCoverageDataManager> RegionManager;
std::vector<ExpansionView> ExpansionSubViews;
std::vector<InstantiationView> InstantiationSubViews;
- std::vector<LineCoverageInfo> LineStats;
- std::vector<HighlightRange> HighlightRanges;
- std::vector<RegionMarker> Markers;
-
- /// \brief Initialize the visible source range for this view.
- void setUpVisibleRange(SourceCoverageDataManager &Data);
-
- /// \brief Create the line coverage information using the coverage data.
- void createLineCoverageInfo(SourceCoverageDataManager &Data);
-
- /// \brief Create the line highlighting ranges using the coverage data.
- void createHighlightRanges(SourceCoverageDataManager &Data);
-
- /// \brief Create the region markers using the coverage data.
- void createRegionMarkers(SourceCoverageDataManager &Data);
/// \brief Render a source line with highlighting.
- void renderLine(raw_ostream &OS, StringRef Line,
- ArrayRef<HighlightRange> Ranges);
+ 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 renderLineNumberColumn(raw_ostream &OS, unsigned LineNo);
/// \brief Render all the region's execution counts on a line.
- void renderRegionMarkers(raw_ostream &OS, ArrayRef<RegionMarker> Regions);
+ 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), LineOffset(0) {}
+ : File(File), Options(Options) {}
const CoverageViewOptions &getOptions() const { return Options; }
/// \brief Print the code coverage information for a specific
/// portion of a source file to the output stream.
- void render(raw_ostream &OS, unsigned IndentLevel = 0);
+ 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(SourceCoverageDataManager &Data);
+ void load(std::unique_ptr<SourceCoverageDataManager> Data) {
+ RegionManager = std::move(Data);
+ }
};
} // namespace llvm