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
diff --git a/Driver/ASTConsumers.h b/Driver/ASTConsumers.h
index 91ee8fb..6054fdf 100644
--- a/Driver/ASTConsumers.h
+++ b/Driver/ASTConsumers.h
@@ -27,6 +27,7 @@
 class Diagnostic;
 class FileManager;
 struct LangOptions;
+class Preprocessor;
 
 ASTConsumer *CreateASTPrinter(std::ostream* OS = NULL);
 
@@ -57,7 +58,8 @@
                                     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 44cd624..cb32afd 100644
--- a/Driver/HTMLPrint.cpp
+++ b/Driver/HTMLPrint.cpp
@@ -30,9 +30,10 @@
     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 @@
 }
 
 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 @@
   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 09140c9..a9ae98e 100644
--- a/Driver/clang.cpp
+++ b/Driver/clang.cpp
@@ -1033,6 +1033,7 @@
 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 @@
       return CreateASTViewer();   
       
     case EmitHTML:
-      return CreateHTMLPrinter(OutputFile, Diag);
+      return CreateHTMLPrinter(OutputFile, Diag, PP);
       
     case ParseCFGDump:
     case ParseCFGView:
@@ -1099,10 +1100,8 @@
   
   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 @@
   // 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 d5bdc89..520030f 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 @@
   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 9ed5953..e35664f 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 @@
   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 @@
       " .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 @@
   
   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));
+}