diff options
author | dim <dim@FreeBSD.org> | 2015-04-03 19:43:39 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2015-04-03 19:43:39 +0000 |
commit | c660843b7a28be8c4eb316a4c38a9f3cc58ec3e2 (patch) | |
tree | 0be5baf3192b0a86bb58483d62b35e66b3a6feb7 /contrib/llvm/tools/llvm-cov/CoverageReport.cpp | |
parent | e95804b81f9fa2cf9869afe23a2ad6efb7a750f8 (diff) | |
parent | ea50228cd2ebf54c0ec67624d82c47a11b807869 (diff) | |
download | FreeBSD-src-c660843b7a28be8c4eb316a4c38a9f3cc58ec3e2.zip FreeBSD-src-c660843b7a28be8c4eb316a4c38a9f3cc58ec3e2.tar.gz |
Add the llvm-cov and llvm-profdata tools, when WITH_CLANG_EXTRAS is
defined. These help with processing coverage and profile data.
Diffstat (limited to 'contrib/llvm/tools/llvm-cov/CoverageReport.cpp')
-rw-r--r-- | contrib/llvm/tools/llvm-cov/CoverageReport.cpp | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/contrib/llvm/tools/llvm-cov/CoverageReport.cpp b/contrib/llvm/tools/llvm-cov/CoverageReport.cpp new file mode 100644 index 0000000..6ae6ba5 --- /dev/null +++ b/contrib/llvm/tools/llvm-cov/CoverageReport.cpp @@ -0,0 +1,202 @@ +//===- CoverageReport.cpp - Code coverage report -------------------------===// +// +// 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 of a code coverage report. +// +//===----------------------------------------------------------------------===// + +#include "CoverageReport.h" +#include "CoverageSummary.h" +#include "RenderingSupport.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Format.h" + +using namespace llvm; +namespace { +/// \brief Helper struct which prints trimmed and aligned columns. +struct Column { + enum TrimKind { NoTrim, LeftTrim, RightTrim }; + + enum AlignmentKind { LeftAlignment, RightAlignment }; + + StringRef Str; + unsigned Width; + TrimKind Trim; + AlignmentKind Alignment; + + Column(StringRef Str, unsigned Width) + : Str(Str), Width(Width), Trim(NoTrim), Alignment(LeftAlignment) {} + + Column &set(TrimKind Value) { + Trim = Value; + return *this; + } + + Column &set(AlignmentKind Value) { + Alignment = Value; + return *this; + } + + void render(raw_ostream &OS) const; +}; +raw_ostream &operator<<(raw_ostream &OS, const Column &Value) { + Value.render(OS); + return OS; +} +} + +void Column::render(raw_ostream &OS) const { + if (Str.size() <= Width) { + if (Alignment == RightAlignment) { + OS.indent(Width - Str.size()); + OS << Str; + return; + } + OS << Str; + OS.indent(Width - Str.size()); + return; + } + + switch (Trim) { + case NoTrim: + OS << Str.substr(0, Width); + break; + case LeftTrim: + OS << "..." << Str.substr(Str.size() - Width + 3); + break; + case RightTrim: + OS << Str.substr(0, Width - 3) << "..."; + break; + } +} + +static Column column(StringRef Str, unsigned Width) { + return Column(Str, Width); +} + +template <typename T> +static Column column(StringRef Str, unsigned Width, const T &Value) { + return Column(Str, Width).set(Value); +} + +static const unsigned FileReportColumns[] = {25, 10, 8, 8, 10, 10}; +static const unsigned FunctionReportColumns[] = {25, 10, 8, 8, 10, 8, 8}; + +/// \brief Prints a horizontal divider which spans across the given columns. +template <typename T, size_t N> +static void renderDivider(T (&Columns)[N], raw_ostream &OS) { + unsigned Length = 0; + for (unsigned I = 0; I < N; ++I) + Length += Columns[I]; + for (unsigned I = 0; I < Length; ++I) + OS << '-'; +} + +/// \brief Return the color which correponds to the coverage +/// percentage of a certain metric. +template <typename T> +static raw_ostream::Colors determineCoveragePercentageColor(const T &Info) { + if (Info.isFullyCovered()) + return raw_ostream::GREEN; + return Info.getPercentCovered() >= 80.0 ? raw_ostream::YELLOW + : raw_ostream::RED; +} + +void CoverageReport::render(const FileCoverageSummary &File, raw_ostream &OS) { + OS << column(File.Name, FileReportColumns[0], Column::LeftTrim) + << format("%*u", FileReportColumns[1], (unsigned)File.RegionCoverage.NumRegions); + Options.colored_ostream(OS, File.RegionCoverage.isFullyCovered() + ? raw_ostream::GREEN + : raw_ostream::RED) + << format("%*u", FileReportColumns[2], (unsigned)File.RegionCoverage.NotCovered); + Options.colored_ostream(OS, + determineCoveragePercentageColor(File.RegionCoverage)) + << format("%*.2f", FileReportColumns[3] - 1, + File.RegionCoverage.getPercentCovered()) << '%'; + OS << format("%*u", FileReportColumns[4], + (unsigned)File.FunctionCoverage.NumFunctions); + Options.colored_ostream( + OS, determineCoveragePercentageColor(File.FunctionCoverage)) + << format("%*.2f", FileReportColumns[5] - 1, + File.FunctionCoverage.getPercentCovered()) << '%'; + OS << "\n"; +} + +void CoverageReport::render(const FunctionCoverageSummary &Function, + raw_ostream &OS) { + OS << column(Function.Name, FunctionReportColumns[0], Column::RightTrim) + << format("%*u", FunctionReportColumns[1], + (unsigned)Function.RegionCoverage.NumRegions); + Options.colored_ostream(OS, Function.RegionCoverage.isFullyCovered() + ? raw_ostream::GREEN + : raw_ostream::RED) + << format("%*u", FunctionReportColumns[2], + (unsigned)Function.RegionCoverage.NotCovered); + Options.colored_ostream( + OS, determineCoveragePercentageColor(Function.RegionCoverage)) + << format("%*.2f", FunctionReportColumns[3] - 1, + Function.RegionCoverage.getPercentCovered()) << '%'; + OS << format("%*u", FunctionReportColumns[4], + (unsigned)Function.LineCoverage.NumLines); + Options.colored_ostream(OS, Function.LineCoverage.isFullyCovered() + ? raw_ostream::GREEN + : raw_ostream::RED) + << format("%*u", FunctionReportColumns[5], + (unsigned)Function.LineCoverage.NotCovered); + Options.colored_ostream( + OS, determineCoveragePercentageColor(Function.LineCoverage)) + << format("%*.2f", FunctionReportColumns[6] - 1, + Function.LineCoverage.getPercentCovered()) << '%'; + OS << "\n"; +} + +void CoverageReport::renderFunctionReports(raw_ostream &OS) { + bool isFirst = true; + for (const auto &File : Summary.getFileSummaries()) { + if (isFirst) + isFirst = false; + else + OS << "\n"; + OS << "File '" << File.Name << "':\n"; + OS << column("Name", FunctionReportColumns[0]) + << column("Regions", FunctionReportColumns[1], Column::RightAlignment) + << column("Miss", FunctionReportColumns[2], Column::RightAlignment) + << column("Cover", FunctionReportColumns[3], Column::RightAlignment) + << column("Lines", FunctionReportColumns[4], Column::RightAlignment) + << column("Miss", FunctionReportColumns[5], Column::RightAlignment) + << column("Cover", FunctionReportColumns[6], Column::RightAlignment); + OS << "\n"; + renderDivider(FunctionReportColumns, OS); + OS << "\n"; + for (const auto &Function : File.FunctionSummaries) + render(Function, OS); + renderDivider(FunctionReportColumns, OS); + OS << "\n"; + render(FunctionCoverageSummary("TOTAL", /*ExecutionCount=*/0, + File.RegionCoverage, File.LineCoverage), + OS); + } +} + +void CoverageReport::renderFileReports(raw_ostream &OS) { + OS << column("Filename", FileReportColumns[0]) + << column("Regions", FileReportColumns[1], Column::RightAlignment) + << column("Miss", FileReportColumns[2], Column::RightAlignment) + << column("Cover", FileReportColumns[3], Column::RightAlignment) + << column("Functions", FileReportColumns[4], Column::RightAlignment) + << column("Executed", FileReportColumns[5], Column::RightAlignment) + << "\n"; + renderDivider(FileReportColumns, OS); + OS << "\n"; + for (const auto &File : Summary.getFileSummaries()) + render(File, OS); + renderDivider(FileReportColumns, OS); + OS << "\n"; + render(Summary.getCombinedFileSummaries(), OS); +} |