Index: test/tools/llvm-cov/Inputs/showProjectSummary.test
===================================================================
--- test/tools/llvm-cov/Inputs/showProjectSummary.test
+++ test/tools/llvm-cov/Inputs/showProjectSummary.test
@@ -8,6 +8,10 @@
HTML-TITLE:
Test Suite
HTML: Coverage Report
HTML: Created:{{.*}}
+HTML-TOTAL: Function Coverage: |
+HTML-TOTAL: Instantiation Coverage: |
+HTML-TOTAL: Line Coverage: |
+HTML-TOTAL: Region Coverage: |
HTML-FILE: {{.*}}showProjectSummary.cpp (Binary: showProjectSummary.covmapping)
HTML-FUNCTION: main
HTML-HEADER: Line |
Index: test/tools/llvm-cov/showProjectSummary.cpp
===================================================================
--- test/tools/llvm-cov/showProjectSummary.cpp
+++ test/tools/llvm-cov/showProjectSummary.cpp
@@ -23,6 +23,6 @@
// RUN: FileCheck -check-prefixes=HTML,HTML-FILE,HTML-HEADER -input-file %t.dir/coverage/tmp/showProjectSummary.cpp.html %S/Inputs/showProjectSummary.test
// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -format=html -o %t.dir -instr-profile %t.profdata -project-title "Test Suite" -filename-equivalence %s
// RUN: FileCheck -check-prefixes=HTML-TITLE,HTML,HTML-FILE,HTML-HEADER -input-file %t.dir/coverage/tmp/showProjectSummary.cpp.html %S/Inputs/showProjectSummary.test
-// RUN: FileCheck -check-prefixes=HTML-TITLE,HTML,HTML-FOOTER -input-file %t.dir/index.html %S/Inputs/showProjectSummary.test
+// RUN: FileCheck -check-prefixes=HTML-TITLE,HTML,HTML-TOTAL,HTML-FOOTER -input-file %t.dir/index.html %S/Inputs/showProjectSummary.test
// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -format=html -o %t.dir -instr-profile %t.profdata -project-title "Test Suite" -filename-equivalence -name=main %s
// RUN: FileCheck -check-prefixes=HTML-FUNCTION,HTML-HEADER -input-file %t.dir/functions.html %S/Inputs/showProjectSummary.test
Index: tools/llvm-cov/SourceCoverageViewHTML.h
===================================================================
--- tools/llvm-cov/SourceCoverageViewHTML.h
+++ tools/llvm-cov/SourceCoverageViewHTML.h
@@ -38,6 +38,9 @@
void emitFileSummary(raw_ostream &OS, StringRef SF,
const FileCoverageSummary &FCS,
bool IsTotals = false) const;
+
+ void emitProjectSummary(raw_ostream &OS,
+ const FileCoverageSummary &PCS) const;
};
/// \brief A code coverage view which supports html-based rendering.
Index: tools/llvm-cov/SourceCoverageViewHTML.cpp
===================================================================
--- tools/llvm-cov/SourceCoverageViewHTML.cpp
+++ tools/llvm-cov/SourceCoverageViewHTML.cpp
@@ -293,6 +293,19 @@
OS << tag("tr", join(Columns.begin(), Columns.end(), ""));
}
+/// Get the HTML for a coverage triple.
+static std::string getCoverageTriple(unsigned Hit, unsigned Total, float Pctg) {
+ std::string S;
+ raw_string_ostream RSO{S};
+ RSO << format("%*.2f", 7, Pctg) << "% (" << Hit << '/' << Total << ')';
+ const char *CellClass = "column-entry-yellow";
+ if (Pctg < 80.0)
+ CellClass = "column-entry-red";
+ else if (Hit == Total)
+ CellClass = "column-entry-green";
+ return tag("td", tag("pre", RSO.str()), CellClass);
+}
+
/// Render a file coverage summary (\p FCS) in a table row. If \p IsTotals is
/// false, link the summary to \p SF.
void CoveragePrinterHTML::emitFileSummary(raw_ostream &OS, StringRef SF,
@@ -300,22 +313,6 @@
bool IsTotals) const {
SmallVector Columns;
- // Format a coverage triple and add the result to the list of columns.
- auto AddCoverageTripleToColumn = [&Columns](unsigned Hit, unsigned Total,
- float Pctg) {
- std::string S;
- {
- raw_string_ostream RSO{S};
- RSO << format("%*.2f", 7, Pctg) << "% (" << Hit << '/' << Total << ')';
- }
- const char *CellClass = "column-entry-yellow";
- if (Pctg < 80.0)
- CellClass = "column-entry-red";
- else if (Hit == Total)
- CellClass = "column-entry-green";
- Columns.emplace_back(tag("td", tag("pre", S), CellClass));
- };
-
// Simplify the display file path, and wrap it in a link if requested.
std::string Filename;
SmallString<128> LinkTextStr(sys::path::relative_path(FCS.Name));
@@ -331,21 +328,63 @@
}
Columns.emplace_back(tag("td", tag("pre", Filename)));
- AddCoverageTripleToColumn(FCS.FunctionCoverage.Executed,
- FCS.FunctionCoverage.NumFunctions,
- FCS.FunctionCoverage.getPercentCovered());
- AddCoverageTripleToColumn(FCS.InstantiationCoverage.Executed,
- FCS.InstantiationCoverage.NumFunctions,
- FCS.InstantiationCoverage.getPercentCovered());
- AddCoverageTripleToColumn(FCS.LineCoverage.Covered, FCS.LineCoverage.NumLines,
- FCS.LineCoverage.getPercentCovered());
- AddCoverageTripleToColumn(FCS.RegionCoverage.Covered,
- FCS.RegionCoverage.NumRegions,
- FCS.RegionCoverage.getPercentCovered());
-
+ Columns.emplace_back(getCoverageTriple(
+ FCS.FunctionCoverage.Executed, FCS.FunctionCoverage.NumFunctions,
+ FCS.FunctionCoverage.getPercentCovered()));
+ Columns.emplace_back(
+ getCoverageTriple(FCS.InstantiationCoverage.Executed,
+ FCS.InstantiationCoverage.NumFunctions,
+ FCS.InstantiationCoverage.getPercentCovered()));
+ Columns.emplace_back(getCoverageTriple(
+ FCS.LineCoverage.NumLines - FCS.LineCoverage.NotCovered,
+ FCS.LineCoverage.NumLines, FCS.LineCoverage.getPercentCovered()));
+ Columns.emplace_back(getCoverageTriple(
+ FCS.RegionCoverage.NumRegions - FCS.RegionCoverage.NotCovered,
+ FCS.RegionCoverage.NumRegions, FCS.RegionCoverage.getPercentCovered()));
OS << tag("tr", join(Columns.begin(), Columns.end(), ""), "light-row");
}
+/// Render the project coverage summary (\p PCS) and the project directory (\p
+/// ProjectDir) above the index table.
+void CoveragePrinterHTML::emitProjectSummary(
+ raw_ostream &OS, const FileCoverageSummary &PCS) const {
+
+ OS << ""
+ << "";
+
+ // Add a coverage row to the coverage summary table.
+ auto AddCoverageSummaryRow = [&OS](StringRef CoverageTitle,
+ StringRef CoverageValue) {
+ OS << tag("tr",
+ tag("td", CoverageTitle, "column-entry") + CoverageValue.str());
+ };
+
+ AddCoverageSummaryRow(
+ "Function Coverage:",
+ getCoverageTriple(PCS.FunctionCoverage.Executed,
+ PCS.FunctionCoverage.NumFunctions,
+ PCS.FunctionCoverage.getPercentCovered()));
+ AddCoverageSummaryRow(
+ "Instantiation Coverage:",
+ getCoverageTriple(PCS.InstantiationCoverage.Executed,
+ PCS.InstantiationCoverage.NumFunctions,
+ PCS.InstantiationCoverage.getPercentCovered()));
+ AddCoverageSummaryRow(
+ "Line Coverage:",
+ getCoverageTriple(PCS.LineCoverage.NumLines - PCS.LineCoverage.NotCovered,
+ PCS.LineCoverage.NumLines,
+ PCS.LineCoverage.getPercentCovered()));
+ AddCoverageSummaryRow(
+ "Region Coverage:",
+ getCoverageTriple(PCS.RegionCoverage.NumRegions -
+ PCS.RegionCoverage.NotCovered,
+ PCS.RegionCoverage.NumRegions,
+ PCS.RegionCoverage.getPercentCovered()));
+
+ OS << ""
+ << "
" << "
";
+}
+
Error CoveragePrinterHTML::createIndexFile(
ArrayRef SourceFiles,
const coverage::CoverageMapping &Coverage) {
@@ -381,12 +420,15 @@
"here") +
" for information about interpreting this report.");
- // Emit a table containing links to reports for each file in the covmapping.
- OSRef << BeginCenteredDiv << BeginTable;
- emitColumnLabelsForIndex(OSRef);
+ // Emit a table containing the project coverage summary.
FileCoverageSummary Totals("TOTALS");
auto FileReports =
CoverageReport::prepareFileReports(Coverage, Totals, SourceFiles);
+ emitProjectSummary(OSRef, Totals);
+
+ // Emit a table containing links to reports for each file in the covmapping.
+ OSRef << BeginCenteredDiv << BeginTable;
+ emitColumnLabelsForIndex(OSRef);
for (unsigned I = 0, E = FileReports.size(); I < E; ++I)
emitFileSummary(OSRef, SourceFiles[I], FileReports[I]);
emitFileSummary(OSRef, "Totals", Totals, /*IsTotals=*/true);