forked from OSchip/llvm-project
Initial experimentation with adding boxed "annotations" to HTMLized source.
llvm-svn: 48540
This commit is contained in:
parent
c6a8352820
commit
216624ce58
|
@ -54,7 +54,7 @@ ASTConsumer *CreateCodeRewriterTest(const std::string& InFile,
|
|||
const LangOptions &LOpts);
|
||||
|
||||
ASTConsumer* CreateHTMLPrinter();
|
||||
|
||||
ASTConsumer* CreateHTMLTest();
|
||||
|
||||
ASTConsumer *CreateSerializationTest(Diagnostic &Diags,
|
||||
FileManager& FMgr,
|
||||
|
|
|
@ -18,10 +18,17 @@
|
|||
#include "clang/Basic/SourceManager.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Analysis/LocalCheckers.h"
|
||||
#include "clang/AST/CFG.h"
|
||||
#include <sstream>
|
||||
|
||||
using namespace clang;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Functional HTML pretty-printing.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
class HTMLPrinter : public ASTConsumer {
|
||||
Rewriter R;
|
||||
|
@ -40,14 +47,8 @@ void HTMLPrinter::Initialize(ASTContext &context) {
|
|||
}
|
||||
|
||||
HTMLPrinter::~HTMLPrinter() {
|
||||
unsigned FileID = R.getSourceMgr().getMainFileID();
|
||||
|
||||
const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FileID);
|
||||
const char* FileStart = Buf->getBufferStart();
|
||||
const char* FileEnd = Buf->getBufferEnd();
|
||||
SourceLocation StartLoc = SourceLocation::getFileLoc(FileID, 0);
|
||||
SourceLocation EndLoc = SourceLocation::getFileLoc(FileID, FileEnd-FileStart);
|
||||
|
||||
unsigned FileID = R.getSourceMgr().getMainFileID();
|
||||
html::EscapeText(R, FileID);
|
||||
html::AddLineNumbers(R, FileID);
|
||||
html::AddHeaderFooterInternalBuiltinCSS(R, FileID);
|
||||
|
@ -59,3 +60,157 @@ HTMLPrinter::~HTMLPrinter() {
|
|||
printf("%s\n", S.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Other HTML pretty-printing code used to test new features.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
class HTMLTest : public ASTConsumer {
|
||||
Rewriter R;
|
||||
ASTContext* Ctx;
|
||||
public:
|
||||
HTMLTest() : Ctx(NULL) {}
|
||||
virtual ~HTMLTest();
|
||||
virtual void HandleTopLevelDecl(Decl* D);
|
||||
|
||||
void Initialize(ASTContext &context);
|
||||
void ProcessBody(Stmt* S);
|
||||
};
|
||||
}
|
||||
|
||||
ASTConsumer* clang::CreateHTMLTest() { return new HTMLTest(); }
|
||||
|
||||
void HTMLTest::Initialize(ASTContext &context) {
|
||||
Ctx = &context;
|
||||
R.setSourceMgr(context.getSourceManager());
|
||||
}
|
||||
|
||||
void HTMLTest::HandleTopLevelDecl(Decl* D) {
|
||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
|
||||
if (Stmt* B = FD->getBody()) {
|
||||
SourceLocation L = B->getLocStart();
|
||||
|
||||
if (L.isFileID() && L.getFileID() == R.getSourceMgr().getMainFileID())
|
||||
ProcessBody(B);
|
||||
}
|
||||
}
|
||||
|
||||
HTMLTest::~HTMLTest() {
|
||||
|
||||
unsigned FileID = R.getSourceMgr().getMainFileID();
|
||||
html::EscapeText(R, FileID);
|
||||
html::AddLineNumbers(R, FileID);
|
||||
html::AddHeaderFooterInternalBuiltinCSS(R, FileID);
|
||||
|
||||
// Emit the HTML.
|
||||
|
||||
if (const RewriteBuffer *RewriteBuf = R.getRewriteBufferFor(FileID)) {
|
||||
std::string S(RewriteBuf->begin(), RewriteBuf->end());
|
||||
printf("%s\n", S.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
class HTMLDiagnostic : public DiagnosticClient {
|
||||
Rewriter& R;
|
||||
public:
|
||||
HTMLDiagnostic(Rewriter& r) : R(r) {}
|
||||
virtual void HandleDiagnostic(Diagnostic &Diags,
|
||||
Diagnostic::Level DiagLevel,
|
||||
FullSourceLoc Pos,
|
||||
diag::kind ID,
|
||||
const std::string *Strs,
|
||||
unsigned NumStrs,
|
||||
const SourceRange *Ranges,
|
||||
unsigned NumRanges);
|
||||
};
|
||||
}
|
||||
|
||||
void HTMLTest::ProcessBody(Stmt* S) {
|
||||
CFG* cfg = CFG::buildCFG(S);
|
||||
|
||||
if (!cfg)
|
||||
return;
|
||||
|
||||
HTMLDiagnostic HD(R);
|
||||
Diagnostic D(HD);
|
||||
|
||||
CheckDeadStores(*cfg, *Ctx, D);
|
||||
}
|
||||
|
||||
void HTMLDiagnostic::HandleDiagnostic(Diagnostic &Diags,
|
||||
Diagnostic::Level DiagLevel,
|
||||
FullSourceLoc Pos,
|
||||
diag::kind ID,
|
||||
const std::string *Strs,
|
||||
unsigned NumStrs,
|
||||
const SourceRange *Ranges,
|
||||
unsigned NumRanges) {
|
||||
|
||||
// For now, just draw a box above the line in question, and emit the
|
||||
// warning.
|
||||
|
||||
if (!Pos.isValid())
|
||||
return;
|
||||
|
||||
FullSourceLoc LPos = Pos.getLogicalLoc();
|
||||
unsigned FileID = LPos.getLocation().getFileID();
|
||||
|
||||
if (FileID != LPos.getManager().getMainFileID())
|
||||
return;
|
||||
|
||||
|
||||
// Compute the column number. Rewind from the current position to the start
|
||||
// of the line.
|
||||
|
||||
unsigned ColNo = LPos.getColumnNumber();
|
||||
const char *TokLogicalPtr = LPos.getCharacterData();
|
||||
const char *LineStart = TokLogicalPtr-ColNo;
|
||||
|
||||
// Ripped from TextDiagnostics::FormatDiagnostic:
|
||||
|
||||
std::string Msg = Diags.getDescription(ID);
|
||||
|
||||
for (unsigned i = 0; i < Msg.size() - 1; ++i) {
|
||||
if (Msg[i] == '%' && isdigit(Msg[i + 1])) {
|
||||
unsigned StrNo = Msg[i + 1] - '0';
|
||||
Msg = std::string(Msg.begin(), Msg.begin() + i) +
|
||||
(StrNo < NumStrs ? Strs[StrNo] : "<<<INTERNAL ERROR>>>") +
|
||||
std::string(Msg.begin() + i + 2, Msg.end());
|
||||
}
|
||||
}
|
||||
|
||||
// Start making the div tag.
|
||||
|
||||
std::ostringstream os;
|
||||
|
||||
os << "\n<div class=\"codeline\"><div class=\"nums\"> </div>"
|
||||
<< "<div class=\"lines\">";
|
||||
|
||||
for (unsigned i = 0; i < ColNo+1; ++i)
|
||||
os << ' ';
|
||||
|
||||
os << "</div><span class=\"msg\">";
|
||||
|
||||
switch (DiagLevel) {
|
||||
default: assert(0 && "Unknown diagnostic type!");
|
||||
case Diagnostic::Note: os << "note: "; break;
|
||||
case Diagnostic::Warning: os << "warning: "; break;
|
||||
case Diagnostic::Error: os << "error: "; break;
|
||||
case Diagnostic::Fatal: os << "fatal error: "; break;
|
||||
break;
|
||||
}
|
||||
|
||||
os << Msg; // FIXME: HTML escape "Msg"
|
||||
os << "</span></div";
|
||||
|
||||
// Insert a div tag with the warning.
|
||||
|
||||
const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FileID);
|
||||
const char* FileStart = Buf->getBufferStart();
|
||||
|
||||
|
||||
R.InsertStrBefore(SourceLocation::getFileLoc(FileID, LineStart - FileStart),
|
||||
os.str());
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ Stats("print-stats",
|
|||
|
||||
enum ProgActions {
|
||||
RewriteTest, // Rewriter testing stuff.
|
||||
HTMLTest, // HTML displayer testing stuff.
|
||||
EmitLLVM, // Emit a .ll file.
|
||||
EmitBC, // Emit a .bc file.
|
||||
SerializeAST, // Emit a .ast file.
|
||||
|
@ -135,6 +136,8 @@ ProgAction(llvm::cl::desc("Choose output type:"), llvm::cl::ZeroOrMore,
|
|||
"Build ASTs and emit .ast file"),
|
||||
clEnumValN(RewriteTest, "rewrite-test",
|
||||
"Playground for the code rewriter"),
|
||||
clEnumValN(HTMLTest, "html-test",
|
||||
"Playground for the HTML displayer"),
|
||||
clEnumValEnd));
|
||||
|
||||
|
||||
|
@ -1002,6 +1005,9 @@ static ASTConsumer* CreateASTConsumer(const std::string& InFile,
|
|||
case EmitHTML:
|
||||
return CreateHTMLPrinter();
|
||||
|
||||
case HTMLTest:
|
||||
return CreateHTMLTest();
|
||||
|
||||
case ParseCFGDump:
|
||||
case ParseCFGView:
|
||||
return CreateCFGDumper(ProgAction == ParseCFGView,
|
||||
|
|
|
@ -50,6 +50,8 @@ static void AddLineNumber(Rewriter& R, unsigned LineNo,
|
|||
SourceLocation B, SourceLocation E) {
|
||||
|
||||
// Surround the line text with a div tag.
|
||||
|
||||
R.InsertCStrBefore(E, "</div>");
|
||||
|
||||
if (B == E) // Handle empty lines.
|
||||
R.InsertCStrBefore(B, "<div class=\"lines\"> </div>");
|
||||
|
@ -68,7 +70,7 @@ static void AddLineNumber(Rewriter& R, unsigned LineNo,
|
|||
// Now surround the whole line with another div tag.
|
||||
|
||||
R.InsertCStrBefore(B, "<div class=\"codeline\">");
|
||||
R.InsertCStrAfter(E, "</div>");
|
||||
|
||||
}
|
||||
|
||||
void html::AddLineNumbers(Rewriter& R, unsigned FileID) {
|
||||
|
@ -141,9 +143,12 @@ void html::AddHeaderFooterInternalBuiltinCSS(Rewriter& R, unsigned FileID) {
|
|||
<< " .nums, .lines { float:left; height:100% }\n"
|
||||
<< " .nums { background-color: #eeeeee }\n"
|
||||
<< " .nums { font-size:smaller }\n"
|
||||
<< " .nums { width:2.5em; padding-right:2ex; text-align:right }\n"
|
||||
<< " .nums { width:2.5em; padding-right:2ex; text-align:right }\n"
|
||||
<< " .lines { padding-left: 1ex; border-left: 3px solid #ccc }\n"
|
||||
<< " .lines { white-space: pre }\n"
|
||||
<< " .msg { background-color:#fcff4c; float:left }\n"
|
||||
<< " .msg { font-family:Helvetica, sans-serif; font-size: smaller }\n"
|
||||
<< " .msg { padding:5px; margin-top:10px; margin-bottom:10px }\n"
|
||||
<< " </style>\n"
|
||||
<< "</head>\n"
|
||||
<< "<body>";
|
||||
|
|
Loading…
Reference in New Issue