diff options
| author | George Karpenkov <ekarpenkov@apple.com> | 2017-12-21 22:57:51 +0000 |
|---|---|---|
| committer | George Karpenkov <ekarpenkov@apple.com> | 2017-12-21 22:57:51 +0000 |
| commit | 151407c35be5c1b77e742ce501bdfa930419f484 (patch) | |
| tree | e0920ada4163f2f1620b236074da0a92e104d5c6 | |
| parent | f72fb7e989d94e53e827b2d70fdb435089026824 (diff) | |
| download | bcm5719-llvm-151407c35be5c1b77e742ce501bdfa930419f484.tar.gz bcm5719-llvm-151407c35be5c1b77e742ce501bdfa930419f484.zip | |
[analyzer] Add Javascript to analyzer HTML output to allow keyboard navigation.
Differential Revision: https://reviews.llvm.org/D41414
llvm-svn: 321320
| -rw-r--r-- | clang/lib/Rewrite/HTMLRewrite.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp | 95 |
2 files changed, 94 insertions, 2 deletions
diff --git a/clang/lib/Rewrite/HTMLRewrite.cpp b/clang/lib/Rewrite/HTMLRewrite.cpp index 23d1895e31b..618c0179f10 100644 --- a/clang/lib/Rewrite/HTMLRewrite.cpp +++ b/clang/lib/Rewrite/HTMLRewrite.cpp @@ -342,6 +342,7 @@ void html::AddHeaderFooterInternalBuiltinCSS(Rewriter &R, FileID FID, " .CodeInsertionHint { font-weight: bold; background-color: #10dd10 }\n" " .CodeRemovalHint { background-color:#de1010 }\n" " .CodeRemovalHint { border-bottom:1px solid #6F9DBE }\n" + " .selected{ background-color:orange !important; }\n" " table.simpletable {\n" " padding: 5px;\n" " font-size:12pt;\n" diff --git a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp index 9b820e81e37..ebf1487d4bf 100644 --- a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp @@ -91,6 +91,9 @@ public: // Rewrite the file specified by FID with HTML formatting. void RewriteFile(Rewriter &R, const SourceManager& SMgr, const PathPieces& path, FileID FID); + + /// \return Javascript for navigating the HTML report using j/k keys. + std::string generateKeyboardNavigationJavascript(); }; } // end anonymous namespace @@ -337,6 +340,9 @@ void HTMLDiagnostics::FinalizeHTML(const PathDiagnostic& D, Rewriter &R, int LineNumber = path.back()->getLocation().asLocation().getExpansionLineNumber(); int ColumnNumber = path.back()->getLocation().asLocation().getExpansionColumnNumber(); + R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), + generateKeyboardNavigationJavascript()); + // Add the name of the file as an <h1> tag. { std::string s; @@ -378,8 +384,14 @@ void HTMLDiagnostics::FinalizeHTML(const PathDiagnostic& D, Rewriter &R, os << "<tr><td></td><td>" << html::EscapeText(*I) << "</td></tr>\n"; } - os << "</table>\n<!-- REPORTSUMMARYEXTRA -->\n" - "<h3>Annotated Source Code</h3>\n"; + os << R"<<<( +</table> +<!-- REPORTSUMMARYEXTRA --> +<h3>Annotated Source Code</h3> +<p><span class='macro'>[?] + <span class='expansion'>Use j/k keys for keyboard navigation</span> +</span></p> +)<<<"; R.InsertTextBefore(SMgr.getLocForStartOfFile(FID), os.str()); } @@ -777,3 +789,82 @@ void HTMLDiagnostics::HighlightRange(Rewriter& R, FileID BugFileID, html::HighlightRange(R, InstantiationStart, E, HighlightStart, HighlightEnd); } + +std::string HTMLDiagnostics::generateKeyboardNavigationJavascript() { + return R"<<<( +<script type='text/javascript'> +var digitMatcher = new RegExp("[0-9]+"); + +document.addEventListener("DOMContentLoaded", function() { + document.querySelectorAll(".PathNav > a").forEach( + function(currentValue, currentIndex) { + var hrefValue = currentValue.getAttribute("href"); + currentValue.onclick = function() { + scrollTo(document.querySelector(hrefValue)); + return false; + }; + }); +}); + +var findNum = function() { + var s = document.querySelector(".selected"); + if (!s || s.id == "EndPath") { + return 0; + } + var out = parseInt(digitMatcher.exec(s.id)[0]); + return out; +}; + +var scrollTo = function(el) { + document.querySelectorAll(".selected").forEach(function(s) { + s.classList.remove("selected"); + }); + el.classList.add("selected"); + window.scrollBy(0, el.getBoundingClientRect().top - + (window.innerHeight / 2)); +} + +var move = function(num, up, numItems) { + if (num == 1 && up || num == numItems - 1 && !up) { + return 0; + } else if (num == 0 && up) { + return numItems - 1; + } else if (num == 0 && !up) { + return 1 % numItems; + } + return up ? num - 1 : num + 1; +} + +var numToId = function(num) { + if (num == 0) { + return document.getElementById("EndPath") + } + return document.getElementById("Path" + num); +}; + +var navigateTo = function(up) { + var numItems = document.querySelectorAll(".line > .msg").length; + var currentSelected = findNum(); + var newSelected = move(currentSelected, up, numItems); + var newEl = numToId(newSelected, numItems); + + // Scroll element into center. + scrollTo(newEl); +}; + +window.addEventListener("keydown", function (event) { + if (event.defaultPrevented) { + return; + } + if (event.key == "j") { + navigateTo(/*up=*/false); + } else if (event.key == "k") { + navigateTo(/*up=*/true); + } else { + return; + } + event.preventDefault(); +}, true); +</script> + )<<<"; +} |

