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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@49779 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Driver/HTMLPrint.cpp b/Driver/HTMLPrint.cpp
index cb32afd..2b01489 100644
--- a/Driver/HTMLPrint.cpp
+++ b/Driver/HTMLPrint.cpp
@@ -61,8 +61,10 @@
// 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/include/clang/Rewrite/HTMLRewrite.h b/include/clang/Rewrite/HTMLRewrite.h
index 520030f..be16eaa 100644
--- a/include/clang/Rewrite/HTMLRewrite.h
+++ b/include/clang/Rewrite/HTMLRewrite.h
@@ -45,11 +45,16 @@
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/lib/Rewrite/HTMLRewrite.cpp b/lib/Rewrite/HTMLRewrite.cpp
index e35664f..ad7e237 100644
--- a/lib/Rewrite/HTMLRewrite.cpp
+++ b/lib/Rewrite/HTMLRewrite.cpp
@@ -185,7 +185,8 @@
" .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 @@
// 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<unsigned, unsigned> LLocInfo =
@@ -249,6 +251,8 @@
unsigned TokLen = Tok.getLength();
switch (Tok.getKind()) {
default: break;
+ // FIXME: Add keywords here.
+
case tok::comment:
RB.InsertTextAfter(TokOffs, "<span class='comment'>",
strlen("<span class='comment'>"));
@@ -257,4 +261,66 @@
}
} 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<unsigned, unsigned> 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, "<span class='macro'>",
+ strlen("<span class='macro'>"));
+ RB.InsertTextBefore(TokOffs+TokLen, "</span>", strlen("</span>"));
+
+ // 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);
+ }
+}
+
+