10b57cec5SDimitry Andric //===--- HTMLPrint.cpp - Source code -> HTML pretty-printing --------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Pretty-printing of source code to HTML.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
130b57cec5SDimitry Andric #include "clang/AST/ASTConsumer.h"
140b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
150b57cec5SDimitry Andric #include "clang/AST/Decl.h"
160b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h"
170b57cec5SDimitry Andric #include "clang/Basic/FileManager.h"
180b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
190b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h"
200b57cec5SDimitry Andric #include "clang/Rewrite/Core/HTMLRewrite.h"
210b57cec5SDimitry Andric #include "clang/Rewrite/Core/Rewriter.h"
220b57cec5SDimitry Andric #include "clang/Rewrite/Frontend/ASTConsumers.h"
230b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
240b57cec5SDimitry Andric using namespace clang;
250b57cec5SDimitry Andric
260b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
270b57cec5SDimitry Andric // Functional HTML pretty-printing.
280b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
290b57cec5SDimitry Andric
300b57cec5SDimitry Andric namespace {
310b57cec5SDimitry Andric class HTMLPrinter : public ASTConsumer {
320b57cec5SDimitry Andric Rewriter R;
330b57cec5SDimitry Andric std::unique_ptr<raw_ostream> Out;
340b57cec5SDimitry Andric Preprocessor &PP;
350b57cec5SDimitry Andric bool SyntaxHighlight, HighlightMacros;
360b57cec5SDimitry Andric
370b57cec5SDimitry Andric public:
HTMLPrinter(std::unique_ptr<raw_ostream> OS,Preprocessor & pp,bool _SyntaxHighlight,bool _HighlightMacros)380b57cec5SDimitry Andric HTMLPrinter(std::unique_ptr<raw_ostream> OS, Preprocessor &pp,
390b57cec5SDimitry Andric bool _SyntaxHighlight, bool _HighlightMacros)
400b57cec5SDimitry Andric : Out(std::move(OS)), PP(pp), SyntaxHighlight(_SyntaxHighlight),
410b57cec5SDimitry Andric HighlightMacros(_HighlightMacros) {}
420b57cec5SDimitry Andric
430b57cec5SDimitry Andric void Initialize(ASTContext &context) override;
440b57cec5SDimitry Andric void HandleTranslationUnit(ASTContext &Ctx) override;
450b57cec5SDimitry Andric };
460b57cec5SDimitry Andric }
470b57cec5SDimitry Andric
480b57cec5SDimitry Andric std::unique_ptr<ASTConsumer>
CreateHTMLPrinter(std::unique_ptr<raw_ostream> OS,Preprocessor & PP,bool SyntaxHighlight,bool HighlightMacros)490b57cec5SDimitry Andric clang::CreateHTMLPrinter(std::unique_ptr<raw_ostream> OS, Preprocessor &PP,
500b57cec5SDimitry Andric bool SyntaxHighlight, bool HighlightMacros) {
51a7dea167SDimitry Andric return std::make_unique<HTMLPrinter>(std::move(OS), PP, SyntaxHighlight,
520b57cec5SDimitry Andric HighlightMacros);
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric
Initialize(ASTContext & context)550b57cec5SDimitry Andric void HTMLPrinter::Initialize(ASTContext &context) {
560b57cec5SDimitry Andric R.setSourceMgr(context.getSourceManager(), context.getLangOpts());
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric
HandleTranslationUnit(ASTContext & Ctx)590b57cec5SDimitry Andric void HTMLPrinter::HandleTranslationUnit(ASTContext &Ctx) {
600b57cec5SDimitry Andric if (PP.getDiagnostics().hasErrorOccurred())
610b57cec5SDimitry Andric return;
620b57cec5SDimitry Andric
630b57cec5SDimitry Andric // Format the file.
640b57cec5SDimitry Andric FileID FID = R.getSourceMgr().getMainFileID();
65*5f757f3fSDimitry Andric OptionalFileEntryRef Entry = R.getSourceMgr().getFileEntryRefForID(FID);
660b57cec5SDimitry Andric StringRef Name;
670b57cec5SDimitry Andric // In some cases, in particular the case where the input is from stdin,
680b57cec5SDimitry Andric // there is no entry. Fall back to the memory buffer for a name in those
690b57cec5SDimitry Andric // cases.
700b57cec5SDimitry Andric if (Entry)
710b57cec5SDimitry Andric Name = Entry->getName();
720b57cec5SDimitry Andric else
73e8d8bef9SDimitry Andric Name = R.getSourceMgr().getBufferOrFake(FID).getBufferIdentifier();
740b57cec5SDimitry Andric
750b57cec5SDimitry Andric html::AddLineNumbers(R, FID);
760b57cec5SDimitry Andric html::AddHeaderFooterInternalBuiltinCSS(R, FID, Name);
770b57cec5SDimitry Andric
780b57cec5SDimitry Andric // If we have a preprocessor, relex the file and syntax highlight.
790b57cec5SDimitry Andric // We might not have a preprocessor if we come from a deserialized AST file,
800b57cec5SDimitry Andric // for example.
810b57cec5SDimitry Andric
820b57cec5SDimitry Andric if (SyntaxHighlight) html::SyntaxHighlight(R, FID, PP);
830b57cec5SDimitry Andric if (HighlightMacros) html::HighlightMacros(R, FID, PP);
840b57cec5SDimitry Andric html::EscapeText(R, FID, false, true);
850b57cec5SDimitry Andric
860b57cec5SDimitry Andric // Emit the HTML.
870b57cec5SDimitry Andric const RewriteBuffer &RewriteBuf = R.getEditBuffer(FID);
880b57cec5SDimitry Andric std::unique_ptr<char[]> Buffer(new char[RewriteBuf.size()]);
890b57cec5SDimitry Andric std::copy(RewriteBuf.begin(), RewriteBuf.end(), Buffer.get());
900b57cec5SDimitry Andric Out->write(Buffer.get(), RewriteBuf.size());
910b57cec5SDimitry Andric }
92