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: 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> 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 550b57cec5SDimitry Andric void HTMLPrinter::Initialize(ASTContext &context) { 560b57cec5SDimitry Andric R.setSourceMgr(context.getSourceManager(), context.getLangOpts()); 570b57cec5SDimitry Andric } 580b57cec5SDimitry Andric 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