summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
diff options
context:
space:
mode:
authorGeorge Karpenkov <ekarpenkov@apple.com>2018-01-17 02:59:11 +0000
committerGeorge Karpenkov <ekarpenkov@apple.com>2018-01-17 02:59:11 +0000
commita5ddd3cacb01ede6576d14d7ff9a3faee7d80f06 (patch)
treee4315f5c4e8db7028c24b503db360a289a9c7803 /clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp
parent8321ad9ffc1290f914f7065965085d32961fc941 (diff)
downloadbcm5719-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.cpp99
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.
OpenPOWER on IntegriCloud