[llvm] r273767 - [llvm-cov] Separate presentation logic from formatting logic, NFC
Vedant Kumar via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 24 19:58:30 PDT 2016
Author: vedantk
Date: Fri Jun 24 21:58:30 2016
New Revision: 273767
URL: http://llvm.org/viewvc/llvm-project?rev=273767&view=rev
Log:
[llvm-cov] Separate presentation logic from formatting logic, NFC
This makes it easier to add renderers for new kinds of output formats.
- Define and document a pure-virtual coverage rendering interface.
- Move the text-based rendering logic into its a new file.
- Re-work the API to better reflect the presentation/formatting split.
Added:
llvm/trunk/tools/llvm-cov/SourceCoverageViewText.cpp
llvm/trunk/tools/llvm-cov/SourceCoverageViewText.h
Modified:
llvm/trunk/tools/llvm-cov/CMakeLists.txt
llvm/trunk/tools/llvm-cov/CodeCoverage.cpp
llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp
llvm/trunk/tools/llvm-cov/SourceCoverageView.h
Modified: llvm/trunk/tools/llvm-cov/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CMakeLists.txt?rev=273767&r1=273766&r2=273767&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/CMakeLists.txt (original)
+++ llvm/trunk/tools/llvm-cov/CMakeLists.txt Fri Jun 24 21:58:30 2016
@@ -8,5 +8,6 @@ add_llvm_tool(llvm-cov
CoverageReport.cpp
CoverageSummaryInfo.cpp
SourceCoverageView.cpp
+ SourceCoverageViewText.cpp
TestingSupport.cpp
)
Modified: llvm/trunk/tools/llvm-cov/CodeCoverage.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/CodeCoverage.cpp?rev=273767&r1=273766&r2=273767&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/CodeCoverage.cpp (original)
+++ llvm/trunk/tools/llvm-cov/CodeCoverage.cpp Fri Jun 24 21:58:30 2016
@@ -132,9 +132,9 @@ CodeCoverageTool::attachExpansionSubView
continue;
auto SubViewExpansions = ExpansionCoverage.getExpansions();
- auto SubView = llvm::make_unique<SourceCoverageView>(
- Expansion.Function.Name, SourceBuffer.get(), ViewOpts,
- std::move(ExpansionCoverage));
+ auto SubView =
+ SourceCoverageView::create(Expansion.Function.Name, SourceBuffer.get(),
+ ViewOpts, std::move(ExpansionCoverage));
attachExpansionSubViews(*SubView, SubViewExpansions, Coverage);
View.addExpansion(Expansion.Region, std::move(SubView));
}
@@ -151,8 +151,8 @@ CodeCoverageTool::createFunctionView(con
return nullptr;
auto Expansions = FunctionCoverage.getExpansions();
- auto View = llvm::make_unique<SourceCoverageView>(
- Function.Name, SourceBuffer.get(), ViewOpts, std::move(FunctionCoverage));
+ auto View = SourceCoverageView::create(Function.Name, SourceBuffer.get(),
+ ViewOpts, std::move(FunctionCoverage));
attachExpansionSubViews(*View, Expansions, Coverage);
return View;
@@ -169,16 +169,16 @@ CodeCoverageTool::createSourceFileView(S
return nullptr;
auto Expansions = FileCoverage.getExpansions();
- auto View = llvm::make_unique<SourceCoverageView>(
- SourceFile, SourceBuffer.get(), ViewOpts, std::move(FileCoverage));
+ auto View = SourceCoverageView::create(SourceFile, SourceBuffer.get(),
+ ViewOpts, std::move(FileCoverage));
attachExpansionSubViews(*View, Expansions, Coverage);
for (auto Function : Coverage.getInstantiations(SourceFile)) {
auto SubViewCoverage = Coverage.getCoverageForFunction(*Function);
auto SubViewExpansions = SubViewCoverage.getExpansions();
- auto SubView = llvm::make_unique<SourceCoverageView>(
- Function->Name, SourceBuffer.get(), ViewOpts,
- std::move(SubViewCoverage));
+ auto SubView =
+ SourceCoverageView::create(Function->Name, SourceBuffer.get(), ViewOpts,
+ std::move(SubViewCoverage));
attachExpansionSubViews(*SubView, SubViewExpansions, Coverage);
if (SubView) {
@@ -428,8 +428,7 @@ int CodeCoverageTool::show(int argc, con
<< "\n";
continue;
}
- mainView->renderSourceName(outs());
- mainView->render(outs(), /*WholeFile=*/false);
+ mainView->print(outs(), /*WholeFile=*/false, /*ShowSourceName=*/true);
outs() << "\n";
}
return 0;
@@ -452,10 +451,7 @@ int CodeCoverageTool::show(int argc, con
continue;
}
- if (ShowFilenames)
- mainView->renderSourceName(outs());
-
- mainView->render(outs(), /*Wholefile=*/true);
+ mainView->print(outs(), /*Wholefile=*/true, /*ShowSourceName=*/ShowFilenames);
if (SourceFiles.size() > 1)
outs() << "\n";
}
Modified: llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp?rev=273767&r1=273766&r2=273767&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp (original)
+++ llvm/trunk/tools/llvm-cov/SourceCoverageView.cpp Fri Jun 24 21:58:30 2016
@@ -12,75 +12,14 @@
//===----------------------------------------------------------------------===//
#include "SourceCoverageView.h"
-#include "llvm/ADT/Optional.h"
+#include "SourceCoverageViewText.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/LineIterator.h"
using namespace llvm;
-void SourceCoverageView::renderLine(
- raw_ostream &OS, StringRef Line, int64_t LineNumber,
- const coverage::CoverageSegment *WrappedSegment,
- ArrayRef<const coverage::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,
- getOptions().Colors && Highlight, /*Bold=*/false,
- /*BG=*/true)
- << Line.substr(Col - 1, End - Col);
- if (getOptions().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
- colored_ostream(OS, Highlight ? *Highlight : raw_ostream::SAVEDCOLOR,
- getOptions().Colors && Highlight, /*Bold=*/false, /*BG=*/true)
- << Line.substr(Col - 1, Line.size() - Col + 1);
- OS << "\n";
-
- if (getOptions().Debug) {
- for (const auto &Range : HighlightedRanges)
- errs() << "Highlighted line " << LineNumber << ", " << Range.first
- << " -> " << Range.second << "\n";
- if (Highlight)
- errs() << "Highlighted line " << LineNumber << ", " << Col << " -> ?\n";
- }
-}
-
-void SourceCoverageView::renderIndent(raw_ostream &OS, unsigned Level) {
- for (unsigned I = 0; I < Level; ++I)
- OS << " |";
-}
-
-void SourceCoverageView::renderViewDivider(unsigned Level, unsigned Length,
- raw_ostream &OS) {
- assert(Level != 0 && "Cannot render divider at top level");
- renderIndent(OS, Level - 1);
- OS.indent(2);
- for (unsigned I = 0; I < Length; ++I)
- OS << "-";
-}
-
-/// Format a count using engineering notation with 3 significant digits.
-static std::string formatCount(uint64_t N) {
+std::string SourceCoverageView::formatCount(uint64_t N) {
std::string Number = utostr(N);
int Len = Number.size();
if (Len <= 3)
@@ -95,63 +34,30 @@ static std::string formatCount(uint64_t
return Result;
}
-void
-SourceCoverageView::renderLineCoverageColumn(raw_ostream &OS,
- const LineCoverageStats &Line) {
- if (!Line.isMapped()) {
- OS.indent(LineCoverageColumnWidth) << '|';
- return;
- }
- std::string C = formatCount(Line.ExecutionCount);
- OS.indent(LineCoverageColumnWidth - C.size());
- colored_ostream(OS, raw_ostream::MAGENTA,
- Line.hasMultipleRegions() && getOptions().Colors)
- << C;
- OS << '|';
-}
-
-void SourceCoverageView::renderLineNumberColumn(raw_ostream &OS,
- unsigned LineNo) {
- SmallString<32> Buffer;
- raw_svector_ostream BufferOS(Buffer);
- BufferOS << LineNo;
- auto Str = BufferOS.str();
- // Trim and align to the right
- Str = Str.substr(0, std::min(Str.size(), (size_t)LineNumberColumnWidth));
- OS.indent(LineNumberColumnWidth - Str.size()) << Str << '|';
-}
-
-void SourceCoverageView::renderRegionMarkers(
- raw_ostream &OS, ArrayRef<const coverage::CoverageSegment *> Segments) {
- unsigned PrevColumn = 1;
- for (const auto *S : Segments) {
- if (!S->IsRegionEntry)
- continue;
- // Skip to the new region
- if (S->Col > PrevColumn)
- OS.indent(S->Col - PrevColumn);
- PrevColumn = S->Col + 1;
- std::string C = formatCount(S->Count);
- PrevColumn += C.size();
- OS << '^' << C;
- }
- OS << "\n";
-
- if (getOptions().Debug)
- for (const auto *S : Segments)
- errs() << "Marker at " << S->Line << ":" << S->Col << " = "
- << formatCount(S->Count) << (S->IsRegionEntry ? "\n" : " (pop)\n");
-}
-
-void SourceCoverageView::render(raw_ostream &OS, bool WholeFile,
- unsigned IndentLevel) {
- // The width of the leading columns
- unsigned CombinedColumnWidth =
- (getOptions().ShowLineStats ? LineCoverageColumnWidth + 1 : 0) +
- (getOptions().ShowLineNumbers ? LineNumberColumnWidth + 1 : 0);
- // The width of the line that is used to divide between the view and the
- // subviews.
- unsigned DividerWidth = CombinedColumnWidth + 4;
+void SourceCoverageView::addExpansion(
+ const coverage::CounterMappingRegion &Region,
+ std::unique_ptr<SourceCoverageView> View) {
+ ExpansionSubViews.emplace_back(Region, std::move(View));
+}
+
+void SourceCoverageView::addInstantiation(
+ StringRef FunctionName, unsigned Line,
+ std::unique_ptr<SourceCoverageView> View) {
+ InstantiationSubViews.emplace_back(FunctionName, Line, std::move(View));
+}
+
+std::unique_ptr<SourceCoverageView>
+SourceCoverageView::create(StringRef SourceName, const MemoryBuffer &File,
+ const CoverageViewOptions &Options,
+ coverage::CoverageData &&CoverageInfo) {
+ return llvm::make_unique<SourceCoverageViewText>(SourceName, File, Options,
+ std::move(CoverageInfo));
+}
+
+void SourceCoverageView::print(raw_ostream &OS, bool WholeFile,
+ bool ShowSourceName, unsigned ViewDepth) {
+ if (ShowSourceName)
+ renderSourceName(OS);
// We need the expansions and instantiations sorted so we can go through them
// while we iterate lines.
@@ -192,10 +98,9 @@ void SourceCoverageView::render(raw_ostr
LineCount.addRegionCount(WrappedSegment->Count);
for (const auto *S : LineSegments)
if (S->HasCount && S->IsRegionEntry)
- LineCount.addRegionStartCount(S->Count);
+ LineCount.addRegionStartCount(S->Count);
- // Render the line prefix.
- renderIndent(OS, IndentLevel);
+ renderLinePrefix(OS, ViewDepth);
if (getOptions().ShowLineStats)
renderLineCoverageColumn(OS, LineCount);
if (getOptions().ShowLineNumbers)
@@ -208,62 +113,34 @@ void SourceCoverageView::render(raw_ostr
ExpansionColumn = NextESV->getStartCol();
// Display the source code for the current line.
- renderLine(OS, *LI, LI.line_number(), WrappedSegment, LineSegments,
- ExpansionColumn);
+ renderLine(OS, {*LI, LI.line_number()}, WrappedSegment, LineSegments,
+ ExpansionColumn, ViewDepth);
// Show the region markers.
if (getOptions().ShowRegionMarkers &&
(!getOptions().ShowLineStatsOrRegionMarkers ||
LineCount.hasMultipleRegions()) &&
!LineSegments.empty()) {
- renderIndent(OS, IndentLevel);
- OS.indent(CombinedColumnWidth);
- renderRegionMarkers(OS, LineSegments);
+ renderRegionMarkers(OS, LineSegments, ViewDepth);
}
// Show the expansions and instantiations for this line.
- unsigned NestedIndent = IndentLevel + 1;
bool RenderedSubView = false;
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.
- ExpansionColumn = NextESV->getStartCol();
- renderIndent(OS, IndentLevel);
- OS.indent(CombinedColumnWidth + (IndentLevel == 0 ? 0 : 1));
- renderLine(OS, *LI, LI.line_number(), WrappedSegment, LineSegments,
- ExpansionColumn);
- renderViewDivider(NestedIndent, DividerWidth, OS);
- OS << "\n";
- }
- // Render the child subview
- if (getOptions().Debug)
- errs() << "Expansion at line " << NextESV->getLine() << ", "
- << NextESV->getStartCol() << " -> " << NextESV->getEndCol()
- << "\n";
- NextESV->View->render(OS, false, NestedIndent);
+ renderViewDivider(OS, ViewDepth + 1);
+ ExpansionColumn = renderExpansionView(
+ OS, *NextESV,
+ RenderedSubView ? Optional<LineRef>({*LI, LI.line_number()})
+ : Optional<LineRef>(),
+ ExpansionColumn, WrappedSegment, LineSegments, ViewDepth);
RenderedSubView = true;
}
for (; NextISV != EndISV && NextISV->Line == LI.line_number(); ++NextISV) {
- renderViewDivider(NestedIndent, DividerWidth, OS);
- OS << "\n";
- renderIndent(OS, NestedIndent);
- OS << ' ';
- NextISV->View->renderSourceName(OS);
- NextISV->View->render(OS, false, NestedIndent);
+ renderInstantiationView(OS, *NextISV, ViewDepth + 1);
RenderedSubView = true;
}
- if (RenderedSubView) {
- renderViewDivider(NestedIndent, DividerWidth, OS);
- OS << "\n";
- }
+ if (RenderedSubView)
+ renderViewDivider(OS, ViewDepth + 1);
}
}
-
-void SourceCoverageView::renderSourceName(raw_ostream &OS) {
- getOptions().colored_ostream(OS, raw_ostream::CYAN) << getSourceName()
- << ":\n";
-}
Modified: llvm/trunk/tools/llvm-cov/SourceCoverageView.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/SourceCoverageView.h?rev=273767&r1=273766&r2=273767&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-cov/SourceCoverageView.h (original)
+++ llvm/trunk/tools/llvm-cov/SourceCoverageView.h Fri Jun 24 21:58:30 2016
@@ -16,6 +16,7 @@
#include "CoverageViewOptions.h"
#include "llvm/ProfileData/Coverage/CoverageMapping.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/Support/MemoryBuffer.h"
#include <vector>
@@ -100,7 +101,6 @@ struct LineCoverageStats {
/// \brief A code coverage view of a specific source file.
/// It can have embedded coverage views.
class SourceCoverageView {
-private:
/// A function or file name.
StringRef SourceName;
@@ -120,59 +120,93 @@ private:
/// on display.
std::vector<InstantiationView> InstantiationSubViews;
- /// \brief Render a source line with highlighting.
- void renderLine(raw_ostream &OS, StringRef Line, int64_t LineNumber,
- const coverage::CoverageSegment *WrappedSegment,
- ArrayRef<const coverage::CoverageSegment *> Segments,
- unsigned ExpansionCol);
+protected:
+ struct LineRef {
+ StringRef Line;
+ int64_t LineNo;
+
+ LineRef(StringRef Line, int64_t LineNo) : Line(Line), LineNo(LineNo) {}
+ };
+
+ using CoverageSegmentArray = ArrayRef<const coverage::CoverageSegment *>;
+
+ /// @name Rendering Interface
+ /// @{
- void renderIndent(raw_ostream &OS, unsigned Level);
+ /// \brief Render the source name for the view.
+ virtual void renderSourceName(raw_ostream &OS) = 0;
- void renderViewDivider(unsigned Offset, unsigned Length, raw_ostream &OS);
+ /// \brief Render the line prefix at the given \p ViewDepth.
+ virtual void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) = 0;
+
+ /// \brief Render a view divider at the given \p ViewDepth.
+ virtual void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) = 0;
+
+ /// \brief Render a source line with highlighting.
+ virtual void renderLine(raw_ostream &OS, LineRef L,
+ const coverage::CoverageSegment *WrappedSegment,
+ CoverageSegmentArray Segments, unsigned ExpansionCol,
+ unsigned ViewDepth) = 0;
/// \brief Render the line's execution count column.
- void renderLineCoverageColumn(raw_ostream &OS, const LineCoverageStats &Line);
+ virtual void renderLineCoverageColumn(raw_ostream &OS,
+ const LineCoverageStats &Line) = 0;
/// \brief Render the line number column.
- void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo);
+ virtual void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) = 0;
/// \brief Render all the region's execution counts on a line.
- void
- renderRegionMarkers(raw_ostream &OS,
- ArrayRef<const coverage::CoverageSegment *> Segments);
-
- static const unsigned LineCoverageColumnWidth = 7;
- static const unsigned LineNumberColumnWidth = 5;
+ virtual void renderRegionMarkers(raw_ostream &OS,
+ CoverageSegmentArray Segments,
+ unsigned ViewDepth) = 0;
+
+ /// \brief Render an expansion view. If \p FirstLine is provided, it points
+ /// to the expansion site, which must be re-rendered for clarity.
+ virtual unsigned renderExpansionView(
+ raw_ostream &OS, ExpansionView &ESV, Optional<LineRef> FirstLine,
+ unsigned ExpansionCol, const coverage::CoverageSegment *WrappedSegment,
+ CoverageSegmentArray LineSegments, unsigned ViewDepth) = 0;
+
+ /// \brief Render an instantiation view.
+ virtual void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV,
+ unsigned ViewDepth) = 0;
+
+ /// @}
+
+ /// \brief Format a count using engineering notation with 3 significant
+ /// digits.
+ static std::string formatCount(uint64_t N);
-public:
SourceCoverageView(StringRef SourceName, const MemoryBuffer &File,
const CoverageViewOptions &Options,
coverage::CoverageData &&CoverageInfo)
: SourceName(SourceName), File(File), Options(Options),
CoverageInfo(std::move(CoverageInfo)) {}
+public:
+ static std::unique_ptr<SourceCoverageView>
+ create(StringRef SourceName, const MemoryBuffer &File,
+ const CoverageViewOptions &Options,
+ coverage::CoverageData &&CoverageInfo);
+
+ virtual ~SourceCoverageView() {}
+
StringRef getSourceName() const { return SourceName; }
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));
- }
+ std::unique_ptr<SourceCoverageView> 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);
+ std::unique_ptr<SourceCoverageView> View);
- /// \brief Print the source name corresponding to this view.
- void renderSourceName(raw_ostream &OS);
+ /// \brief Print the code coverage information for a specific portion of a
+ /// source file to the output stream.
+ void print(raw_ostream &OS, bool WholeFile, bool ShowSourceName,
+ unsigned ViewDepth = 0);
};
} // namespace llvm
Added: llvm/trunk/tools/llvm-cov/SourceCoverageViewText.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/SourceCoverageViewText.cpp?rev=273767&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-cov/SourceCoverageViewText.cpp (added)
+++ llvm/trunk/tools/llvm-cov/SourceCoverageViewText.cpp Fri Jun 24 21:58:30 2016
@@ -0,0 +1,193 @@
+//===- SourceCoverageViewText.cpp - A text-based code coverage view -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the text-based coverage renderer.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SourceCoverageViewText.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+
+using namespace llvm;
+
+namespace {
+
+constexpr unsigned LineCoverageColumnWidth = 7;
+constexpr unsigned LineNumberColumnWidth = 5;
+
+/// \brief Get the width of the leading columns.
+unsigned getCombinedColumnWidth(const CoverageViewOptions &Opts) {
+ return (Opts.ShowLineStats ? LineCoverageColumnWidth + 1 : 0) +
+ (Opts.ShowLineNumbers ? LineNumberColumnWidth + 1 : 0);
+}
+
+/// \brief The width of the line that is used to divide between the view and
+/// the subviews.
+unsigned getDividerWidth(const CoverageViewOptions &Opts) {
+ return getCombinedColumnWidth(Opts) + 4;
+}
+
+} // anonymous namespace
+
+void SourceCoverageViewText::renderSourceName(raw_ostream &OS) {
+ getOptions().colored_ostream(OS, raw_ostream::CYAN) << getSourceName()
+ << ":\n";
+}
+
+void SourceCoverageViewText::renderLinePrefix(raw_ostream &OS,
+ unsigned ViewDepth) {
+ for (unsigned I = 0; I < ViewDepth; ++I)
+ OS << " |";
+}
+
+void SourceCoverageViewText::renderViewDivider(raw_ostream &OS,
+ unsigned ViewDepth) {
+ assert(ViewDepth != 0 && "Cannot render divider at top level");
+ renderLinePrefix(OS, ViewDepth - 1);
+ OS.indent(2);
+ unsigned Length = getDividerWidth(getOptions());
+ for (unsigned I = 0; I < Length; ++I)
+ OS << '-';
+ OS << '\n';
+}
+
+void SourceCoverageViewText::renderLine(
+ raw_ostream &OS, LineRef L,
+ const coverage::CoverageSegment *WrappedSegment,
+ CoverageSegmentArray Segments, unsigned ExpansionCol, unsigned ViewDepth) {
+ StringRef Line = L.Line;
+ unsigned LineNumber = L.LineNo;
+
+ 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,
+ getOptions().Colors && Highlight, /*Bold=*/false,
+ /*BG=*/true)
+ << Line.substr(Col - 1, End - Col);
+ if (getOptions().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.
+ colored_ostream(OS, Highlight ? *Highlight : raw_ostream::SAVEDCOLOR,
+ getOptions().Colors && Highlight, /*Bold=*/false, /*BG=*/true)
+ << Line.substr(Col - 1, Line.size() - Col + 1);
+ OS << '\n';
+
+ if (getOptions().Debug) {
+ for (const auto &Range : HighlightedRanges)
+ errs() << "Highlighted line " << LineNumber << ", " << Range.first
+ << " -> " << Range.second << '\n';
+ if (Highlight)
+ errs() << "Highlighted line " << LineNumber << ", " << Col << " -> ?\n";
+ }
+}
+
+void SourceCoverageViewText::renderLineCoverageColumn(
+ raw_ostream &OS, const LineCoverageStats &Line) {
+ if (!Line.isMapped()) {
+ OS.indent(LineCoverageColumnWidth) << '|';
+ return;
+ }
+ std::string C = formatCount(Line.ExecutionCount);
+ OS.indent(LineCoverageColumnWidth - C.size());
+ colored_ostream(OS, raw_ostream::MAGENTA,
+ Line.hasMultipleRegions() && getOptions().Colors)
+ << C;
+ OS << '|';
+}
+
+void SourceCoverageViewText::renderLineNumberColumn(raw_ostream &OS,
+ unsigned LineNo) {
+ SmallString<32> Buffer;
+ raw_svector_ostream BufferOS(Buffer);
+ BufferOS << LineNo;
+ auto Str = BufferOS.str();
+ // Trim and align to the right.
+ Str = Str.substr(0, std::min(Str.size(), (size_t)LineNumberColumnWidth));
+ OS.indent(LineNumberColumnWidth - Str.size()) << Str << '|';
+}
+
+void SourceCoverageViewText::renderRegionMarkers(
+ raw_ostream &OS, CoverageSegmentArray Segments, unsigned ViewDepth) {
+ renderLinePrefix(OS, ViewDepth);
+ OS.indent(getCombinedColumnWidth(getOptions()));
+
+ unsigned PrevColumn = 1;
+ for (const auto *S : Segments) {
+ if (!S->IsRegionEntry)
+ continue;
+ // Skip to the new region.
+ if (S->Col > PrevColumn)
+ OS.indent(S->Col - PrevColumn);
+ PrevColumn = S->Col + 1;
+ std::string C = formatCount(S->Count);
+ PrevColumn += C.size();
+ OS << '^' << C;
+ }
+ OS << '\n';
+
+ if (getOptions().Debug)
+ for (const auto *S : Segments)
+ errs() << "Marker at " << S->Line << ":" << S->Col << " = "
+ << formatCount(S->Count) << (S->IsRegionEntry ? "\n" : " (pop)\n");
+}
+
+unsigned SourceCoverageViewText::renderExpansionView(
+ raw_ostream &OS, ExpansionView &ESV, Optional<LineRef> FirstLine,
+ unsigned ExpansionCol, const coverage::CoverageSegment *WrappedSegment,
+ CoverageSegmentArray LineSegments, unsigned ViewDepth) {
+ unsigned NextExpansionCol = ExpansionCol;
+
+ if (FirstLine.hasValue()) {
+ // Re-render the current line and highlight the expansion range for
+ // this subview.
+ NextExpansionCol = ESV.getStartCol();
+ renderLinePrefix(OS, ViewDepth);
+ OS.indent(getCombinedColumnWidth(getOptions()) + (ViewDepth == 0 ? 0 : 1));
+ renderLine(OS, *FirstLine, WrappedSegment, LineSegments, ExpansionCol,
+ ViewDepth);
+ renderViewDivider(OS, ViewDepth + 1);
+ }
+
+ // Render the child subview.
+ if (getOptions().Debug)
+ errs() << "Expansion at line " << ESV.getLine() << ", " << ESV.getStartCol()
+ << " -> " << ESV.getEndCol() << '\n';
+ ESV.View->print(OS, /*WholeFile=*/false, /*ShowSourceName=*/false,
+ ViewDepth + 1);
+
+ return NextExpansionCol;
+}
+
+void SourceCoverageViewText::renderInstantiationView(raw_ostream &OS,
+ InstantiationView &ISV,
+ unsigned ViewDepth) {
+ renderViewDivider(OS, ViewDepth);
+ renderLinePrefix(OS, ViewDepth);
+ OS << ' ';
+ ISV.View->print(OS, /*WholeFile=*/false, /*ShowSourceName=*/true, ViewDepth);
+}
Added: llvm/trunk/tools/llvm-cov/SourceCoverageViewText.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-cov/SourceCoverageViewText.h?rev=273767&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-cov/SourceCoverageViewText.h (added)
+++ llvm/trunk/tools/llvm-cov/SourceCoverageViewText.h Fri Jun 24 21:58:30 2016
@@ -0,0 +1,61 @@
+//===- SourceCoverageViewText.h - A text-based code coverage view ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interface to the text-based coverage renderer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_COV_SOURCECOVERAGEVIEWTEXT_H
+#define LLVM_COV_SOURCECOVERAGEVIEWTEXT_H
+
+#include "SourceCoverageView.h"
+
+namespace llvm {
+
+class SourceCoverageViewText : public SourceCoverageView {
+ void renderSourceName(raw_ostream &OS) override;
+
+ void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) override;
+
+ void renderViewDivider(raw_ostream &OS, unsigned ViewDepth) override;
+
+ void renderLine(raw_ostream &OS, LineRef L,
+ const coverage::CoverageSegment *WrappedSegment,
+ CoverageSegmentArray Segments, unsigned ExpansionCol,
+ unsigned ViewDepth) override;
+
+ unsigned renderExpansionView(raw_ostream &OS, ExpansionView &ESV,
+ Optional<LineRef> FirstLine,
+ unsigned ExpansionCol,
+ const coverage::CoverageSegment *WrappedSegment,
+ CoverageSegmentArray LineSegments,
+ unsigned ViewDepth) override;
+
+ void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV,
+ unsigned ViewDepth) override;
+
+ void renderLineCoverageColumn(raw_ostream &OS,
+ const LineCoverageStats &Line) override;
+
+ void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) override;
+
+ void renderRegionMarkers(raw_ostream &OS, CoverageSegmentArray Segments,
+ unsigned ViewDepth) override;
+
+public:
+ SourceCoverageViewText(StringRef SourceName, const MemoryBuffer &File,
+ const CoverageViewOptions &Options,
+ coverage::CoverageData &&CoverageInfo)
+ : SourceCoverageView(SourceName, File, Options, std::move(CoverageInfo)) {
+ }
+};
+
+} // namespace llvm
+
+#endif // LLVM_COV_SOURCECOVERAGEVIEWTEXT_H
More information about the llvm-commits
mailing list