From b485cd1e0a5a1e942d0e682b9b1c4bc9df111528 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Tue, 18 Mar 2008 23:08:51 +0000 Subject: [PATCH] Some cleanups to the HTMLRewrite API. Added support for printing out line numbers (more work to be done on aesthetics). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@48512 91177308-0d34-0410-b5e6-96231b3b80d8 --- Driver/HTMLPrint.cpp | 7 +- include/clang/Rewrite/HTMLRewrite.h | 18 +++- lib/Rewrite/HTMLRewrite.cpp | 128 +++++++++++++++++++++++----- 3 files changed, 124 insertions(+), 29 deletions(-) diff --git a/Driver/HTMLPrint.cpp b/Driver/HTMLPrint.cpp index d347901e8b..940016afd2 100644 --- a/Driver/HTMLPrint.cpp +++ b/Driver/HTMLPrint.cpp @@ -49,9 +49,10 @@ HTMLPrinter::~HTMLPrinter() { html::EscapeText(R, FileID); html::AddLineNumbers(R, FileID); -// html::InsertTag(R, html::HEAD, StartLoc, EndLoc, true); -// html::InsertTag(R, html::BODY, StartLoc, EndLoc, true); -// html::InsertTag(R, html::PRE, StartLoc, EndLoc); + html::InsertTag(R, html::PRE, StartLoc, EndLoc, 0, 0, true); + html::InsertTag(R, html::BODY, StartLoc, EndLoc, NULL, "\n", true); + html::InsertTag(R, html::HEAD, StartLoc, StartLoc, 0, 0, true); + html::InsertTag(R, html::HTML, StartLoc, EndLoc, NULL, "\n", true); // Emit the HTML. diff --git a/include/clang/Rewrite/HTMLRewrite.h b/include/clang/Rewrite/HTMLRewrite.h index 43923ae332..3f821cc1fd 100644 --- a/include/clang/Rewrite/HTMLRewrite.h +++ b/include/clang/Rewrite/HTMLRewrite.h @@ -23,14 +23,26 @@ class Rewriter; namespace html { - enum Tags { PRE, HEAD, BODY }; + // Basic operations. + + enum Tags { BODY, + DIV, + HEAD, + HTML, + PRE, + SPAN }; void EscapeText(Rewriter& R, unsigned FileID, bool EscapeSpaces = false); void InsertTag(Rewriter& R, Tags tag, SourceLocation OpenLoc, SourceLocation CloseLoc, - bool NewlineOpen = false, bool NewlineClose = true, - bool OutermostTag = false); + const char* Attributes = NULL, const char* Content = NULL, + bool Newline = false, + bool OpenInsertBefore = true, bool CloseInsertAfter = true); + + // High-level operations. + + void AddLineNumbers(Rewriter& R, unsigned FileID); } // end html namespace } // end clang namespace diff --git a/lib/Rewrite/HTMLRewrite.cpp b/lib/Rewrite/HTMLRewrite.cpp index 717f6cec81..f8c96cca39 100644 --- a/lib/Rewrite/HTMLRewrite.cpp +++ b/lib/Rewrite/HTMLRewrite.cpp @@ -20,6 +20,10 @@ using namespace clang; +//===----------------------------------------------------------------------===// +// Basic operations. +//===----------------------------------------------------------------------===// + void html::EscapeText(Rewriter& R, unsigned FileID, bool EscapeSpaces) { const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FileID); @@ -46,46 +50,124 @@ void html::EscapeText(Rewriter& R, unsigned FileID, bool EscapeSpaces) { } } + +static void TagOpen(std::ostringstream& os, const char* TagStr, + const char* Attr, const char* Content) { + + os << '<' << TagStr; + if (Attr) os << ' ' << Attr; + os << '>'; + if (Content) os << Content; +} + +static void TagClose(std::ostringstream& os, const char* TagStr) { + os << ""; +} + void html::InsertTag(Rewriter& R, html::Tags tag, SourceLocation B, SourceLocation E, - bool NewlineOpen, bool NewlineClose, bool OutermostTag) { + const char* Attributes, + const char* Content, bool Newline, + bool OpenInsertBefore, bool CloseInsertAfter) { const char* TagStr = 0; switch (tag) { default: break; - case PRE: TagStr = "pre"; break; - case HEAD: TagStr = "head"; break; case BODY: TagStr = "body"; break; + case DIV: TagStr = "div"; break; + case HEAD: TagStr = "head"; break; + case HTML: TagStr = "html"; break; + case PRE: TagStr = "pre"; break; + case SPAN: TagStr = "span"; break; } assert (TagStr && "Tag not supported."); - { // Generate the opening tag. - std::ostringstream os; - os << '<' << TagStr << '>'; - if (NewlineOpen) os << '\n'; - - const char* s = os.str().c_str(); - unsigned n = os.str().size(); + // Generate the opening tag. We also generate the closing + // tag of the start and end SourceLocations are the same. + + { + std::ostringstream os; + TagOpen(os, TagStr, Attributes, Content); + if (B == E) { + TagClose(os, TagStr); + if (Newline) os << '\n'; + } - if (OutermostTag) - R.InsertTextBefore(B, s, n); + if (OpenInsertBefore) + R.InsertTextBefore(B, os.str().c_str(), os.str().size()); else - R.InsertTextAfter(B, s, n); + R.InsertTextAfter(B, os.str().c_str(), os.str().size()); } - { // Generate the closing tag. - std::ostringstream os; - os << "'; - if (NewlineClose) os << '\n'; - - const char* s = os.str().c_str(); - unsigned n = os.str().size(); + // Generate the closing tag if the start and end SourceLocations + // are different. + + if (B != E) { + std::ostringstream os; + TagClose(os, TagStr); + if (Newline) os << '\n'; - if (OutermostTag) - R.InsertTextAfter(E, s, n); + if (CloseInsertAfter) + R.InsertTextAfter(E, os.str().c_str(), os.str().size()); else - R.InsertTextBefore(E, s, n); + R.InsertTextBefore(E, os.str().c_str(), os.str().size()); } } + +//===----------------------------------------------------------------------===// +// High-level operations. +//===----------------------------------------------------------------------===// + +static void AddLineNumber(Rewriter& R, unsigned LineNo, + SourceLocation B, SourceLocation E) { + + // Add two "div" tags: one to contain the line number, and the other + // to contain the content of the line. + + std::ostringstream os; + os << LineNo; + html::InsertTag(R, html::SPAN, B, E, "class=Line"); + html::InsertTag(R, html::SPAN, B, B, "class=Num", os.str().c_str()); +} + +void html::AddLineNumbers(Rewriter& R, unsigned FileID) { + + const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FileID); + const char* FileBeg = Buf->getBufferStart(); + const char* FileEnd = Buf->getBufferEnd(); + const char* C = FileBeg; + + assert (C <= FileEnd); + + unsigned LineNo = 0; + unsigned FilePos = 0; + + while (C != FileEnd) { + + ++LineNo; + unsigned LineStartPos = FilePos; + unsigned LineEndPos = FileEnd - FileBeg; + + assert (FilePos <= LineEndPos); + assert (C < FileEnd); + + // Scan until the newline (or end-of-file). + + for ( ; C != FileEnd ; ++C, ++FilePos) + if (*C == '\n') { + LineEndPos = FilePos; + break; + } + + AddLineNumber(R, LineNo, + SourceLocation::getFileLoc(FileID, LineStartPos), + SourceLocation::getFileLoc(FileID, LineEndPos)); + + if (C != FileEnd) { + ++C; + ++FilePos; + } + } +} -- 2.40.0