[llvm] [llvm-cov] format cells in code coverage report with 0/0 branches/functions/lines differently (PR #75780)

Hana Dusíková via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 19 01:21:23 PST 2023


https://github.com/hanickadot updated https://github.com/llvm/llvm-project/pull/75780

>From 7a75dc696bd4de9ce8ff636a7a50fd6c035d13f9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= <hanicka at hanicka.net>
Date: Mon, 18 Dec 2023 11:11:15 +0100
Subject: [PATCH 1/2] [llvm-cov] format cells in report with 0/0
 branches/functions/lines differenly (gray instead red) and make the table a
 bit nicer

---
 .../tools/llvm-cov/coverage_watermark.test    | 20 +++++++++++++++-
 .../tools/llvm-cov/SourceCoverageViewHTML.cpp | 24 +++++++++++++++----
 2 files changed, 39 insertions(+), 5 deletions(-)

diff --git a/llvm/test/tools/llvm-cov/coverage_watermark.test b/llvm/test/tools/llvm-cov/coverage_watermark.test
index 1c0408dd0078c9..5c48b4f0fb4bf4 100644
--- a/llvm/test/tools/llvm-cov/coverage_watermark.test
+++ b/llvm/test/tools/llvm-cov/coverage_watermark.test
@@ -13,29 +13,47 @@ INVALID-ARRANGE: error: -coverage-watermark: invalid number range '10,20', must
 RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -format html -show-region-summary -show-instantiation-summary -o %t.html.dir -path-equivalence=/tmp,%S %S/showTemplateInstantiations.cpp
 RUN: FileCheck -check-prefix=ORIGIN %s -input-file %t.html.dir/index.html
 
+ORIGIN: Totals
+ORIGIN: <td class='column-entry-green'>
+ORIGIN: 100.00% (2/2)
 ORIGIN: <td class='column-entry-green'>
 ORIGIN: 100.00% (3/3)
 ORIGIN: <td class='column-entry-red'>
 ORIGIN: 75.00% (9/12)
 ORIGIN: <td class='column-entry-red'>
 ORIGIN: 66.67% (4/6)
+ORIGIN: <td class='column-entry-gray'>
+ORIGIN: - (0/0)
+ORIGIN: </tr>
 
-RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -format html -show-region-summary -show-instantiation-summary -o %t.html.dir -path-equivalence=/tmp,%S -coverage-watermark 80,60 %S/showTemplateInstantiations.cpp
+RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -format html -show-region-summary -show-instantiation-summary -o %t.html.dir -path-equivalence=/tmp,%S -coverage-watermark 80,70 %S/showTemplateInstantiations.cpp
 RUN: FileCheck -check-prefix=DOWNGRADE1 %s -input-file %t.html.dir/index.html
 
+DOWNGRADE:1 Totals
+DOWNGRADE1: <td class='column-entry-green'>
+DOWNGRADE1: 100.00% (2/2)
 DOWNGRADE1: <td class='column-entry-green'>
 DOWNGRADE1: 100.00% (3/3)
 DOWNGRADE1: <td class='column-entry-yellow'>
 DOWNGRADE1: 75.00% (9/12)
 DOWNGRADE1: <td class='column-entry-red'>
 DOWNGRADE1: 66.67% (4/6)
+DOWNGRADE1: <td class='column-entry-gray'>
+DOWNGRADE1: - (0/0)
+DOWNGRADE1: </tr>
 
 RUN: llvm-cov show %S/Inputs/templateInstantiations.covmapping -instr-profile %S/Inputs/templateInstantiations.profdata -format html -show-region-summary -show-instantiation-summary -o %t.html.dir -path-equivalence=/tmp,%S -coverage-watermark 70,50 %S/showTemplateInstantiations.cpp
 RUN: FileCheck -check-prefix=DOWNGRADE2 %s -input-file %t.html.dir/index.html
 
+DOWNGRADE:1 Totals
+DOWNGRADE2: <td class='column-entry-green'>
+DOWNGRADE2: 100.00% (2/2)
 DOWNGRADE2: <td class='column-entry-green'>
 DOWNGRADE2: 100.00% (3/3)
 DOWNGRADE2: <td class='column-entry-green'>
 DOWNGRADE2: 75.00% (9/12)
 DOWNGRADE2: <td class='column-entry-yellow'>
 DOWNGRADE2: 66.67% (4/6)
+DOWNGRADE1: <td class='column-entry-gray'>
+DOWNGRADE1: - (0/0)
+DOWNGRADE1: </tr>
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
index b43e9e64231e0c..e1aa5e4a05af78 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
@@ -130,10 +130,14 @@ table {
 .light-row {
   background: #ffffff;
   border: 1px solid #dbdbdb;
+  border-left: none;
+  border-right: none;
 }
 .light-row-bold {
   background: #ffffff;
   border: 1px solid #dbdbdb;
+  border-left: none;
+  border-right: none;
   font-weight: bold;
 }
 .column-entry {
@@ -147,21 +151,28 @@ table {
   text-align: left;
   background-color: #ffffd0;
 }
-.column-entry-yellow:hover {
+.column-entry-yellow:hover, tr:hover .column-entry-yellow {
   background-color: #fffff0;
 }
 .column-entry-red {
   text-align: left;
   background-color: #ffd0d0;
 }
-.column-entry-red:hover {
+.column-entry-red:hover, tr:hover .column-entry-red {
   background-color: #fff0f0;
 }
+.column-entry-gray {
+  text-align: left;
+  background-color: #fbfbfb;
+}
+.column-entry-gray:hover, tr:hover .column-entry-gray {
+  background-color: #f0f0f0;
+}
 .column-entry-green {
   text-align: left;
   background-color: #d0ffd0;
 }
-.column-entry-green:hover {
+.column-entry-green:hover, tr:hover .column-entry-green {
   background-color: #f0fff0;
 }
 .line-number {
@@ -232,6 +243,9 @@ td:last-child {
 tr:hover {
   background-color: #f0f0f0;
 }
+tr:last-child {
+  border-bottom: none;
+}
 )";
 
 const char *EndHeader = "</head>";
@@ -309,7 +323,9 @@ void emitTableRow(raw_ostream &OS, const CoverageViewOptions &Opts,
           RSO << '(' << Hit << '/' << Total << ')';
         }
         const char *CellClass = "column-entry-yellow";
-        if (Pctg >= Opts.HighCovWatermark)
+        if (!Total) {
+          CellClass = "column-entry-gray";
+        } else if (Pctg >= Opts.HighCovWatermark)
           CellClass = "column-entry-green";
         else if (Pctg < Opts.LowCovWatermark)
           CellClass = "column-entry-red";

>From 67c537c168bba30b66d29b64381e6fad65c8d76c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hana=20Dusi=CC=81kova=CC=81?= <hanicka at hanicka.net>
Date: Tue, 19 Dec 2023 10:21:04 +0100
Subject: [PATCH 2/2] [llvm-cov] add sorting of code-coverage table by clicking
 on header

---
 .../test/tools/llvm-cov/branch-c-general.test | 10 +--
 .../llvm-cov/hideUnexecutedSubviews.test      | 10 +--
 .../tools/llvm-cov/mcdc-general-none.test     | 12 +--
 llvm/test/tools/llvm-cov/mcdc-general.test    | 12 +--
 .../llvm-cov/showLineExecutionCounts.cpp      |  8 +-
 .../tools/llvm-cov/SourceCoverageViewHTML.cpp | 74 +++++++++++++++++--
 6 files changed, 92 insertions(+), 34 deletions(-)

diff --git a/llvm/test/tools/llvm-cov/branch-c-general.test b/llvm/test/tools/llvm-cov/branch-c-general.test
index 9b5889babde366..0ec67eb1a6cfea 100644
--- a/llvm/test/tools/llvm-cov/branch-c-general.test
+++ b/llvm/test/tools/llvm-cov/branch-c-general.test
@@ -148,11 +148,11 @@
 
 // RUN: FileCheck -check-prefix HTML-INDEX -input-file %t.html.dir/index.html %s
 // HTML-INDEX-LABEL: <table>
-// HTML-INDEX: <td class='column-entry-bold'>Filename</td>
-// HTML-INDEX: <td class='column-entry-bold'>Function Coverage</td>
-// HTML-INDEX: <td class='column-entry-bold'>Line Coverage</td>
-// HTML-INDEX: <td class='column-entry-bold'>Region Coverage</td>
-// HTML-INDEX: <td class='column-entry-bold'>Branch Coverage</td>
+// HTML-INDEX: <th class='column-entry-bold'>Filename</th>
+// HTML-INDEX: <th class='column-entry-bold'>Function Coverage</th>
+// HTML-INDEX: <th class='column-entry-bold'>Line Coverage</th>
+// HTML-INDEX: <th class='column-entry-bold'>Region Coverage</th>
+// HTML-INDEX: <th class='column-entry-bold'>Branch Coverage</th>
 // HTML-INDEX: <a href='coverage{{.*}}branch-c-general.c.html'{{.*}}branch-c-general.c</a>
 // HTML-INDEX: <td class='column-entry-green'>
 // HTML-INDEX: 100.00% (12/12)
diff --git a/llvm/test/tools/llvm-cov/hideUnexecutedSubviews.test b/llvm/test/tools/llvm-cov/hideUnexecutedSubviews.test
index b3fc1e63bcdee6..16859d550b6f8a 100644
--- a/llvm/test/tools/llvm-cov/hideUnexecutedSubviews.test
+++ b/llvm/test/tools/llvm-cov/hideUnexecutedSubviews.test
@@ -11,11 +11,11 @@ FILE-NOT: Unexecuted instantiation
 
 RUN: FileCheck -check-prefix=INDEX %s -input-file %t.html.dir/index.html
 
-INDEX: <td class='column-entry-bold'>Filename</td>
-INDEX: <td class='column-entry-bold'>Function Coverage</td>
-INDEX: <td class='column-entry-bold'>Instantiation Coverage</td>
-INDEX: <td class='column-entry-bold'>Line Coverage</td>
-INDEX: <td class='column-entry-bold'>Region Coverage</td>
+INDEX: <th class='column-entry-bold'>Filename</th>
+INDEX: <th class='column-entry-bold'>Function Coverage</th>
+INDEX: <th class='column-entry-bold'>Instantiation Coverage</th>
+INDEX: <th class='column-entry-bold'>Line Coverage</th>
+INDEX: <th class='column-entry-bold'>Region Coverage</th>
 INDEX: <td class='column-entry-red'>
 INDEX: 50.00% (1/2)
 INDEX: <td class='column-entry-red'>
diff --git a/llvm/test/tools/llvm-cov/mcdc-general-none.test b/llvm/test/tools/llvm-cov/mcdc-general-none.test
index bcf8f3cbd05d45..91ca7a252193c6 100644
--- a/llvm/test/tools/llvm-cov/mcdc-general-none.test
+++ b/llvm/test/tools/llvm-cov/mcdc-general-none.test
@@ -56,12 +56,12 @@
 
 // RUN: FileCheck -check-prefix HTML-INDEX -input-file %t.html.dir/index.html %s
 // HTML-INDEX-LABEL: <table>
-// HTML-INDEX: <td class='column-entry-bold'>Filename</td>
-// HTML-INDEX: <td class='column-entry-bold'>Function Coverage</td>
-// HTML-INDEX: <td class='column-entry-bold'>Line Coverage</td>
-// HTML-INDEX: <td class='column-entry-bold'>Region Coverage</td>
-// HTML-INDEX: <td class='column-entry-bold'>Branch Coverage</td>
-// HTML-INDEX: <td class='column-entry-bold'>MC/DC</td>
+// HTML-INDEX: <th class='column-entry-bold'>Filename</th>
+// HTML-INDEX: <th class='column-entry-bold'>Function Coverage</th>
+// HTML-INDEX: <th class='column-entry-bold'>Line Coverage</th>
+// HTML-INDEX: <th class='column-entry-bold'>Region Coverage</th>
+// HTML-INDEX: <th class='column-entry-bold'>Branch Coverage</th>
+// HTML-INDEX: <th class='column-entry-bold'>MC/DC</th>
 // HTML-INDEX: <a href='coverage{{.*}}mcdc-general.cpp.html'{{.*}}mcdc-general.cpp</a>
 // HTML-INDEX: <td class='column-entry-green'>
 // HTML-INDEX: 100.00% (2/2)
diff --git a/llvm/test/tools/llvm-cov/mcdc-general.test b/llvm/test/tools/llvm-cov/mcdc-general.test
index 588aed09c16a5e..0ec38617dfbdd1 100644
--- a/llvm/test/tools/llvm-cov/mcdc-general.test
+++ b/llvm/test/tools/llvm-cov/mcdc-general.test
@@ -122,12 +122,12 @@
 
 // RUN: FileCheck -check-prefix HTML-INDEX -input-file %t.html.dir/index.html %s
 // HTML-INDEX-LABEL: <table>
-// HTML-INDEX: <td class='column-entry-bold'>Filename</td>
-// HTML-INDEX: <td class='column-entry-bold'>Function Coverage</td>
-// HTML-INDEX: <td class='column-entry-bold'>Line Coverage</td>
-// HTML-INDEX: <td class='column-entry-bold'>Region Coverage</td>
-// HTML-INDEX: <td class='column-entry-bold'>Branch Coverage</td>
-// HTML-INDEX: <td class='column-entry-bold'>MC/DC</td>
+// HTML-INDEX: <th class='column-entry-bold'>Filename</th>
+// HTML-INDEX: <th class='column-entry-bold'>Function Coverage</th>
+// HTML-INDEX: <th class='column-entry-bold'>Line Coverage</th>
+// HTML-INDEX: <th class='column-entry-bold'>Region Coverage</th>
+// HTML-INDEX: <th class='column-entry-bold'>Branch Coverage</th>
+// HTML-INDEX: <th class='column-entry-bold'>MC/DC</th>
 // HTML-INDEX: <a href='coverage{{.*}}mcdc-general.cpp.html'{{.*}}mcdc-general.cpp</a>
 // HTML-INDEX: <td class='column-entry-green'>
 // HTML-INDEX: 100.00% (2/2)
diff --git a/llvm/test/tools/llvm-cov/showLineExecutionCounts.cpp b/llvm/test/tools/llvm-cov/showLineExecutionCounts.cpp
index 51ac3ae1deee55..a42928102c8560 100644
--- a/llvm/test/tools/llvm-cov/showLineExecutionCounts.cpp
+++ b/llvm/test/tools/llvm-cov/showLineExecutionCounts.cpp
@@ -58,10 +58,10 @@ int main() {                              // TEXT: [[@LINE]]|   161|int main(
 //
 // RUN: FileCheck -check-prefix HTML-INDEX -input-file %t.html.dir/index.html %s
 // HTML-INDEX-LABEL: <table>
-// HTML-INDEX: <td class='column-entry-bold'>Filename</td>
-// HTML-INDEX: <td class='column-entry-bold'>Function Coverage</td>
-// HTML-INDEX: <td class='column-entry-bold'>Line Coverage</td>
-// HTML-INDEX: <td class='column-entry-bold'>Region Coverage</td>
+// HTML-INDEX: <th class='column-entry-bold'>Filename</th>
+// HTML-INDEX: <th class='column-entry-bold'>Function Coverage</th>
+// HTML-INDEX: <th class='column-entry-bold'>Line Coverage</th>
+// HTML-INDEX: <th class='column-entry-bold'>Region Coverage</th>
 // HTML-INDEX: <a href='coverage{{.*}}showLineExecutionCounts.cpp.html'{{.*}}showLineExecutionCounts.cpp</a>
 // HTML-INDEX: <td class='column-entry-green'>
 // HTML-INDEX: 100.00% (1/1)
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
index e1aa5e4a05af78..82a1809a00139d 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
@@ -231,6 +231,9 @@ th, td {
   border-left: solid 1px #eee;
   text-align: left;
 }
+th {
+  cursor: pointer;
+}
 td pre {
   display: inline-block;
 }
@@ -248,6 +251,42 @@ tr:last-child {
 }
 )";
 
+const char *scriptForSorting = R"js(
+  <script>
+    const getCellValue = (tr, index) => {
+      const content = tr.children[index].innerText || tr.children[index].textContent;
+      
+      if (content == "- (0/0)") {
+        return Infinity;
+      }
+      
+      return content;
+    };
+    
+    const comparator = (index, asc) => (a, b) => {
+      if (asc) {
+        [a, b] = [b, a];
+      }
+      
+      const v1 = getCellValue(a, index);
+      const v2 = getCellValue(b, index);
+      
+      if (v1 !== '' && v2 !== '' && !isNaN(v1) && !isNaN(v1)) {
+        return v1 - v2;
+      }
+      
+      return v1.toString().localeCompare(v2);
+    };
+    
+    document.querySelectorAll('th').forEach(th => th.addEventListener('click', (() => {
+      const tbody = th.closest('table').querySelector('tbody');
+      Array.from(tbody.querySelectorAll('tr'))
+        .sort(comparator(Array.from(th.parentNode.children).indexOf(th), this.asc = !this.asc))
+        .forEach(tr => tbody.appendChild(tr));
+    })));
+  </script>
+)js";
+
 const char *EndHeader = "</head>";
 
 const char *BeginCenteredDiv = "<div class='centered'>";
@@ -270,6 +309,14 @@ const char *BeginExpansionDiv = "<div class='expansion-view'>";
 
 const char *EndExpansionDiv = "</div>";
 
+const char *BeginTableBody = "<tbody>";
+
+const char *EndTableBody = "</tbody>";
+
+const char *BeginTableFoot = "<tfoot>";
+
+const char *EndTableFoot = "</tfoot>";
+
 const char *BeginTable = "<table>";
 
 const char *EndTable = "</table>";
@@ -395,19 +442,19 @@ void CoveragePrinterHTML::closeViewFile(OwnedStream OS) {
 static void emitColumnLabelsForIndex(raw_ostream &OS,
                                      const CoverageViewOptions &Opts) {
   SmallVector<std::string, 4> Columns;
-  Columns.emplace_back(tag("td", "Filename", "column-entry-bold"));
-  Columns.emplace_back(tag("td", "Function Coverage", "column-entry-bold"));
+  Columns.emplace_back(tag("th", "Filename", "column-entry-bold"));
+  Columns.emplace_back(tag("th", "Function Coverage", "column-entry-bold"));
   if (Opts.ShowInstantiationSummary)
     Columns.emplace_back(
-        tag("td", "Instantiation Coverage", "column-entry-bold"));
-  Columns.emplace_back(tag("td", "Line Coverage", "column-entry-bold"));
+        tag("th", "Instantiation Coverage", "column-entry-bold"));
+  Columns.emplace_back(tag("th", "Line Coverage", "column-entry-bold"));
   if (Opts.ShowRegionSummary)
-    Columns.emplace_back(tag("td", "Region Coverage", "column-entry-bold"));
+    Columns.emplace_back(tag("th", "Region Coverage", "column-entry-bold"));
   if (Opts.ShowBranchSummary)
-    Columns.emplace_back(tag("td", "Branch Coverage", "column-entry-bold"));
+    Columns.emplace_back(tag("th", "Branch Coverage", "column-entry-bold"));
   if (Opts.ShowMCDCSummary)
-    Columns.emplace_back(tag("td", "MC/DC", "column-entry-bold"));
-  OS << tag("tr", join(Columns.begin(), Columns.end(), ""));
+    Columns.emplace_back(tag("th", "MC/DC", "column-entry-bold"));
+  OS << tag("thead", tag("tr", join(Columns.begin(), Columns.end(), "")));
 }
 
 std::string
@@ -490,6 +537,7 @@ Error CoveragePrinterHTML::createIndexFile(
 
   emitReportHeader(OSRef, "Coverage Report");
 
+  OSRef << BeginTableBody;
   FileCoverageSummary Totals("TOTALS");
   auto FileReports = CoverageReport::prepareFileReports(
       Coverage, Totals, SourceFiles, Opts, Filters);
@@ -500,7 +548,11 @@ Error CoveragePrinterHTML::createIndexFile(
     else
       EmptyFiles = true;
   }
+  OSRef << EndTableBody;
+  
+  OSRef << BeginTableFoot;
   emitFileSummary(OSRef, "Totals", Totals, /*IsTotals=*/true);
+  OSRef << EndTableFoot;
   OSRef << EndTable << EndCenteredDiv;
 
   // Emit links to files which don't contain any functions. These are normally
@@ -518,6 +570,8 @@ Error CoveragePrinterHTML::createIndexFile(
       }
     OSRef << EndTable << EndCenteredDiv;
   }
+  
+  OSRef << scriptForSorting;
 
   OSRef << tag("h5", escape(Opts.getLLVMVersionString(), Opts));
   emitEpilog(OSRef);
@@ -559,6 +613,7 @@ struct CoveragePrinterHTMLDirectory::Reporter : public DirectoryCoverageReport {
 
     std::vector<const FileCoverageSummary *> EmptyFiles;
 
+    OSRef << BeginTableBody;
     // Make directories at the top of the table.
     for (auto &&SubDir : SubDirs) {
       auto &Report = SubDir.second.first;
@@ -577,9 +632,12 @@ struct CoveragePrinterHTMLDirectory::Reporter : public DirectoryCoverageReport {
         emitTableRow(OSRef, Options, buildRelLinkToFile(Report.Name), Report,
                      /*IsTotals=*/false);
     }
+    OSRef << EndTableBody;
 
     // Emit the totals row.
+    OSRef << BeginTableFoot;
     emitTableRow(OSRef, Options, "Totals", SubTotals, /*IsTotals=*/false);
+    OSRef << EndTableFoot;
     OSRef << EndTable << EndCenteredDiv;
 
     // Emit links to files which don't contain any functions. These are normally



More information about the llvm-commits mailing list