diff options
Diffstat (limited to 'contrib/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp')
| -rw-r--r-- | contrib/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp | 158 | 
1 files changed, 97 insertions, 61 deletions
diff --git a/contrib/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp b/contrib/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp index 64b888e89d79..e45c6f4cb473 100644 --- a/contrib/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp +++ b/contrib/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp @@ -16,7 +16,6 @@  #include "llvm/ADT/Optional.h"  #include "llvm/ADT/SmallString.h"  #include "llvm/ADT/StringExtras.h" -#include "llvm/Support/FileSystem.h"  #include "llvm/Support/Format.h"  #include "llvm/Support/Path.h" @@ -285,15 +284,31 @@ void CoveragePrinterHTML::closeViewFile(OwnedStream OS) {  }  /// Emit column labels for the table in the index. -static void emitColumnLabelsForIndex(raw_ostream &OS) { +static void emitColumnLabelsForIndex(raw_ostream &OS, +                                     const CoverageViewOptions &Opts) {    SmallVector<std::string, 4> Columns;    Columns.emplace_back(tag("td", "Filename", "column-entry-left")); -  for (const char *Label : {"Function Coverage", "Instantiation Coverage", -                            "Line Coverage", "Region Coverage"}) -    Columns.emplace_back(tag("td", Label, "column-entry")); +  Columns.emplace_back(tag("td", "Function Coverage", "column-entry")); +  if (Opts.ShowInstantiationSummary) +    Columns.emplace_back(tag("td", "Instantiation Coverage", "column-entry")); +  Columns.emplace_back(tag("td", "Line Coverage", "column-entry")); +  if (Opts.ShowRegionSummary) +    Columns.emplace_back(tag("td", "Region Coverage", "column-entry"));    OS << tag("tr", join(Columns.begin(), Columns.end(), ""));  } +std::string +CoveragePrinterHTML::buildLinkToFile(StringRef SF, +                                     const FileCoverageSummary &FCS) const { +  SmallString<128> LinkTextStr(sys::path::relative_path(FCS.Name)); +  sys::path::remove_dots(LinkTextStr, /*remove_dot_dots=*/true); +  sys::path::native(LinkTextStr); +  std::string LinkText = escape(LinkTextStr, Opts); +  std::string LinkTarget = +      escape(getOutputPath(SF, "html", /*InToplevel=*/false), Opts); +  return a(LinkTarget, LinkText); +} +  /// 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, @@ -326,34 +341,31 @@ void CoveragePrinterHTML::emitFileSummary(raw_ostream &OS, StringRef SF,    if (IsTotals) {      Filename = "TOTALS";    } else { -    SmallString<128> LinkTextStr(sys::path::relative_path(FCS.Name)); -    sys::path::remove_dots(LinkTextStr, /*remove_dot_dots=*/true); -    sys::path::native(LinkTextStr); -    std::string LinkText = escape(LinkTextStr, Opts); -    std::string LinkTarget = -        escape(getOutputPath(SF, "html", /*InToplevel=*/false), Opts); -    Filename = a(LinkTarget, LinkText); +    Filename = buildLinkToFile(SF, FCS);    }    Columns.emplace_back(tag("td", tag("pre", Filename))); -  AddCoverageTripleToColumn(FCS.FunctionCoverage.Executed, -                            FCS.FunctionCoverage.NumFunctions, +  AddCoverageTripleToColumn(FCS.FunctionCoverage.getExecuted(), +                            FCS.FunctionCoverage.getNumFunctions(),                              FCS.FunctionCoverage.getPercentCovered()); -  AddCoverageTripleToColumn(FCS.InstantiationCoverage.Executed, -                            FCS.InstantiationCoverage.NumFunctions, -                            FCS.InstantiationCoverage.getPercentCovered()); -  AddCoverageTripleToColumn(FCS.LineCoverage.Covered, FCS.LineCoverage.NumLines, +  if (Opts.ShowInstantiationSummary) +    AddCoverageTripleToColumn(FCS.InstantiationCoverage.getExecuted(), +                              FCS.InstantiationCoverage.getNumFunctions(), +                              FCS.InstantiationCoverage.getPercentCovered()); +  AddCoverageTripleToColumn(FCS.LineCoverage.getCovered(), +                            FCS.LineCoverage.getNumLines(),                              FCS.LineCoverage.getPercentCovered()); -  AddCoverageTripleToColumn(FCS.RegionCoverage.Covered, -                            FCS.RegionCoverage.NumRegions, -                            FCS.RegionCoverage.getPercentCovered()); +  if (Opts.ShowRegionSummary) +    AddCoverageTripleToColumn(FCS.RegionCoverage.getCovered(), +                              FCS.RegionCoverage.getNumRegions(), +                              FCS.RegionCoverage.getPercentCovered());    OS << tag("tr", join(Columns.begin(), Columns.end(), ""), "light-row");  }  Error CoveragePrinterHTML::createIndexFile( -    ArrayRef<std::string> SourceFiles, -    const coverage::CoverageMapping &Coverage) { +    ArrayRef<std::string> SourceFiles, const CoverageMapping &Coverage, +    const CoverageFiltersMatchAll &Filters) {    // Emit the default stylesheet.    auto CSSOrErr = createOutputStream("style", "css", /*InToplevel=*/true);    if (Error E = CSSOrErr.takeError()) @@ -387,16 +399,39 @@ Error CoveragePrinterHTML::createIndexFile(                          " for information about interpreting this report.");    // Emit a table containing links to reports for each file in the covmapping. +  // Exclude files which don't contain any regions.    OSRef << BeginCenteredDiv << BeginTable; -  emitColumnLabelsForIndex(OSRef); +  emitColumnLabelsForIndex(OSRef, Opts);    FileCoverageSummary Totals("TOTALS"); -  auto FileReports = -      CoverageReport::prepareFileReports(Coverage, Totals, SourceFiles); -  for (unsigned I = 0, E = FileReports.size(); I < E; ++I) -    emitFileSummary(OSRef, SourceFiles[I], FileReports[I]); +  auto FileReports = CoverageReport::prepareFileReports( +      Coverage, Totals, SourceFiles, Opts, Filters); +  bool EmptyFiles = false; +  for (unsigned I = 0, E = FileReports.size(); I < E; ++I) { +    if (FileReports[I].FunctionCoverage.getNumFunctions()) +      emitFileSummary(OSRef, SourceFiles[I], FileReports[I]); +    else +      EmptyFiles = true; +  }    emitFileSummary(OSRef, "Totals", Totals, /*IsTotals=*/true); -  OSRef << EndTable << EndCenteredDiv -        << tag("h5", escape(Opts.getLLVMVersionString(), Opts)); +  OSRef << EndTable << EndCenteredDiv; + +  // Emit links to files which don't contain any functions. These are normally +  // not very useful, but could be relevant for code which abuses the +  // preprocessor. +  if (EmptyFiles && Filters.empty()) { +    OSRef << tag("p", "Files which contain no functions. (These " +                      "files contain code pulled into other files " +                      "by the preprocessor.)\n"); +    OSRef << BeginCenteredDiv << BeginTable; +    for (unsigned I = 0, E = FileReports.size(); I < E; ++I) +      if (!FileReports[I].FunctionCoverage.getNumFunctions()) { +        std::string Link = buildLinkToFile(SourceFiles[I], FileReports[I]); +        OSRef << tag("tr", tag("td", tag("pre", Link)), "light-row") << '\n'; +      } +    OSRef << EndTable << EndCenteredDiv; +  } + +  OSRef << tag("h5", escape(Opts.getLLVMVersionString(), Opts));    emitEpilog(OSRef);    return Error::success(); @@ -431,9 +466,9 @@ void SourceCoverageViewHTML::renderViewDivider(raw_ostream &, unsigned) {    // The table-based output makes view dividers unnecessary.  } -void SourceCoverageViewHTML::renderLine( -    raw_ostream &OS, LineRef L, const coverage::CoverageSegment *WrappedSegment, -    CoverageSegmentArray Segments, unsigned ExpansionCol, unsigned) { +void SourceCoverageViewHTML::renderLine(raw_ostream &OS, LineRef L, +                                        const LineCoverageStats &LCS, +                                        unsigned ExpansionCol, unsigned) {    StringRef Line = L.Line;    unsigned LineNo = L.LineNo; @@ -445,6 +480,7 @@ void SourceCoverageViewHTML::renderLine(    //    at the end of the line. Both are required but may be empty.    SmallVector<std::string, 8> Snippets; +  CoverageSegmentArray Segments = LCS.getLineSegments();    unsigned LCol = 1;    auto Snip = [&](unsigned Start, unsigned Len) { @@ -469,7 +505,7 @@ void SourceCoverageViewHTML::renderLine(    //    1 to set the highlight for snippet 2, segment 2 to set the highlight for    //    snippet 3, and so on. -  Optional<std::string> Color; +  Optional<StringRef> Color;    SmallVector<std::pair<unsigned, unsigned>, 2> HighlightedRanges;    auto Highlight = [&](const std::string &Snippet, unsigned LC, unsigned RC) {      if (getOptions().Debug) @@ -477,11 +513,12 @@ void SourceCoverageViewHTML::renderLine(      return tag("span", Snippet, Color.getValue());    }; -  auto CheckIfUncovered = [](const coverage::CoverageSegment *S) { -    return S && S->HasCount && S->Count == 0; +  auto CheckIfUncovered = [&](const CoverageSegment *S) { +    return S && (!S->IsGapRegion || (Color && *Color == "red")) && +           S->HasCount && S->Count == 0;    }; -  if (CheckIfUncovered(WrappedSegment)) { +  if (CheckIfUncovered(LCS.getWrappedSegment())) {      Color = "red";      if (!Snippets[0].empty())        Snippets[0] = Highlight(Snippets[0], 1, 1 + Snippets[0].size()); @@ -489,10 +526,10 @@ void SourceCoverageViewHTML::renderLine(    for (unsigned I = 0, E = Segments.size(); I < E; ++I) {      const auto *CurSeg = Segments[I]; -    if (CurSeg->Col == ExpansionCol) -      Color = "cyan"; -    else if (CheckIfUncovered(CurSeg)) +    if (CheckIfUncovered(CurSeg))        Color = "red"; +    else if (CurSeg->Col == ExpansionCol) +      Color = "cyan";      else        Color = None; @@ -518,25 +555,23 @@ void SourceCoverageViewHTML::renderLine(    // 4. Snippets[1:N+1] correspond to \p Segments[0:N]: use these to generate    //    sub-line region count tooltips if needed. -  bool HasMultipleRegions = [&] { -    unsigned RegionCount = 0; -    for (const auto *S : Segments) -      if (S->HasCount && S->IsRegionEntry) -        if (++RegionCount > 1) -          return true; -    return false; -  }(); - -  if (shouldRenderRegionMarkers(HasMultipleRegions)) { -    for (unsigned I = 0, E = Segments.size(); I < E; ++I) { +  if (shouldRenderRegionMarkers(LCS)) { +    // Just consider the segments which start *and* end on this line. +    for (unsigned I = 0, E = Segments.size() - 1; I < E; ++I) {        const auto *CurSeg = Segments[I]; -      if (!CurSeg->IsRegionEntry || !CurSeg->HasCount) +      if (!CurSeg->IsRegionEntry) +        continue; +      if (CurSeg->Count == LCS.getExecutionCount())          continue;        Snippets[I + 1] =            tag("div", Snippets[I + 1] + tag("span", formatCount(CurSeg->Count),                                             "tooltip-content"),                "tooltip"); + +      if (getOptions().Debug) +        errs() << "Marker at " << CurSeg->Line << ":" << CurSeg->Col << " = " +               << formatCount(CurSeg->Count) << "\n";      }    } @@ -556,9 +591,9 @@ void SourceCoverageViewHTML::renderLineCoverageColumn(      raw_ostream &OS, const LineCoverageStats &Line) {    std::string Count = "";    if (Line.isMapped()) -    Count = tag("pre", formatCount(Line.ExecutionCount)); +    Count = tag("pre", formatCount(Line.getExecutionCount()));    std::string CoverageClass = -      (Line.ExecutionCount > 0) ? "covered-line" : "uncovered-line"; +      (Line.getExecutionCount() > 0) ? "covered-line" : "uncovered-line";    OS << tag("td", Count, CoverageClass);  } @@ -571,16 +606,17 @@ void SourceCoverageViewHTML::renderLineNumberColumn(raw_ostream &OS,  }  void SourceCoverageViewHTML::renderRegionMarkers(raw_ostream &, -                                                 CoverageSegmentArray, +                                                 const LineCoverageStats &Line,                                                   unsigned) {    // Region markers are rendered in-line using tooltips.  } -void SourceCoverageViewHTML::renderExpansionSite( -    raw_ostream &OS, LineRef L, const coverage::CoverageSegment *WrappedSegment, -    CoverageSegmentArray Segments, unsigned ExpansionCol, unsigned ViewDepth) { +void SourceCoverageViewHTML::renderExpansionSite(raw_ostream &OS, LineRef L, +                                                 const LineCoverageStats &LCS, +                                                 unsigned ExpansionCol, +                                                 unsigned ViewDepth) {    // Render the line containing the expansion site. No extra formatting needed. -  renderLine(OS, L, WrappedSegment, Segments, ExpansionCol, ViewDepth); +  renderLine(OS, L, LCS, ExpansionCol, ViewDepth);  }  void SourceCoverageViewHTML::renderExpansionView(raw_ostream &OS, @@ -588,7 +624,7 @@ void SourceCoverageViewHTML::renderExpansionView(raw_ostream &OS,                                                   unsigned ViewDepth) {    OS << BeginExpansionDiv;    ESV.View->print(OS, /*WholeFile=*/false, /*ShowSourceName=*/false, -                  ViewDepth + 1); +                  /*ShowTitle=*/false, ViewDepth + 1);    OS << EndExpansionDiv;  } @@ -604,7 +640,7 @@ void SourceCoverageViewHTML::renderInstantiationView(raw_ostream &OS,         << EndSourceNameDiv;    else      ISV.View->print(OS, /*WholeFile=*/false, /*ShowSourceName=*/true, -                    ViewDepth); +                    /*ShowTitle=*/false, ViewDepth);    OS << EndExpansionDiv;  }  | 
