mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[llvm-cov] Add the "Go to first unexecuted line" feature.
This patch provides easy navigation to find the zero count lines, especially useful when the source file is very large. Differential Revision: https://reviews.llvm.org/D23277 llvm-svn: 280739
This commit is contained in:
parent
c45aa06c47
commit
961fc8f2d7
@ -19,3 +19,9 @@
|
||||
// HTML: tools\llvm-cov\Inputs\native_separators.covmapping</pre>
|
||||
|
||||
int main() {}
|
||||
|
||||
// Re-purpose this file to test that "Go to first unexecuted line" feature.
|
||||
|
||||
// RUN: llvm-cov show %S/Inputs/native_separators.covmapping -instr-profile %t.profdata -filename-equivalence -format html -o %t.dir %s
|
||||
// RUN: FileCheck -input-file %t.dir/coverage/tmp/native_separators.c.html %s
|
||||
// CHECK-NOT: >Go to first unexecuted line<
|
||||
|
@ -24,9 +24,9 @@ int main(int argc, char ** argv) {
|
||||
|
||||
// Test html output.
|
||||
// RUN: llvm-cov show %S/Inputs/showProjectSummary.covmapping -format=html -o %t.dir -instr-profile %t.profdata -filename-equivalence %s
|
||||
// RUN: FileCheck -check-prefixes=HTML,HTML-FILE,HTML-HEADER -input-file %t.dir/coverage/tmp/showProjectSummary.cpp.html %s
|
||||
// RUN: FileCheck -check-prefixes=HTML,HTML-FILE,HTML-HEADER,HTML-UNCOVEREDLINE -input-file %t.dir/coverage/tmp/showProjectSummary.cpp.html %s
|
||||
// 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
|
||||
// RUN: FileCheck -check-prefixes=HTML-TITLE,HTML,HTML-FILE,HTML-HEADER,HTML-UNCOVEREDLINE -input-file %t.dir/coverage/tmp/showProjectSummary.cpp.html %s
|
||||
// RUN: FileCheck -check-prefixes=HTML-TITLE,HTML -input-file %t.dir/index.html %s
|
||||
// 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
|
||||
@ -41,6 +41,7 @@ int main(int argc, char ** argv) {
|
||||
// HTML-FILE: <pre>Binary:
|
||||
// HTML-FILE: showProjectSummary.covmapping</pre>
|
||||
// HTML-FUNCTION: <pre>Function: main</pre>
|
||||
// HTML-UNCOVEREDLINE: <a href='#L8'>Go to first unexecuted line</a>
|
||||
// HTML-HEADER: <tr><td><span><pre>Line No.</pre></span></td>
|
||||
// HTML-HEADER: <td><span><pre>Count</pre></span></td>
|
||||
// HTML-HEADER: <td><span><pre>Source</pre></span></td>
|
||||
|
@ -82,6 +82,25 @@ CoveragePrinter::create(const CoverageViewOptions &Opts) {
|
||||
llvm_unreachable("Unknown coverage output format!");
|
||||
}
|
||||
|
||||
unsigned SourceCoverageView::getFirstUncoveredLineNo() {
|
||||
auto CheckIfUncovered = [](const coverage::CoverageSegment &S) {
|
||||
return S.HasCount && S.Count == 0;
|
||||
};
|
||||
// L is less than R if (1) it's an uncovered segment (has a 0 count), and (2)
|
||||
// either R is not an uncovered segment, or L has a lower line number than R.
|
||||
const auto MinSegIt =
|
||||
std::min_element(CoverageInfo.begin(), CoverageInfo.end(),
|
||||
[CheckIfUncovered](const coverage::CoverageSegment &L,
|
||||
const coverage::CoverageSegment &R) {
|
||||
return (CheckIfUncovered(L) &&
|
||||
(!CheckIfUncovered(R) || (L.Line < R.Line)));
|
||||
});
|
||||
if (CheckIfUncovered(*MinSegIt))
|
||||
return (*MinSegIt).Line;
|
||||
// There is no uncovered line, return zero.
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string SourceCoverageView::formatCount(uint64_t N) {
|
||||
std::string Number = utostr(N);
|
||||
int Len = Number.size();
|
||||
@ -142,8 +161,12 @@ void SourceCoverageView::print(raw_ostream &OS, bool WholeFile,
|
||||
|
||||
renderViewHeader(OS);
|
||||
|
||||
unsigned FirstUncoveredLineNo = 0;
|
||||
if (WholeFile)
|
||||
FirstUncoveredLineNo = getFirstUncoveredLineNo();
|
||||
|
||||
if (ShowSourceName)
|
||||
renderSourceName(OS, WholeFile);
|
||||
renderSourceName(OS, WholeFile, FirstUncoveredLineNo);
|
||||
|
||||
renderTableHeader(OS, ViewDepth);
|
||||
// We need the expansions and instantiations sorted so we can go through them
|
||||
|
@ -175,6 +175,9 @@ class SourceCoverageView {
|
||||
/// Specifies whether or not the view is a function view.
|
||||
bool FunctionView;
|
||||
|
||||
/// Get the first uncovered line number for the source file.
|
||||
unsigned getFirstUncoveredLineNo();
|
||||
|
||||
protected:
|
||||
struct LineRef {
|
||||
StringRef Line;
|
||||
@ -195,7 +198,8 @@ protected:
|
||||
virtual void renderViewFooter(raw_ostream &OS) = 0;
|
||||
|
||||
/// \brief Render the source name for the view.
|
||||
virtual void renderSourceName(raw_ostream &OS, bool WholeFile) = 0;
|
||||
virtual void renderSourceName(raw_ostream &OS, bool WholeFile,
|
||||
unsigned FirstUncoveredLineNo) = 0;
|
||||
|
||||
/// \brief Render the line prefix at the given \p ViewDepth.
|
||||
virtual void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) = 0;
|
||||
|
@ -338,7 +338,8 @@ void SourceCoverageViewHTML::renderViewFooter(raw_ostream &OS) {
|
||||
OS << EndTable << EndCenteredDiv;
|
||||
}
|
||||
|
||||
void SourceCoverageViewHTML::renderSourceName(raw_ostream &OS, bool WholeFile) {
|
||||
void SourceCoverageViewHTML::renderSourceName(raw_ostream &OS, bool WholeFile,
|
||||
unsigned FirstUncoveredLineNo) {
|
||||
OS << BeginSourceNameDiv;
|
||||
// Render the source name for the view.
|
||||
std::string SourceFile = isFunctionView() ? "Function: " : "Source: ";
|
||||
@ -347,10 +348,18 @@ void SourceCoverageViewHTML::renderSourceName(raw_ostream &OS, bool WholeFile) {
|
||||
sys::path::remove_dots(SourceText, /*remove_dot_dots=*/true);
|
||||
sys::path::native(SourceText);
|
||||
OS << tag("pre", escape(SourceText, getOptions()));
|
||||
// Render the object file name for the view.
|
||||
if (WholeFile)
|
||||
if (WholeFile) {
|
||||
// Render the object file name for the view.
|
||||
OS << tag("pre",
|
||||
escape("Binary: " + getOptions().ObjectFilename, getOptions()));
|
||||
// Render the "Go to first unexecuted line" link for the view.
|
||||
if (FirstUncoveredLineNo != 0) { // The file is not fully covered
|
||||
std::string LinkText =
|
||||
escape("Go to first unexecuted line", getOptions());
|
||||
std::string LinkTarget = "#L" + utostr(uint64_t(FirstUncoveredLineNo));
|
||||
OS << tag("pre", a(LinkTarget, LinkText));
|
||||
}
|
||||
}
|
||||
OS << EndSourceNameDiv;
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,8 @@ class SourceCoverageViewHTML : public SourceCoverageView {
|
||||
|
||||
void renderViewFooter(raw_ostream &OS) override;
|
||||
|
||||
void renderSourceName(raw_ostream &OS, bool WholeFile) override;
|
||||
void renderSourceName(raw_ostream &OS, bool WholeFile,
|
||||
unsigned FirstUncoveredLineNo) override;
|
||||
|
||||
void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) override;
|
||||
|
||||
|
@ -63,7 +63,8 @@ void SourceCoverageViewText::renderViewHeader(raw_ostream &) {}
|
||||
|
||||
void SourceCoverageViewText::renderViewFooter(raw_ostream &) {}
|
||||
|
||||
void SourceCoverageViewText::renderSourceName(raw_ostream &OS, bool WholeFile) {
|
||||
void SourceCoverageViewText::renderSourceName(raw_ostream &OS, bool WholeFile,
|
||||
unsigned FirstUncoveredLineNo) {
|
||||
getOptions().colored_ostream(OS, raw_ostream::CYAN) << getSourceName()
|
||||
<< ":\n";
|
||||
if (WholeFile) {
|
||||
|
@ -38,7 +38,8 @@ class SourceCoverageViewText : public SourceCoverageView {
|
||||
|
||||
void renderViewFooter(raw_ostream &OS) override;
|
||||
|
||||
void renderSourceName(raw_ostream &OS, bool WholeFile) override;
|
||||
void renderSourceName(raw_ostream &OS, bool WholeFile,
|
||||
unsigned FirstUncoveredLineNo) override;
|
||||
|
||||
void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) override;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user