From a5a75e7a106aa58c65ae9b5e42128e1278542f67 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 16 Apr 2008 06:32:08 +0000 Subject: [PATCH] split syntax highlighting of macros from keywords and comments, allowing us to use a cheaper means to highlight keywords and making it so that comments won't foul up macro expansions. Start highlighting macro expansions. llvm-svn: 49779 --- clang/Driver/HTMLPrint.cpp | 4 +- clang/include/clang/Rewrite/HTMLRewrite.h | 11 +++- clang/lib/Rewrite/HTMLRewrite.cpp | 72 ++++++++++++++++++++++- 3 files changed, 80 insertions(+), 7 deletions(-) diff --git a/clang/Driver/HTMLPrint.cpp b/clang/Driver/HTMLPrint.cpp index cb32afd8175f..2b014899631d 100644 --- a/clang/Driver/HTMLPrint.cpp +++ b/clang/Driver/HTMLPrint.cpp @@ -61,8 +61,10 @@ HTMLPrinter::~HTMLPrinter() { // 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) + if (PP) { html::SyntaxHighlight(R, FileID, *PP); + html::HighlightMacros(R, FileID, *PP); + } // Open the output. diff --git a/clang/include/clang/Rewrite/HTMLRewrite.h b/clang/include/clang/Rewrite/HTMLRewrite.h index 520030fcdf01..be16eaaab17a 100644 --- a/clang/include/clang/Rewrite/HTMLRewrite.h +++ b/clang/include/clang/Rewrite/HTMLRewrite.h @@ -45,11 +45,16 @@ namespace html { 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. + /// information about keywords, comments, etc. void SyntaxHighlight(Rewriter &R, unsigned FileID, Preprocessor &PP); + /// HighlightMacros - This uses the macro table state from the end of the + /// file, to reexpand macros and insert (into the HTML) information about the + /// macro expansions. This won't be perfectly perfect, but it will be + /// reasonably close. + void HighlightMacros(Rewriter &R, unsigned FileID, Preprocessor &PP); + + } // end html namespace } // end clang namespace diff --git a/clang/lib/Rewrite/HTMLRewrite.cpp b/clang/lib/Rewrite/HTMLRewrite.cpp index e35664f54611..ad7e23716aef 100644 --- a/clang/lib/Rewrite/HTMLRewrite.cpp +++ b/clang/lib/Rewrite/HTMLRewrite.cpp @@ -185,7 +185,8 @@ 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" + " .comment { color: #A0A0A0 }\n" + " .macro { color: #FF0000; background-color:#FFC0C0 }\n" " .num { width:2.5em; padding-right:2ex; background-color:#eeeeee }\n" " .num { text-align:right; font-size: smaller }\n" " .num { color:#444444 }\n" @@ -232,11 +233,12 @@ void html::SyntaxHighlight(Rewriter &R, unsigned FileID, Preprocessor &PP) { // Start parsing the specified input file. PP.EnterMainSourceFile(); - // Lex all the tokens. + // Lex all the tokens in raw mode, to avoid entering #includes or expanding + // macros. const SourceManager &SourceMgr = PP.getSourceManager(); Token Tok; do { - PP.Lex(Tok); + PP.LexUnexpandedToken(Tok); // Ignore tokens whose logical location was not the main file. SourceLocation LLoc = SourceMgr.getLogicalLoc(Tok.getLocation()); std::pair LLocInfo = @@ -249,6 +251,8 @@ void html::SyntaxHighlight(Rewriter &R, unsigned FileID, Preprocessor &PP) { unsigned TokLen = Tok.getLength(); switch (Tok.getKind()) { default: break; + // FIXME: Add keywords here. + case tok::comment: RB.InsertTextAfter(TokOffs, "", strlen("")); @@ -257,4 +261,66 @@ void html::SyntaxHighlight(Rewriter &R, unsigned FileID, Preprocessor &PP) { } } while (Tok.isNot(tok::eof)); + PP.SetCommentRetentionState(false, false); } + +/// HighlightMacros - This uses the macro table state from the end of the +/// file, to reexpand macros and insert (into the HTML) information about the +/// macro expansions. This won't be perfectly perfect, but it will be +/// reasonably close. +void html::HighlightMacros(Rewriter &R, unsigned FileID, Preprocessor &PP) { + RewriteBuffer &RB = R.getEditBuffer(FileID); + + // Inform the preprocessor that we don't want comments. + PP.SetCommentRetentionState(false, false); + + // Start parsing the specified input file. + PP.EnterMainSourceFile(); + + // Lex all the tokens. + const SourceManager &SourceMgr = PP.getSourceManager(); + Token Tok; + PP.Lex(Tok); + while (Tok.isNot(tok::eof)) { + // Ignore non-macro tokens. + if (!Tok.getLocation().isMacroID()) { + PP.Lex(Tok); + continue; + } + + // Ignore tokens whose logical location was not the main file. + SourceLocation LLoc = SourceMgr.getLogicalLoc(Tok.getLocation()); + std::pair LLocInfo = + SourceMgr.getDecomposedFileLoc(LLoc); + + if (LLocInfo.first != FileID) { + PP.Lex(Tok); + continue; + } + + // Okay, we have the first token of a macro expansion: highlight the + // instantiation. + + // Get the size of current macro call itself. + // FIXME: This should highlight the args of a function-like + // macro, using a heuristic. + unsigned TokLen = Lexer::MeasureTokenLength(LLoc, SourceMgr); + + unsigned TokOffs = LLocInfo.second; + RB.InsertTextAfter(TokOffs, "", + strlen("")); + RB.InsertTextBefore(TokOffs+TokLen, "", strlen("")); + + // Okay, eat this token, getting the next one. + PP.Lex(Tok); + + // Skip all the rest of the tokens that are part of this macro + // instantiation. It would be really nice to pop up a window with all the + // spelling of the tokens or something. + while (!Tok.is(tok::eof) && + SourceMgr.getLogicalLoc(Tok.getLocation()) == LLoc) + PP.Lex(Tok); + } +} + +