diff options
author | Chris Lattner <sabre@nondot.org> | 2008-04-16 06:11:58 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-04-16 06:11:58 +0000 |
commit | 3245a0a1c7a4fd74fca845b2edba275bb126d773 (patch) | |
tree | ab2aab4b4acc1ce3427c823ee94da56635472898 | |
parent | 8ac661c3c5ffaeedfb3268994ad864ade77b3ba0 (diff) |
Add a mode of hackily syntax highlighting comments. This has a number of
problems, including the fact that it doesn't work well with multi-line
comments due to Ted's crazy table. However, that could be fixed, and it
does work with single-line ones :).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49778 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | Driver/ASTConsumers.h | 4 | ||||
-rw-r--r-- | Driver/HTMLPrint.cpp | 15 | ||||
-rw-r--r-- | Driver/clang.cpp | 11 | ||||
-rw-r--r-- | include/clang/Rewrite/HTMLRewrite.h | 8 | ||||
-rw-r--r-- | lib/Rewrite/HTMLRewrite.cpp | 45 |
5 files changed, 69 insertions, 14 deletions
diff --git a/Driver/ASTConsumers.h b/Driver/ASTConsumers.h index 91ee8fbf93..6054fdf443 100644 --- a/Driver/ASTConsumers.h +++ b/Driver/ASTConsumers.h @@ -27,6 +27,7 @@ class ASTConsumer; class Diagnostic; class FileManager; struct LangOptions; +class Preprocessor; ASTConsumer *CreateASTPrinter(std::ostream* OS = NULL); @@ -57,7 +58,8 @@ ASTConsumer *CreateCodeRewriterTest(const std::string& InFile, Diagnostic &Diags, const LangOptions &LOpts); - ASTConsumer* CreateHTMLPrinter(const std::string &OutFile, Diagnostic &D); +ASTConsumer* CreateHTMLPrinter(const std::string &OutFile, Diagnostic &D, + Preprocessor *PP); ASTConsumer *CreateSerializationTest(Diagnostic &Diags, FileManager& FMgr, diff --git a/Driver/HTMLPrint.cpp b/Driver/HTMLPrint.cpp index 44cd6244ec..cb32afd817 100644 --- a/Driver/HTMLPrint.cpp +++ b/Driver/HTMLPrint.cpp @@ -30,9 +30,10 @@ namespace { Rewriter R; std::string OutFilename; Diagnostic &Diags; + Preprocessor *PP; public: - HTMLPrinter(const std::string &OutFile, Diagnostic &D) - : OutFilename(OutFile), Diags(D) {} + HTMLPrinter(const std::string &OutFile, Diagnostic &D, Preprocessor *pp) + : OutFilename(OutFile), Diags(D), PP(pp) {} virtual ~HTMLPrinter(); void Initialize(ASTContext &context); @@ -40,8 +41,8 @@ namespace { } ASTConsumer* clang::CreateHTMLPrinter(const std::string &OutFile, - Diagnostic &D) { - return new HTMLPrinter(OutFile, D); + Diagnostic &D, Preprocessor *PP) { + return new HTMLPrinter(OutFile, D, PP); } void HTMLPrinter::Initialize(ASTContext &context) { @@ -58,6 +59,12 @@ HTMLPrinter::~HTMLPrinter() { html::AddLineNumbers(R, FileID); html::AddHeaderFooterInternalBuiltinCSS(R, FileID); + // If we have a preprocessor, relex the file and syntax hilight. We might not + // have a preprocessor if we come from a deserialized AST file, for example. + if (PP) + html::SyntaxHighlight(R, FileID, *PP); + + // Open the output. FILE *OutputFILE; if (OutFilename.empty() || OutFilename == "-") diff --git a/Driver/clang.cpp b/Driver/clang.cpp index 09140c942e..a9ae98e555 100644 --- a/Driver/clang.cpp +++ b/Driver/clang.cpp @@ -1033,6 +1033,7 @@ static void ParseFile(Preprocessor &PP, MinimalAction *PA){ static ASTConsumer* CreateASTConsumer(const std::string& InFile, Diagnostic& Diag, FileManager& FileMgr, const LangOptions& LangOpts, + Preprocessor *PP, llvm::Module *&DestModule) { switch (ProgAction) { default: @@ -1048,7 +1049,7 @@ static ASTConsumer* CreateASTConsumer(const std::string& InFile, return CreateASTViewer(); case EmitHTML: - return CreateHTMLPrinter(OutputFile, Diag); + return CreateHTMLPrinter(OutputFile, Diag, PP); case ParseCFGDump: case ParseCFGView: @@ -1099,10 +1100,8 @@ static void ProcessInputFile(Preprocessor &PP, const std::string &InFile) { switch (ProgAction) { default: - Consumer = CreateASTConsumer(InFile, - PP.getDiagnostics(), - PP.getFileManager(), - PP.getLangOptions(), + Consumer = CreateASTConsumer(InFile, PP.getDiagnostics(), + PP.getFileManager(), PP.getLangOptions(), &PP, CodeGenModule); if (!Consumer) { @@ -1242,7 +1241,7 @@ static void ProcessSerializedFile(const std::string& InFile, Diagnostic& Diag, // translation unit, rather than InFile. llvm::Module *DestModule; llvm::OwningPtr<ASTConsumer> - Consumer(CreateASTConsumer(InFile, Diag, FileMgr, TU->getLangOpts(), + Consumer(CreateASTConsumer(InFile, Diag, FileMgr, TU->getLangOpts(), 0, DestModule)); if (!Consumer) { diff --git a/include/clang/Rewrite/HTMLRewrite.h b/include/clang/Rewrite/HTMLRewrite.h index d5bdc89070..520030fcdf 100644 --- a/include/clang/Rewrite/HTMLRewrite.h +++ b/include/clang/Rewrite/HTMLRewrite.h @@ -21,6 +21,7 @@ namespace clang { class Rewriter; +class Preprocessor; namespace html { @@ -42,7 +43,12 @@ namespace html { void AddLineNumbers(Rewriter& R, unsigned FileID); void AddHeaderFooterInternalBuiltinCSS(Rewriter& R, unsigned FileID); - + + /// SyntaxHighlight - Relex the specified FileID and annotate the HTML with + /// information about keywords, macro expansions etc. This uses the macro + /// table state from the end of the file, so it won't be perfectly perfect, + /// but it will be reasonably close. + void SyntaxHighlight(Rewriter &R, unsigned FileID, Preprocessor &PP); } // end html namespace } // end clang namespace diff --git a/lib/Rewrite/HTMLRewrite.cpp b/lib/Rewrite/HTMLRewrite.cpp index 9ed5953c60..e35664f546 100644 --- a/lib/Rewrite/HTMLRewrite.cpp +++ b/lib/Rewrite/HTMLRewrite.cpp @@ -14,11 +14,11 @@ #include "clang/Rewrite/Rewriter.h" #include "clang/Rewrite/HTMLRewrite.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/MemoryBuffer.h" #include <sstream> - using namespace clang; void html::EscapeText(Rewriter& R, unsigned FileID, @@ -176,7 +176,6 @@ void html::AddHeaderFooterInternalBuiltinCSS(Rewriter& R, unsigned FileID) { SourceLocation EndLoc = SourceLocation::getFileLoc(FileID, FileEnd-FileStart); // Generate header - R.InsertCStrBefore(StartLoc, "<html>\n<head>\n" "<style type=\"text/css\">\n" @@ -186,6 +185,7 @@ void html::AddHeaderFooterInternalBuiltinCSS(Rewriter& R, unsigned FileID) { " .code { border-spacing:0px; width:100%; }\n" " .code { font-family: \"Andale Mono\", monospace; font-size:10pt }\n" " .code { line-height: 1.2em }\n" + " .comment { color:#A0A0A0 }\n" " .num { width:2.5em; padding-right:2ex; background-color:#eeeeee }\n" " .num { text-align:right; font-size: smaller }\n" " .num { color:#444444 }\n" @@ -217,3 +217,44 @@ void html::AddHeaderFooterInternalBuiltinCSS(Rewriter& R, unsigned FileID) { R.InsertCStrAfter(EndLoc, "</body></html>\n"); } + +/// SyntaxHighlight - Relex the specified FileID and annotate the HTML with +/// information about keywords, macro expansions etc. This uses the macro +/// table state from the end of the file, so it won't be perfectly perfect, +/// but it will be reasonably close. +void html::SyntaxHighlight(Rewriter &R, unsigned FileID, Preprocessor &PP) { + RewriteBuffer &RB = R.getEditBuffer(FileID); + + // Inform the preprocessor that we want to retain comments as tokens, so we + // can highlight them. + PP.SetCommentRetentionState(true, false); + + // Start parsing the specified input file. + PP.EnterMainSourceFile(); + + // Lex all the tokens. + const SourceManager &SourceMgr = PP.getSourceManager(); + Token Tok; + do { + PP.Lex(Tok); + // Ignore tokens whose logical location was not the main file. + SourceLocation LLoc = SourceMgr.getLogicalLoc(Tok.getLocation()); + std::pair<unsigned, unsigned> LLocInfo = + SourceMgr.getDecomposedFileLoc(LLoc); + + if (LLocInfo.first != FileID) + continue; + + unsigned TokOffs = LLocInfo.second; + unsigned TokLen = Tok.getLength(); + switch (Tok.getKind()) { + default: break; + case tok::comment: + RB.InsertTextAfter(TokOffs, "<span class='comment'>", + strlen("<span class='comment'>")); + RB.InsertTextBefore(TokOffs+TokLen, "</span>", strlen("</span>")); + break; + } + + } while (Tok.isNot(tok::eof)); +} |