Mercurial > hg > CbC > CbC_llvm
diff tools/llvm-cov/SourceCoverageViewText.cpp @ 122:36195a0db682
merging ( incomplete )
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 17 Nov 2017 20:32:31 +0900 |
parents | 803732b1fca8 |
children | 3a76565eade5 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/llvm-cov/SourceCoverageViewText.cpp Fri Nov 17 20:32:31 2017 +0900 @@ -0,0 +1,251 @@ +//===- 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. +// +//===----------------------------------------------------------------------===// +/// +/// \file This file implements the text-based coverage renderer. +/// +//===----------------------------------------------------------------------===// + +#include "CoverageReport.h" +#include "SourceCoverageViewText.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" + +using namespace llvm; + +Expected<CoveragePrinter::OwnedStream> +CoveragePrinterText::createViewFile(StringRef Path, bool InToplevel) { + return createOutputStream(Path, "txt", InToplevel); +} + +void CoveragePrinterText::closeViewFile(OwnedStream OS) { + OS->operator<<('\n'); +} + +Error CoveragePrinterText::createIndexFile( + ArrayRef<std::string> SourceFiles, const CoverageMapping &Coverage, + const CoverageFiltersMatchAll &Filters) { + auto OSOrErr = createOutputStream("index", "txt", /*InToplevel=*/true); + if (Error E = OSOrErr.takeError()) + return E; + auto OS = std::move(OSOrErr.get()); + raw_ostream &OSRef = *OS.get(); + + CoverageReport Report(Opts, Coverage); + Report.renderFileReports(OSRef, SourceFiles, Filters); + + Opts.colored_ostream(OSRef, raw_ostream::CYAN) << "\n" + << Opts.getLLVMVersionString(); + + return Error::success(); +} + +namespace { + +static const unsigned LineCoverageColumnWidth = 7; +static const 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::renderViewHeader(raw_ostream &) {} + +void SourceCoverageViewText::renderViewFooter(raw_ostream &) {} + +void SourceCoverageViewText::renderSourceName(raw_ostream &OS, bool WholeFile) { + 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::renderLineSuffix(raw_ostream &, unsigned) {} + +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 LineCoverageStats &LCS, + unsigned ExpansionCol, + unsigned ViewDepth) { + StringRef Line = L.Line; + unsigned LineNumber = L.LineNo; + auto *WrappedSegment = LCS.getWrappedSegment(); + CoverageSegmentArray Segments = LCS.getLineSegments(); + + 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->IsGapRegion || Highlight == raw_ostream::RED) && + 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.getExecutionCount()); + 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, + const LineCoverageStats &Line, + unsigned ViewDepth) { + renderLinePrefix(OS, ViewDepth); + OS.indent(getCombinedColumnWidth(getOptions())); + + CoverageSegmentArray Segments = Line.getLineSegments(); + + // Just consider the segments which start *and* end on this line. + if (Segments.size() > 1) + Segments = Segments.drop_back(); + + unsigned PrevColumn = 1; + for (const auto *S : Segments) { + if (!S->IsRegionEntry) + continue; + if (S->Count == Line.getExecutionCount()) + 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; + + if (getOptions().Debug) + errs() << "Marker at " << S->Line << ":" << S->Col << " = " + << formatCount(S->Count) << "\n"; + } + OS << '\n'; +} + +void SourceCoverageViewText::renderExpansionSite(raw_ostream &OS, LineRef L, + const LineCoverageStats &LCS, + unsigned ExpansionCol, + unsigned ViewDepth) { + renderLinePrefix(OS, ViewDepth); + OS.indent(getCombinedColumnWidth(getOptions()) + (ViewDepth == 0 ? 0 : 1)); + renderLine(OS, L, LCS, ExpansionCol, ViewDepth); +} + +void SourceCoverageViewText::renderExpansionView(raw_ostream &OS, + ExpansionView &ESV, + unsigned ViewDepth) { + // 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, + /*ShowTitle=*/false, ViewDepth + 1); +} + +void SourceCoverageViewText::renderInstantiationView(raw_ostream &OS, + InstantiationView &ISV, + unsigned ViewDepth) { + renderLinePrefix(OS, ViewDepth); + OS << ' '; + if (!ISV.View) + getOptions().colored_ostream(OS, raw_ostream::RED) + << "Unexecuted instantiation: " << ISV.FunctionName << "\n"; + else + ISV.View->print(OS, /*WholeFile=*/false, /*ShowSourceName=*/true, + /*ShowTitle=*/false, ViewDepth); +} + +void SourceCoverageViewText::renderTitle(raw_ostream &OS, StringRef Title) { + if (getOptions().hasProjectTitle()) + getOptions().colored_ostream(OS, raw_ostream::CYAN) + << getOptions().ProjectTitle << "\n"; + + getOptions().colored_ostream(OS, raw_ostream::CYAN) << Title << "\n"; + + if (getOptions().hasCreatedTime()) + getOptions().colored_ostream(OS, raw_ostream::CYAN) + << getOptions().CreatedTimeStr << "\n"; +} + +void SourceCoverageViewText::renderTableHeader(raw_ostream &, unsigned, + unsigned) {}