Index: test/tools/llvm-cov/Inputs/showTabsHTML.proftext
===================================================================
--- /dev/null
+++ test/tools/llvm-cov/Inputs/showTabsHTML.proftext
@@ -0,0 +1,8 @@
+main
+# Func Hash:
+0
+# Num Counters:
+1
+# Counter Values:
+1
+
Index: test/tools/llvm-cov/showTabsHTML.cpp
===================================================================
--- /dev/null
+++ test/tools/llvm-cov/showTabsHTML.cpp
@@ -0,0 +1,16 @@
+// RUN: llvm-profdata merge -o %t.profdata %S/Inputs/showTabsHTML.proftext
+// RUN: llvm-cov show %S/Inputs/showTabsHTML.covmapping -format html -instr-profile %t.profdata -filename-equivalence %s | FileCheck -check-prefix=CHECK %s
+
+int main(int argc, char ** argv) {
+ (void) "This tab starts at column 0"; // CHECK: (void) "This tab starts at column 0";
+ (void) " This tab starts at column 10"; // CHECK: (void) " This tab starts at column 10";
+ (void) "This tab starts at column 15"; // CHECK: (void) "This tab starts at column 15";
+
+ return 0;
+}
+
+// RUN: llvm-cov show %S/Inputs/showTabsHTML.covmapping -format html -tab-size=3 -instr-profile %t.profdata -filename-equivalence %s | FileCheck -check-prefix=CHECK-TABSIZE %s
+
+// CHECK-TABSIZE: (void) "This tab starts at column 0";
+// CHECK-TABSIZE: (void) " This tab starts at column 10";
+// CHECK-TABSIZE: (void) "This tab starts at column 15";
\ No newline at end of file
Index: tools/llvm-cov/CodeCoverage.cpp
===================================================================
--- tools/llvm-cov/CodeCoverage.cpp
+++ tools/llvm-cov/CodeCoverage.cpp
@@ -584,6 +584,10 @@
cl::alias ShowOutputDirectoryA("o", cl::desc("Alias for --output-dir"),
cl::aliasopt(ShowOutputDirectory));
+ cl::opt TabSize(
+ "tab-size", cl::Hidden, cl::init(2),
+ cl::desc("Set tab size for the HTML coverage report (default = 2)"));
+
auto Err = commandLineParser(argc, argv);
if (Err)
return Err;
@@ -596,6 +600,7 @@
ViewOpts.ShowExpandedRegions = ShowExpansions;
ViewOpts.ShowFunctionInstantiations = ShowInstantiations;
ViewOpts.ShowOutputDirectory = ShowOutputDirectory;
+ ViewOpts.TabSize = TabSize;
if (ViewOpts.hasOutputDirectory()) {
if (auto E = sys::fs::create_directories(ViewOpts.ShowOutputDirectory)) {
Index: tools/llvm-cov/CoverageViewOptions.h
===================================================================
--- tools/llvm-cov/CoverageViewOptions.h
+++ tools/llvm-cov/CoverageViewOptions.h
@@ -34,6 +34,7 @@
OutputFormat Format;
std::string ShowOutputDirectory;
std::vector DemanglerOpts;
+ uint32_t TabSize;
/// \brief Change the output's stream color if the colors are enabled.
ColoredRawOstream colored_ostream(raw_ostream &OS,
Index: tools/llvm-cov/SourceCoverageViewHTML.cpp
===================================================================
--- tools/llvm-cov/SourceCoverageViewHTML.cpp
+++ tools/llvm-cov/SourceCoverageViewHTML.cpp
@@ -22,9 +22,11 @@
namespace {
// Return a string with the special characters in \p Str escaped.
-std::string escape(StringRef Str) {
+std::string escape(StringRef Str, const CoverageViewOptions &Opts) {
std::string Result;
+ unsigned ColNum = 0; // Record the column number.
for (char C : Str) {
+ ++ColNum;
if (C == '&')
Result += "&";
else if (C == '<')
@@ -33,7 +35,16 @@
Result += ">";
else if (C == '\"')
Result += """;
- else
+ else if (C == '\n' || C == '\r') {
+ Result += C;
+ ColNum = 0;
+ } else if (C == '\t') {
+ // Replace '\t' with TabSize spaces.
+ unsigned NumSpaces = Opts.TabSize - (--ColNum % Opts.TabSize);
+ for (unsigned I = 0; I < NumSpaces; ++I)
+ Result += " ";
+ ColNum += NumSpaces;
+ } else
Result += C;
}
return Result;
@@ -195,7 +206,8 @@
return PathToStyle + "style.css";
}
-void emitPrelude(raw_ostream &OS, const std::string &PathToStyle = "") {
+void emitPrelude(raw_ostream &OS, const CoverageViewOptions &Opts,
+ const std::string &PathToStyle = "") {
OS << ""
""
<< BeginHeader;
@@ -204,8 +216,8 @@
if (PathToStyle.empty())
OS << "";
else
- OS << "";
+ OS << "";
OS << EndHeader << "" << BeginCenteredDiv;
}
@@ -226,10 +238,10 @@
OwnedStream OS = std::move(OSOrErr.get());
if (!Opts.hasOutputDirectory()) {
- emitPrelude(*OS.get());
+ emitPrelude(*OS.get(), Opts);
} else {
std::string ViewPath = getOutputPath(Path, "html", InToplevel);
- emitPrelude(*OS.get(), getPathToStyle(ViewPath));
+ emitPrelude(*OS.get(), Opts, getPathToStyle(ViewPath));
}
return std::move(OS);
@@ -248,13 +260,13 @@
// Emit a table containing links to reports for each file in the covmapping.
assert(Opts.hasOutputDirectory() && "No output directory for index file");
- emitPrelude(OSRef, getPathToStyle(""));
+ emitPrelude(OSRef, Opts, getPathToStyle(""));
OSRef << BeginSourceNameDiv << "Index" << EndSourceNameDiv;
OSRef << BeginTable;
for (StringRef SF : SourceFiles) {
- std::string LinkText = escape(sys::path::relative_path(SF));
+ std::string LinkText = escape(sys::path::relative_path(SF), Opts);
std::string LinkTarget =
- escape(getOutputPath(SF, "html", /*InToplevel=*/false));
+ escape(getOutputPath(SF, "html", /*InToplevel=*/false), Opts);
OSRef << tag("tr", tag("td", tag("pre", a(LinkTarget, LinkText), "code")));
}
OSRef << EndTable;
@@ -280,7 +292,7 @@
}
void SourceCoverageViewHTML::renderSourceName(raw_ostream &OS) {
- OS << BeginSourceNameDiv << tag("pre", escape(getSourceName()))
+ OS << BeginSourceNameDiv << tag("pre", escape(getSourceName(), getOptions()))
<< EndSourceNameDiv;
}
@@ -336,7 +348,7 @@
// 2. Escape all of the snippets.
for (unsigned I = 0, E = Snippets.size(); I < E; ++I)
- Snippets[I] = escape(Snippets[I]);
+ Snippets[I] = escape(Snippets[I], getOptions());
// 3. Use \p WrappedSegment to set the highlight for snippet 0. Use segment
// 1 to set the highlight for snippet 2, segment 2 to set the highlight for