10621cb2eSAlp Toker //===--- HTMLPrint.cpp - Source code -> HTML pretty-printing --------------===//
20621cb2eSAlp Toker //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60621cb2eSAlp Toker //
70621cb2eSAlp Toker //===----------------------------------------------------------------------===//
80621cb2eSAlp Toker //
90621cb2eSAlp Toker // Pretty-printing of source code to HTML.
100621cb2eSAlp Toker //
110621cb2eSAlp Toker //===----------------------------------------------------------------------===//
120621cb2eSAlp Toker 
130621cb2eSAlp Toker #include "clang/AST/ASTConsumer.h"
140621cb2eSAlp Toker #include "clang/AST/ASTContext.h"
150621cb2eSAlp Toker #include "clang/AST/Decl.h"
160621cb2eSAlp Toker #include "clang/Basic/Diagnostic.h"
170621cb2eSAlp Toker #include "clang/Basic/FileManager.h"
180621cb2eSAlp Toker #include "clang/Basic/SourceManager.h"
190621cb2eSAlp Toker #include "clang/Lex/Preprocessor.h"
200621cb2eSAlp Toker #include "clang/Rewrite/Core/HTMLRewrite.h"
210621cb2eSAlp Toker #include "clang/Rewrite/Core/Rewriter.h"
229670f847SMehdi Amini #include "clang/Rewrite/Frontend/ASTConsumers.h"
230621cb2eSAlp Toker #include "llvm/Support/raw_ostream.h"
240621cb2eSAlp Toker using namespace clang;
250621cb2eSAlp Toker 
260621cb2eSAlp Toker //===----------------------------------------------------------------------===//
270621cb2eSAlp Toker // Functional HTML pretty-printing.
280621cb2eSAlp Toker //===----------------------------------------------------------------------===//
290621cb2eSAlp Toker 
300621cb2eSAlp Toker namespace {
310621cb2eSAlp Toker   class HTMLPrinter : public ASTConsumer {
320621cb2eSAlp Toker     Rewriter R;
3303f8907fSPeter Collingbourne     std::unique_ptr<raw_ostream> Out;
340621cb2eSAlp Toker     Preprocessor &PP;
350621cb2eSAlp Toker     bool SyntaxHighlight, HighlightMacros;
360621cb2eSAlp Toker 
370621cb2eSAlp Toker   public:
HTMLPrinter(std::unique_ptr<raw_ostream> OS,Preprocessor & pp,bool _SyntaxHighlight,bool _HighlightMacros)3803f8907fSPeter Collingbourne     HTMLPrinter(std::unique_ptr<raw_ostream> OS, Preprocessor &pp,
390621cb2eSAlp Toker                 bool _SyntaxHighlight, bool _HighlightMacros)
4003f8907fSPeter Collingbourne       : Out(std::move(OS)), PP(pp), SyntaxHighlight(_SyntaxHighlight),
410621cb2eSAlp Toker         HighlightMacros(_HighlightMacros) {}
420621cb2eSAlp Toker 
430621cb2eSAlp Toker     void Initialize(ASTContext &context) override;
440621cb2eSAlp Toker     void HandleTranslationUnit(ASTContext &Ctx) override;
450621cb2eSAlp Toker   };
46ab9db510SAlexander Kornienko }
470621cb2eSAlp Toker 
4803f8907fSPeter Collingbourne std::unique_ptr<ASTConsumer>
CreateHTMLPrinter(std::unique_ptr<raw_ostream> OS,Preprocessor & PP,bool SyntaxHighlight,bool HighlightMacros)4903f8907fSPeter Collingbourne clang::CreateHTMLPrinter(std::unique_ptr<raw_ostream> OS, Preprocessor &PP,
5003f8907fSPeter Collingbourne                          bool SyntaxHighlight, bool HighlightMacros) {
512b3d49b6SJonas Devlieghere   return std::make_unique<HTMLPrinter>(std::move(OS), PP, SyntaxHighlight,
526beb6aa8SDavid Blaikie                                         HighlightMacros);
530621cb2eSAlp Toker }
540621cb2eSAlp Toker 
Initialize(ASTContext & context)550621cb2eSAlp Toker void HTMLPrinter::Initialize(ASTContext &context) {
560621cb2eSAlp Toker   R.setSourceMgr(context.getSourceManager(), context.getLangOpts());
570621cb2eSAlp Toker }
580621cb2eSAlp Toker 
HandleTranslationUnit(ASTContext & Ctx)590621cb2eSAlp Toker void HTMLPrinter::HandleTranslationUnit(ASTContext &Ctx) {
600621cb2eSAlp Toker   if (PP.getDiagnostics().hasErrorOccurred())
610621cb2eSAlp Toker     return;
620621cb2eSAlp Toker 
630621cb2eSAlp Toker   // Format the file.
640621cb2eSAlp Toker   FileID FID = R.getSourceMgr().getMainFileID();
650621cb2eSAlp Toker   const FileEntry* Entry = R.getSourceMgr().getFileEntryForID(FID);
6699d1b295SMehdi Amini   StringRef Name;
670621cb2eSAlp Toker   // In some cases, in particular the case where the input is from stdin,
680621cb2eSAlp Toker   // there is no entry.  Fall back to the memory buffer for a name in those
690621cb2eSAlp Toker   // cases.
700621cb2eSAlp Toker   if (Entry)
710621cb2eSAlp Toker     Name = Entry->getName();
720621cb2eSAlp Toker   else
73*63af2422SDuncan P. N. Exon Smith     Name = R.getSourceMgr().getBufferOrFake(FID).getBufferIdentifier();
740621cb2eSAlp Toker 
750621cb2eSAlp Toker   html::AddLineNumbers(R, FID);
760621cb2eSAlp Toker   html::AddHeaderFooterInternalBuiltinCSS(R, FID, Name);
770621cb2eSAlp Toker 
780621cb2eSAlp Toker   // If we have a preprocessor, relex the file and syntax highlight.
790621cb2eSAlp Toker   // We might not have a preprocessor if we come from a deserialized AST file,
800621cb2eSAlp Toker   // for example.
810621cb2eSAlp Toker 
820621cb2eSAlp Toker   if (SyntaxHighlight) html::SyntaxHighlight(R, FID, PP);
830621cb2eSAlp Toker   if (HighlightMacros) html::HighlightMacros(R, FID, PP);
840621cb2eSAlp Toker   html::EscapeText(R, FID, false, true);
850621cb2eSAlp Toker 
860621cb2eSAlp Toker   // Emit the HTML.
870621cb2eSAlp Toker   const RewriteBuffer &RewriteBuf = R.getEditBuffer(FID);
8852525730SSerge Pavlov   std::unique_ptr<char[]> Buffer(new char[RewriteBuf.size()]);
8952525730SSerge Pavlov   std::copy(RewriteBuf.begin(), RewriteBuf.end(), Buffer.get());
9052525730SSerge Pavlov   Out->write(Buffer.get(), RewriteBuf.size());
910621cb2eSAlp Toker }
92