diff options
author | George Karpenkov <ekarpenkov@apple.com> | 2018-01-17 02:59:11 +0000 |
---|---|---|
committer | George Karpenkov <ekarpenkov@apple.com> | 2018-01-17 02:59:11 +0000 |
commit | a5ddd3cacb01ede6576d14d7ff9a3faee7d80f06 (patch) | |
tree | e4315f5c4e8db7028c24b503db360a289a9c7803 /clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp | |
parent | 8321ad9ffc1290f914f7065965085d32961fc941 (diff) | |
download | bcm5719-llvm-a5ddd3cacb01ede6576d14d7ff9a3faee7d80f06.tar.gz bcm5719-llvm-a5ddd3cacb01ede6576d14d7ff9a3faee7d80f06.zip |
[analyzer] support a mode to only show relevant lines in HTML diagnostics
HTML diagnostics can be an overwhelming blob of pages of code.
This patch adds a checkbox which filters this list down to only the
lines *relevant* to the counterexample by e.g. skipping branches which
analyzer has assumed to be infeasible at a time.
The resulting amount of output is much smaller, and often fits on one
screen, and also provides a much more readable diagnostics.
Differential Revision: https://reviews.llvm.org/D41378
llvm-svn: 322612
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp index ebf1487d4bf..635625107f0 100644 --- a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp @@ -94,6 +94,13 @@ public: /// \return Javascript for navigating the HTML report using j/k keys. std::string generateKeyboardNavigationJavascript(); + +private: + /// \return JavaScript for an option to only show relevant lines. + std::string showRelevantLinesJavascript(const PathDiagnostic &D); + + /// \return Executed lines from \p D in JSON format. + std::string serializeExecutedLines(const PathDiagnostic &D); }; } // end anonymous namespace @@ -343,6 +350,10 @@ void HTMLDiagnostics::FinalizeHTML(const PathDiagnostic& D, Rewriter &R, R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), generateKeyboardNavigationJavascript()); + // Checkbox and javascript for filtering the output to the counterexample. + R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), + showRelevantLinesJavascript(D)); + // Add the name of the file as an <h1> tag. { std::string s; @@ -450,6 +461,94 @@ void HTMLDiagnostics::FinalizeHTML(const PathDiagnostic& D, Rewriter &R, html::AddHeaderFooterInternalBuiltinCSS(R, FID, Entry->getName()); } +std::string +HTMLDiagnostics::showRelevantLinesJavascript(const PathDiagnostic &D) { + std::string s; + llvm::raw_string_ostream os(s); + os << "<script type='text/javascript'>\n"; + os << serializeExecutedLines(D); + os << R"<<<( + +var filterCounterexample = function (hide) { + var tables = document.getElementsByClassName("code"); + for (var t=0; t<tables.length; t++) { + var table = tables[t]; + var file_id = table.getAttribute("data-fileid"); + var lines_in_fid = relevant_lines[file_id]; + if (!lines_in_fid) { + lines_in_fid = {}; + } + var lines = table.getElementsByClassName("codeline"); + for (var i=0; i<lines.length; i++) { + var el = lines[i]; + var lineNo = el.getAttribute("data-linenumber"); + if (!lines_in_fid[lineNo]) { + if (hide) { + el.setAttribute("hidden", ""); + } else { + el.removeAttribute("hidden"); + } + } + } + } +} + +window.addEventListener("keydown", function (event) { + if (event.defaultPrevented) { + return; + } + if (event.key == "S") { + var checked = document.getElementsByName("showCounterexample")[0].checked; + filterCounterexample(!checked); + document.getElementsByName("showCounterexample")[0].checked = !checked; + } else { + return; + } + event.preventDefault(); +}, true); + +document.addEventListener("DOMContentLoaded", function() { + document.querySelector('input[name="showCounterexample"]').onchange= + function (event) { + filterCounterexample(this.checked); + }; +}); +</script> + +<form> + <input type="checkbox" name="showCounterexample" /> + <label for="showCounterexample"> + Show only relevant lines + </label> +</form> +)<<<"; + + return os.str(); +} + +std::string HTMLDiagnostics::serializeExecutedLines(const PathDiagnostic &D) { + std::string s; + llvm::raw_string_ostream os(s); + os << "var relevant_lines = {"; + for (auto I = D.executedLines_begin(), + E = D.executedLines_end(); I != E; ++I) { + if (I != D.executedLines_begin()) + os << ", "; + + os << "\"" << I->first << "\": {"; + for (unsigned LineNo : I->second) { + if (LineNo != *(I->second.begin())) + os << ", "; + + os << "\"" << LineNo << "\": 1"; + } + os << "}"; + } + + os << "};"; + return os.str(); +} + void HTMLDiagnostics::RewriteFile(Rewriter &R, const SourceManager& SMgr, const PathPieces& path, FileID FID) { // Process the path. |