diff options
author | Ted Kremenek <kremenek@apple.com> | 2008-03-18 23:08:51 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2008-03-18 23:08:51 +0000 |
commit | b485cd1e0a5a1e942d0e682b9b1c4bc9df111528 (patch) | |
tree | b32c93235dec858e9e29be5f3c40027f6532e027 /lib/Rewrite/HTMLRewrite.cpp | |
parent | 5e0020ee6182f63cd5f4a53e240dc08bd02d7728 (diff) |
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
Diffstat (limited to 'lib/Rewrite/HTMLRewrite.cpp')
-rw-r--r-- | lib/Rewrite/HTMLRewrite.cpp | 128 |
1 files changed, 105 insertions, 23 deletions
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 << "</" << TagStr << ">"; +} + 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 << "</" << TagStr << '>'; - 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; + } + } +} |