Index: test/tools/llvm-cov/Inputs/noZeroExecutionLine.proftext =================================================================== --- /dev/null +++ test/tools/llvm-cov/Inputs/noZeroExecutionLine.proftext @@ -0,0 +1,9 @@ +main +# Func Hash: +4 +# Num Counters: +2 +# Counter Values: +1 +10 + Index: test/tools/llvm-cov/Inputs/showProjectSummary.proftext =================================================================== --- /dev/null +++ test/tools/llvm-cov/Inputs/showProjectSummary.proftext @@ -0,0 +1,10 @@ +main +# Func Hash: +266 +# Num Counters: +3 +# Counter Values: +1 +20 +0 + Index: test/tools/llvm-cov/binary-formats.c =================================================================== --- test/tools/llvm-cov/binary-formats.c +++ test/tools/llvm-cov/binary-formats.c @@ -1,6 +1,6 @@ // Checks for reading various formats. -// CHECK: 100| [[@LINE+1]]|int main +// CHECK: [[@LINE+1]]| 100|int main int main(int argc, const char *argv[]) {} // RUN: llvm-profdata merge %S/Inputs/binary-formats.proftext -o %t.profdata Index: test/tools/llvm-cov/combine_expansions.cpp =================================================================== --- test/tools/llvm-cov/combine_expansions.cpp +++ test/tools/llvm-cov/combine_expansions.cpp @@ -5,22 +5,22 @@ #define SIMPLE_OP \ ++x -// CHECK: | [[@LINE-2]]|#define SIMPLE_OP -// CHECK-NEXT: 2| [[@LINE-2]]| ++x +// CHECK: [[@LINE-2]]| |#define SIMPLE_OP +// CHECK-NEXT: [[@LINE-2]]| 2| ++x #define DO_SOMETHING \ { \ int x = 0; \ SIMPLE_OP; \ } -// CHECK: | [[@LINE-5]]|#define DO_SOMETHING -// CHECK-NEXT: 2| [[@LINE-5]]| { -// CHECK-NEXT: 2| [[@LINE-5]]| int x = 0; -// CHECK-NEXT: 2| [[@LINE-5]]| SIMPLE_OP; -// CHECK-NEXT: 2| [[@LINE-5]]| } +// CHECK: [[@LINE-5]]| |#define DO_SOMETHING +// CHECK-NEXT: [[@LINE-5]]| 2| { +// CHECK-NEXT: [[@LINE-5]]| 2| int x = 0; +// CHECK-NEXT: [[@LINE-5]]| 2| SIMPLE_OP; +// CHECK-NEXT: [[@LINE-5]]| 2| } -int main() { // CHECK: 1| [[@LINE]]|int main() { - DO_SOMETHING; // CHECK-NEXT: 1| [[@LINE]]| DO_SOMETHING; - DO_SOMETHING; // CHECK-NEXT: 1| [[@LINE]]| DO_SOMETHING; - return 0; // CHECK-NEXT: 1| [[@LINE]]| return 0; -} // CHECK-NEXT: 1| [[@LINE]]|} +int main() { // CHECK: [[@LINE]]| 1|int main() { + DO_SOMETHING; // CHECK-NEXT: [[@LINE]]| 1| DO_SOMETHING; + DO_SOMETHING; // CHECK-NEXT: [[@LINE]]| 1| DO_SOMETHING; + return 0; // CHECK-NEXT: [[@LINE]]| 1| return 0; +} // CHECK-NEXT: [[@LINE]]| 1|} Index: test/tools/llvm-cov/noZeroExecutionLine.cpp =================================================================== --- /dev/null +++ test/tools/llvm-cov/noZeroExecutionLine.cpp @@ -0,0 +1,16 @@ +// RUN: llvm-profdata merge -o %t.profdata %S/Inputs/noZeroExecutionLine.proftext +// RUN: llvm-cov show %S/Inputs/noZeroExecutionLine.covmapping -instr-profile %t.profdata -filename-equivalence -format html -output-dir %t.dir %s +// RUN: FileCheck -check-prefix=CHECK -check-prefix=WHOLE-FILE -input-file %t.dir/coverage/tmp/noZeroExecutionLine.cpp.html %s + +int main(int argc, char ** argv) { + int x=0; + for (int i = 0; i < 10; ++i) + x *= 2; + return x; +} + +// CHECK: Goto first zero count +// CHECK-NOT: +// CHECK: "; + +// Define a javascript function that disables a hyper link. +const char *JSDisableLink = R"( +function disableLink(link) { + link.disabled = true; + link.removeAttribute('href'); +} +)"; + +// Return a string with the special characters in \p Str escaped. +const char *JSRemoveZeroLink = R"( +var zeroLink = document.getElementById("zeroline"); +disableLink(zeroLink); +)"; + std::string getPathToStyle(StringRef ViewPath) { std::string PathToStyle = ""; std::string PathSep = sys::path::get_separator(); @@ -219,12 +271,12 @@ OS << ""; - OS << EndHeader << "" << BeginCenteredDiv; + OS << EndHeader << ""; } void emitEpilog(raw_ostream &OS) { - OS << EndCenteredDiv << "" - ""; + OS << "" + << ""; } } // anonymous namespace @@ -261,15 +313,25 @@ // Emit a table containing links to reports for each file in the covmapping. assert(Opts.hasOutputDirectory() && "No output directory for index file"); emitPrelude(OSRef, Opts, getPathToStyle("")); - OSRef << BeginSourceNameDiv << "Index" << EndSourceNameDiv; - OSRef << BeginTable; + if (Opts.hasProjectTitle()) + OSRef << BeginProjectTitleDiv + << tag("span", escape(Opts.ProjectTitle, Opts)) << EndProjectTitleDiv; + OSRef << BeginReportTitleDiv + << tag("span", escape("Code Coverage Report", Opts)) + << EndReportTitleDiv; + OSRef << BeginCreatedTimeDiv + << tag("span", escape(SourceCoverageView::CreatedTimeStr, Opts)) + << EndCreatedTimeDiv; + OSRef << LineBreak; + OSRef << BeginCenteredDiv << BeginTable; + OSRef << BeginSourceHeaderDiv << "Index" << EndSourceHeaderDiv; for (StringRef SF : SourceFiles) { std::string LinkText = escape(sys::path::relative_path(SF), Opts); std::string LinkTarget = escape(getOutputPath(SF, "html", /*InToplevel=*/false), Opts); OSRef << tag("tr", tag("td", tag("pre", a(LinkTarget, LinkText), "code"))); } - OSRef << EndTable; + OSRef << EndTable << EndCenteredDiv; emitEpilog(OSRef); // Emit the default stylesheet. @@ -284,20 +346,44 @@ } void SourceCoverageViewHTML::renderViewHeader(raw_ostream &OS) { - OS << BeginTable; + OS << BeginCenteredDiv << BeginTable; } void SourceCoverageViewHTML::renderViewFooter(raw_ostream &OS) { - OS << EndTable; + OS << EndTable << EndCenteredDiv; +} + +void SourceCoverageViewHTML::renderSourceHeaderPrefix(raw_ostream &OS) { + OS << BeginSourceHeaderDiv; } void SourceCoverageViewHTML::renderSourceName(raw_ostream &OS) { - OS << BeginSourceNameDiv << tag("pre", escape(getSourceName(), getOptions())) - << EndSourceNameDiv; + std::string SourceFile = getSourceName().str(); + SourceFile = sys::path::has_extension(SourceFile) + ? "Source file: " + SourceFile + : "Function: " + SourceFile; + OS << tag("pre", escape(SourceFile, getOptions())); +} + +void SourceCoverageViewHTML::renderObjectFilename(raw_ostream &OS) { + SmallString<128> ObjectFilePath(getOptions().ObjectFilename); + SmallString<128> ObjectFile("Binary file: "); + ObjectFile.append(ObjectFilePath); + OS << tag("pre", escape(ObjectFile.c_str(), getOptions())); +} + +void SourceCoverageViewHTML::renderGotoFirstZero(raw_ostream &OS) { + OS << BeginPre << " " + << "Goto first zero count" << EndPre; } -void SourceCoverageViewHTML::renderLinePrefix(raw_ostream &OS, unsigned) { - OS << ""; +void SourceCoverageViewHTML::renderSourceHeaderSuffix(raw_ostream &OS) { + OS << EndSourceHeaderDiv; +} + +void SourceCoverageViewHTML::renderLinePrefix(raw_ostream &OS, unsigned, + bool IsFirstZeroLine = false) { + OS << (IsFirstZeroLine ? "" : ""); } void SourceCoverageViewHTML::renderLineSuffix(raw_ostream &OS, unsigned) { @@ -489,3 +575,50 @@ ISV.View->print(OS, /*WholeFile=*/false, /*ShowSourceName=*/true, ViewDepth); OS << EndExpansionDiv; } + +void SourceCoverageViewHTML::renderProjectTitle(raw_ostream &OS) { + OS << BeginProjectTitleDiv + << tag("span", escape(getOptions().ProjectTitle, getOptions())) + << EndProjectTitleDiv; +} + +void SourceCoverageViewHTML::renderReportTitle(raw_ostream &OS) { + OS << BeginReportTitleDiv + << tag("span", escape("Code Coverage Report", getOptions())) + << EndReportTitleDiv; +} + +void SourceCoverageViewHTML::renderCreatedTime(raw_ostream &OS) { + OS << BeginCreatedTimeDiv + << tag("span", escape(SourceCoverageView::CreatedTimeStr, getOptions())) + << EndCreatedTimeDiv; +} + +void SourceCoverageViewHTML::renderProjectSummary(raw_ostream &OS) { + if (getOptions().hasProjectTitle()) + renderProjectTitle(OS); + renderReportTitle(OS); + renderCreatedTime(OS); + OS << LineBreak; +} + +void SourceCoverageViewHTML::renderTableHeader(raw_ostream &OS, + unsigned ViewDepth) { + renderLinePrefix(OS, ViewDepth); + OS << tag("td", tag("span", tag("pre", escape("Line No.", getOptions())))) + << tag("td", tag("span", tag("pre", escape("Count No.", getOptions())))) + << tag("td", tag("span", tag("pre", escape("Source", getOptions())))); + renderLineSuffix(OS, ViewDepth); +} + +void SourceCoverageViewHTML::renderJavaScriptHeader(raw_ostream &OS) { + OS << BeginJavaScript ; +} + +void SourceCoverageViewHTML::renderJavaScriptBody(raw_ostream &OS) { + OS << JSDisableLink << JSRemoveZeroLink; +} + +void SourceCoverageViewHTML::renderJavaScriptFooter(raw_ostream &OS) { + OS << EndJavaScript; +} Index: tools/llvm-cov/SourceCoverageViewText.h =================================================================== --- tools/llvm-cov/SourceCoverageViewText.h +++ tools/llvm-cov/SourceCoverageViewText.h @@ -38,9 +38,17 @@ void renderViewFooter(raw_ostream &OS) override; + void renderSourceHeaderPrefix(raw_ostream &OS) override; + void renderSourceName(raw_ostream &OS) override; - void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) override; + void renderObjectFilename(raw_ostream &OS) override; + + void renderGotoFirstZero(raw_ostream &OS) override; + + void renderSourceHeaderSuffix(raw_ostream &OS) override; + + void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth, bool IsFirstZeroLine) override; void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) override; @@ -70,6 +78,22 @@ void renderRegionMarkers(raw_ostream &OS, CoverageSegmentArray Segments, unsigned ViewDepth) override; + void renderProjectTitle(raw_ostream &OS) override; + + void renderReportTitle(raw_ostream &OS) override; + + void renderCreatedTime(raw_ostream &OS) override; + + void renderProjectSummary(raw_ostream &OS) override; + + void renderTableHeader(raw_ostream &OS, unsigned IndentLevel) override; + + void renderJavaScriptHeader(raw_ostream &OS) override; + + void renderJavaScriptBody(raw_ostream &OS) override; + + void renderJavaScriptFooter(raw_ostream &OS) override; + public: SourceCoverageViewText(StringRef SourceName, const MemoryBuffer &File, const CoverageViewOptions &Options, Index: tools/llvm-cov/SourceCoverageViewText.cpp =================================================================== --- tools/llvm-cov/SourceCoverageViewText.cpp +++ tools/llvm-cov/SourceCoverageViewText.cpp @@ -63,13 +63,25 @@ void SourceCoverageViewText::renderViewFooter(raw_ostream &) {} +void SourceCoverageViewText::renderSourceHeaderPrefix(raw_ostream &OS) {} + void SourceCoverageViewText::renderSourceName(raw_ostream &OS) { getOptions().colored_ostream(OS, raw_ostream::CYAN) << getSourceName() << ":\n"; } +void SourceCoverageViewText::renderObjectFilename(raw_ostream &OS) { + getOptions().colored_ostream(OS, raw_ostream::CYAN) + << getOptions().ObjectFilename << ":\n"; +} + +void SourceCoverageViewText::renderGotoFirstZero(raw_ostream &OS) {} + +void SourceCoverageViewText::renderSourceHeaderSuffix(raw_ostream &OS) {} + void SourceCoverageViewText::renderLinePrefix(raw_ostream &OS, - unsigned ViewDepth) { + unsigned ViewDepth, + bool IsFirstZeroLine = false) { for (unsigned I = 0; I < ViewDepth; ++I) OS << " |"; } @@ -211,3 +223,39 @@ OS << ' '; ISV.View->print(OS, /*WholeFile=*/false, /*ShowSourceName=*/true, ViewDepth); } + +void SourceCoverageViewText::renderProjectTitle(raw_ostream &OS) { + getOptions().colored_ostream(OS, raw_ostream::CYAN) + << getOptions().ProjectTitle << "\n"; +} + +void SourceCoverageViewText::renderReportTitle(raw_ostream &OS) { + getOptions().colored_ostream(OS, raw_ostream::CYAN) << "Code coverage report" + << "\n"; +} + +void SourceCoverageViewText::renderCreatedTime(raw_ostream &OS) { + getOptions().colored_ostream(OS, raw_ostream::CYAN) + << SourceCoverageView::CreatedTimeStr << "\n"; +} + +void SourceCoverageViewText::renderProjectSummary(raw_ostream &OS) { + if (getOptions().hasProjectTitle()) + renderProjectTitle(OS); + renderReportTitle(OS); + renderCreatedTime(OS); +} + +void SourceCoverageViewText::renderTableHeader(raw_ostream &OS, + unsigned ViewDepth) { + renderLinePrefix(OS, ViewDepth); + getOptions().colored_ostream(OS, raw_ostream::WHITE) + << " Line| Count|Source\n"; + renderLineSuffix(OS, ViewDepth); +} + +void SourceCoverageViewText::renderJavaScriptHeader(raw_ostream &OS) {} + +void SourceCoverageViewText::renderJavaScriptBody(raw_ostream &OS) {} + +void SourceCoverageViewText::renderJavaScriptFooter(raw_ostream &OS) {}