19e605113SDmitri Gribenko //===--- CommentToXML.cpp - Convert comments to XML representation --------===//
29e605113SDmitri Gribenko //
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
69e605113SDmitri Gribenko //
79e605113SDmitri Gribenko //===----------------------------------------------------------------------===//
89e605113SDmitri Gribenko
99e605113SDmitri Gribenko #include "clang/Index/CommentToXML.h"
109e605113SDmitri Gribenko #include "clang/AST/ASTContext.h"
115553d0d4SChandler Carruth #include "clang/AST/Attr.h"
129e605113SDmitri Gribenko #include "clang/AST/Comment.h"
139e605113SDmitri Gribenko #include "clang/AST/CommentVisitor.h"
14*e08464fbSReid Kleckner #include "clang/Basic/FileManager.h"
1586565c13SReid Kleckner #include "clang/Basic/SourceManager.h"
169e605113SDmitri Gribenko #include "clang/Format/Format.h"
179e605113SDmitri Gribenko #include "clang/Index/USRGeneration.h"
189e605113SDmitri Gribenko #include "llvm/ADT/StringExtras.h"
199e605113SDmitri Gribenko #include "llvm/ADT/TinyPtrVector.h"
209e605113SDmitri Gribenko #include "llvm/Support/raw_ostream.h"
219e605113SDmitri Gribenko
229e605113SDmitri Gribenko using namespace clang;
239e605113SDmitri Gribenko using namespace clang::comments;
249e605113SDmitri Gribenko using namespace clang::index;
259e605113SDmitri Gribenko
269e605113SDmitri Gribenko namespace {
279e605113SDmitri Gribenko
289e605113SDmitri Gribenko /// This comparison will sort parameters with valid index by index, then vararg
299e605113SDmitri Gribenko /// parameters, and invalid (unresolved) parameters last.
309e605113SDmitri Gribenko class ParamCommandCommentCompareIndex {
319e605113SDmitri Gribenko public:
operator ()(const ParamCommandComment * LHS,const ParamCommandComment * RHS) const329e605113SDmitri Gribenko bool operator()(const ParamCommandComment *LHS,
339e605113SDmitri Gribenko const ParamCommandComment *RHS) const {
349e605113SDmitri Gribenko unsigned LHSIndex = UINT_MAX;
359e605113SDmitri Gribenko unsigned RHSIndex = UINT_MAX;
369e605113SDmitri Gribenko
379e605113SDmitri Gribenko if (LHS->isParamIndexValid()) {
389e605113SDmitri Gribenko if (LHS->isVarArgParam())
399e605113SDmitri Gribenko LHSIndex = UINT_MAX - 1;
409e605113SDmitri Gribenko else
419e605113SDmitri Gribenko LHSIndex = LHS->getParamIndex();
429e605113SDmitri Gribenko }
439e605113SDmitri Gribenko if (RHS->isParamIndexValid()) {
449e605113SDmitri Gribenko if (RHS->isVarArgParam())
459e605113SDmitri Gribenko RHSIndex = UINT_MAX - 1;
469e605113SDmitri Gribenko else
479e605113SDmitri Gribenko RHSIndex = RHS->getParamIndex();
489e605113SDmitri Gribenko }
499e605113SDmitri Gribenko return LHSIndex < RHSIndex;
509e605113SDmitri Gribenko }
519e605113SDmitri Gribenko };
529e605113SDmitri Gribenko
539e605113SDmitri Gribenko /// This comparison will sort template parameters in the following order:
549e605113SDmitri Gribenko /// \li real template parameters (depth = 1) in index order;
559e605113SDmitri Gribenko /// \li all other names (depth > 1);
569e605113SDmitri Gribenko /// \li unresolved names.
579e605113SDmitri Gribenko class TParamCommandCommentComparePosition {
589e605113SDmitri Gribenko public:
operator ()(const TParamCommandComment * LHS,const TParamCommandComment * RHS) const599e605113SDmitri Gribenko bool operator()(const TParamCommandComment *LHS,
609e605113SDmitri Gribenko const TParamCommandComment *RHS) const {
619e605113SDmitri Gribenko // Sort unresolved names last.
629e605113SDmitri Gribenko if (!LHS->isPositionValid())
639e605113SDmitri Gribenko return false;
649e605113SDmitri Gribenko if (!RHS->isPositionValid())
659e605113SDmitri Gribenko return true;
669e605113SDmitri Gribenko
679e605113SDmitri Gribenko if (LHS->getDepth() > 1)
689e605113SDmitri Gribenko return false;
699e605113SDmitri Gribenko if (RHS->getDepth() > 1)
709e605113SDmitri Gribenko return true;
719e605113SDmitri Gribenko
729e605113SDmitri Gribenko // Sort template parameters in index order.
739e605113SDmitri Gribenko if (LHS->getDepth() == 1 && RHS->getDepth() == 1)
749e605113SDmitri Gribenko return LHS->getIndex(0) < RHS->getIndex(0);
759e605113SDmitri Gribenko
769e605113SDmitri Gribenko // Leave all other names in source order.
779e605113SDmitri Gribenko return true;
789e605113SDmitri Gribenko }
799e605113SDmitri Gribenko };
809e605113SDmitri Gribenko
819e605113SDmitri Gribenko /// Separate parts of a FullComment.
829e605113SDmitri Gribenko struct FullCommentParts {
839e605113SDmitri Gribenko /// Take a full comment apart and initialize members accordingly.
849e605113SDmitri Gribenko FullCommentParts(const FullComment *C,
859e605113SDmitri Gribenko const CommandTraits &Traits);
869e605113SDmitri Gribenko
879e605113SDmitri Gribenko const BlockContentComment *Brief;
889e605113SDmitri Gribenko const BlockContentComment *Headerfile;
899e605113SDmitri Gribenko const ParagraphComment *FirstParagraph;
909e605113SDmitri Gribenko SmallVector<const BlockCommandComment *, 4> Returns;
919e605113SDmitri Gribenko SmallVector<const ParamCommandComment *, 8> Params;
929e605113SDmitri Gribenko SmallVector<const TParamCommandComment *, 4> TParams;
939e605113SDmitri Gribenko llvm::TinyPtrVector<const BlockCommandComment *> Exceptions;
949e605113SDmitri Gribenko SmallVector<const BlockContentComment *, 8> MiscBlocks;
959e605113SDmitri Gribenko };
969e605113SDmitri Gribenko
FullCommentParts(const FullComment * C,const CommandTraits & Traits)979e605113SDmitri Gribenko FullCommentParts::FullCommentParts(const FullComment *C,
989e605113SDmitri Gribenko const CommandTraits &Traits) :
99236bde3dSCraig Topper Brief(nullptr), Headerfile(nullptr), FirstParagraph(nullptr) {
1009e605113SDmitri Gribenko for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
1019e605113SDmitri Gribenko I != E; ++I) {
1029e605113SDmitri Gribenko const Comment *Child = *I;
1039e605113SDmitri Gribenko if (!Child)
1049e605113SDmitri Gribenko continue;
1059e605113SDmitri Gribenko switch (Child->getCommentKind()) {
1069e605113SDmitri Gribenko case Comment::NoCommentKind:
1079e605113SDmitri Gribenko continue;
1089e605113SDmitri Gribenko
1099e605113SDmitri Gribenko case Comment::ParagraphCommentKind: {
1109e605113SDmitri Gribenko const ParagraphComment *PC = cast<ParagraphComment>(Child);
1119e605113SDmitri Gribenko if (PC->isWhitespace())
1129e605113SDmitri Gribenko break;
1139e605113SDmitri Gribenko if (!FirstParagraph)
1149e605113SDmitri Gribenko FirstParagraph = PC;
1159e605113SDmitri Gribenko
1169e605113SDmitri Gribenko MiscBlocks.push_back(PC);
1179e605113SDmitri Gribenko break;
1189e605113SDmitri Gribenko }
1199e605113SDmitri Gribenko
1209e605113SDmitri Gribenko case Comment::BlockCommandCommentKind: {
1219e605113SDmitri Gribenko const BlockCommandComment *BCC = cast<BlockCommandComment>(Child);
1229e605113SDmitri Gribenko const CommandInfo *Info = Traits.getCommandInfo(BCC->getCommandID());
1239e605113SDmitri Gribenko if (!Brief && Info->IsBriefCommand) {
1249e605113SDmitri Gribenko Brief = BCC;
1259e605113SDmitri Gribenko break;
1269e605113SDmitri Gribenko }
1279e605113SDmitri Gribenko if (!Headerfile && Info->IsHeaderfileCommand) {
1289e605113SDmitri Gribenko Headerfile = BCC;
1299e605113SDmitri Gribenko break;
1309e605113SDmitri Gribenko }
1319e605113SDmitri Gribenko if (Info->IsReturnsCommand) {
1329e605113SDmitri Gribenko Returns.push_back(BCC);
1339e605113SDmitri Gribenko break;
1349e605113SDmitri Gribenko }
1359e605113SDmitri Gribenko if (Info->IsThrowsCommand) {
1369e605113SDmitri Gribenko Exceptions.push_back(BCC);
1379e605113SDmitri Gribenko break;
1389e605113SDmitri Gribenko }
1399e605113SDmitri Gribenko MiscBlocks.push_back(BCC);
1409e605113SDmitri Gribenko break;
1419e605113SDmitri Gribenko }
1429e605113SDmitri Gribenko
1439e605113SDmitri Gribenko case Comment::ParamCommandCommentKind: {
1449e605113SDmitri Gribenko const ParamCommandComment *PCC = cast<ParamCommandComment>(Child);
1459e605113SDmitri Gribenko if (!PCC->hasParamName())
1469e605113SDmitri Gribenko break;
1479e605113SDmitri Gribenko
1489e605113SDmitri Gribenko if (!PCC->isDirectionExplicit() && !PCC->hasNonWhitespaceParagraph())
1499e605113SDmitri Gribenko break;
1509e605113SDmitri Gribenko
1519e605113SDmitri Gribenko Params.push_back(PCC);
1529e605113SDmitri Gribenko break;
1539e605113SDmitri Gribenko }
1549e605113SDmitri Gribenko
1559e605113SDmitri Gribenko case Comment::TParamCommandCommentKind: {
1569e605113SDmitri Gribenko const TParamCommandComment *TPCC = cast<TParamCommandComment>(Child);
1579e605113SDmitri Gribenko if (!TPCC->hasParamName())
1589e605113SDmitri Gribenko break;
1599e605113SDmitri Gribenko
1609e605113SDmitri Gribenko if (!TPCC->hasNonWhitespaceParagraph())
1619e605113SDmitri Gribenko break;
1629e605113SDmitri Gribenko
1639e605113SDmitri Gribenko TParams.push_back(TPCC);
1649e605113SDmitri Gribenko break;
1659e605113SDmitri Gribenko }
1669e605113SDmitri Gribenko
1679e605113SDmitri Gribenko case Comment::VerbatimBlockCommentKind:
1689e605113SDmitri Gribenko MiscBlocks.push_back(cast<BlockCommandComment>(Child));
1699e605113SDmitri Gribenko break;
1709e605113SDmitri Gribenko
1719e605113SDmitri Gribenko case Comment::VerbatimLineCommentKind: {
1729e605113SDmitri Gribenko const VerbatimLineComment *VLC = cast<VerbatimLineComment>(Child);
1739e605113SDmitri Gribenko const CommandInfo *Info = Traits.getCommandInfo(VLC->getCommandID());
1749e605113SDmitri Gribenko if (!Info->IsDeclarationCommand)
1759e605113SDmitri Gribenko MiscBlocks.push_back(VLC);
1769e605113SDmitri Gribenko break;
1779e605113SDmitri Gribenko }
1789e605113SDmitri Gribenko
1799e605113SDmitri Gribenko case Comment::TextCommentKind:
1809e605113SDmitri Gribenko case Comment::InlineCommandCommentKind:
1819e605113SDmitri Gribenko case Comment::HTMLStartTagCommentKind:
1829e605113SDmitri Gribenko case Comment::HTMLEndTagCommentKind:
1839e605113SDmitri Gribenko case Comment::VerbatimBlockLineCommentKind:
1849e605113SDmitri Gribenko case Comment::FullCommentKind:
1859e605113SDmitri Gribenko llvm_unreachable("AST node of this kind can't be a child of "
1869e605113SDmitri Gribenko "a FullComment");
1879e605113SDmitri Gribenko }
1889e605113SDmitri Gribenko }
1899e605113SDmitri Gribenko
1909e605113SDmitri Gribenko // Sort params in order they are declared in the function prototype.
1919e605113SDmitri Gribenko // Unresolved parameters are put at the end of the list in the same order
1929e605113SDmitri Gribenko // they were seen in the comment.
193899d1392SFangrui Song llvm::stable_sort(Params, ParamCommandCommentCompareIndex());
194899d1392SFangrui Song llvm::stable_sort(TParams, TParamCommandCommentComparePosition());
1959e605113SDmitri Gribenko }
1969e605113SDmitri Gribenko
printHTMLStartTagComment(const HTMLStartTagComment * C,llvm::raw_svector_ostream & Result)1979e605113SDmitri Gribenko void printHTMLStartTagComment(const HTMLStartTagComment *C,
1989e605113SDmitri Gribenko llvm::raw_svector_ostream &Result) {
1999e605113SDmitri Gribenko Result << "<" << C->getTagName();
2009e605113SDmitri Gribenko
2019e605113SDmitri Gribenko if (C->getNumAttrs() != 0) {
2029e605113SDmitri Gribenko for (unsigned i = 0, e = C->getNumAttrs(); i != e; i++) {
2039e605113SDmitri Gribenko Result << " ";
2049e605113SDmitri Gribenko const HTMLStartTagComment::Attribute &Attr = C->getAttr(i);
2059e605113SDmitri Gribenko Result << Attr.Name;
2069e605113SDmitri Gribenko if (!Attr.Value.empty())
2079e605113SDmitri Gribenko Result << "=\"" << Attr.Value << "\"";
2089e605113SDmitri Gribenko }
2099e605113SDmitri Gribenko }
2109e605113SDmitri Gribenko
2119e605113SDmitri Gribenko if (!C->isSelfClosing())
2129e605113SDmitri Gribenko Result << ">";
2139e605113SDmitri Gribenko else
2149e605113SDmitri Gribenko Result << "/>";
2159e605113SDmitri Gribenko }
2169e605113SDmitri Gribenko
2179e605113SDmitri Gribenko class CommentASTToHTMLConverter :
2189e605113SDmitri Gribenko public ConstCommentVisitor<CommentASTToHTMLConverter> {
2199e605113SDmitri Gribenko public:
2209e605113SDmitri Gribenko /// \param Str accumulator for HTML.
CommentASTToHTMLConverter(const FullComment * FC,SmallVectorImpl<char> & Str,const CommandTraits & Traits)2219e605113SDmitri Gribenko CommentASTToHTMLConverter(const FullComment *FC,
2229e605113SDmitri Gribenko SmallVectorImpl<char> &Str,
2239e605113SDmitri Gribenko const CommandTraits &Traits) :
2249e605113SDmitri Gribenko FC(FC), Result(Str), Traits(Traits)
2259e605113SDmitri Gribenko { }
2269e605113SDmitri Gribenko
2279e605113SDmitri Gribenko // Inline content.
2289e605113SDmitri Gribenko void visitTextComment(const TextComment *C);
2299e605113SDmitri Gribenko void visitInlineCommandComment(const InlineCommandComment *C);
2309e605113SDmitri Gribenko void visitHTMLStartTagComment(const HTMLStartTagComment *C);
2319e605113SDmitri Gribenko void visitHTMLEndTagComment(const HTMLEndTagComment *C);
2329e605113SDmitri Gribenko
2339e605113SDmitri Gribenko // Block content.
2349e605113SDmitri Gribenko void visitParagraphComment(const ParagraphComment *C);
2359e605113SDmitri Gribenko void visitBlockCommandComment(const BlockCommandComment *C);
2369e605113SDmitri Gribenko void visitParamCommandComment(const ParamCommandComment *C);
2379e605113SDmitri Gribenko void visitTParamCommandComment(const TParamCommandComment *C);
2389e605113SDmitri Gribenko void visitVerbatimBlockComment(const VerbatimBlockComment *C);
2399e605113SDmitri Gribenko void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C);
2409e605113SDmitri Gribenko void visitVerbatimLineComment(const VerbatimLineComment *C);
2419e605113SDmitri Gribenko
2429e605113SDmitri Gribenko void visitFullComment(const FullComment *C);
2439e605113SDmitri Gribenko
2449e605113SDmitri Gribenko // Helpers.
2459e605113SDmitri Gribenko
2469e605113SDmitri Gribenko /// Convert a paragraph that is not a block by itself (an argument to some
2479e605113SDmitri Gribenko /// command).
2489e605113SDmitri Gribenko void visitNonStandaloneParagraphComment(const ParagraphComment *C);
2499e605113SDmitri Gribenko
2509e605113SDmitri Gribenko void appendToResultWithHTMLEscaping(StringRef S);
2519e605113SDmitri Gribenko
2529e605113SDmitri Gribenko private:
2539e605113SDmitri Gribenko const FullComment *FC;
2549e605113SDmitri Gribenko /// Output stream for HTML.
2559e605113SDmitri Gribenko llvm::raw_svector_ostream Result;
2569e605113SDmitri Gribenko
2579e605113SDmitri Gribenko const CommandTraits &Traits;
2589e605113SDmitri Gribenko };
2599e605113SDmitri Gribenko } // end unnamed namespace
2609e605113SDmitri Gribenko
visitTextComment(const TextComment * C)2619e605113SDmitri Gribenko void CommentASTToHTMLConverter::visitTextComment(const TextComment *C) {
2629e605113SDmitri Gribenko appendToResultWithHTMLEscaping(C->getText());
2639e605113SDmitri Gribenko }
2649e605113SDmitri Gribenko
visitInlineCommandComment(const InlineCommandComment * C)2659e605113SDmitri Gribenko void CommentASTToHTMLConverter::visitInlineCommandComment(
2669e605113SDmitri Gribenko const InlineCommandComment *C) {
2679e605113SDmitri Gribenko // Nothing to render if no arguments supplied.
2689e605113SDmitri Gribenko if (C->getNumArgs() == 0)
2699e605113SDmitri Gribenko return;
2709e605113SDmitri Gribenko
2719e605113SDmitri Gribenko // Nothing to render if argument is empty.
2729e605113SDmitri Gribenko StringRef Arg0 = C->getArgText(0);
2739e605113SDmitri Gribenko if (Arg0.empty())
2749e605113SDmitri Gribenko return;
2759e605113SDmitri Gribenko
2769e605113SDmitri Gribenko switch (C->getRenderKind()) {
2779e605113SDmitri Gribenko case InlineCommandComment::RenderNormal:
2789e605113SDmitri Gribenko for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) {
2799e605113SDmitri Gribenko appendToResultWithHTMLEscaping(C->getArgText(i));
2809e605113SDmitri Gribenko Result << " ";
2819e605113SDmitri Gribenko }
2829e605113SDmitri Gribenko return;
2839e605113SDmitri Gribenko
2849e605113SDmitri Gribenko case InlineCommandComment::RenderBold:
2859e605113SDmitri Gribenko assert(C->getNumArgs() == 1);
2869e605113SDmitri Gribenko Result << "<b>";
2879e605113SDmitri Gribenko appendToResultWithHTMLEscaping(Arg0);
2889e605113SDmitri Gribenko Result << "</b>";
2899e605113SDmitri Gribenko return;
2909e605113SDmitri Gribenko case InlineCommandComment::RenderMonospaced:
2919e605113SDmitri Gribenko assert(C->getNumArgs() == 1);
2929e605113SDmitri Gribenko Result << "<tt>";
2939e605113SDmitri Gribenko appendToResultWithHTMLEscaping(Arg0);
2949e605113SDmitri Gribenko Result<< "</tt>";
2959e605113SDmitri Gribenko return;
2969e605113SDmitri Gribenko case InlineCommandComment::RenderEmphasized:
2979e605113SDmitri Gribenko assert(C->getNumArgs() == 1);
2989e605113SDmitri Gribenko Result << "<em>";
2999e605113SDmitri Gribenko appendToResultWithHTMLEscaping(Arg0);
3009e605113SDmitri Gribenko Result << "</em>";
3019e605113SDmitri Gribenko return;
302be1a9b38SMark de Wever case InlineCommandComment::RenderAnchor:
303be1a9b38SMark de Wever assert(C->getNumArgs() == 1);
304be1a9b38SMark de Wever Result << "<span id=\"" << Arg0 << "\"></span>";
305be1a9b38SMark de Wever return;
3069e605113SDmitri Gribenko }
3079e605113SDmitri Gribenko }
3089e605113SDmitri Gribenko
visitHTMLStartTagComment(const HTMLStartTagComment * C)3099e605113SDmitri Gribenko void CommentASTToHTMLConverter::visitHTMLStartTagComment(
3109e605113SDmitri Gribenko const HTMLStartTagComment *C) {
3119e605113SDmitri Gribenko printHTMLStartTagComment(C, Result);
3129e605113SDmitri Gribenko }
3139e605113SDmitri Gribenko
visitHTMLEndTagComment(const HTMLEndTagComment * C)3149e605113SDmitri Gribenko void CommentASTToHTMLConverter::visitHTMLEndTagComment(
3159e605113SDmitri Gribenko const HTMLEndTagComment *C) {
3169e605113SDmitri Gribenko Result << "</" << C->getTagName() << ">";
3179e605113SDmitri Gribenko }
3189e605113SDmitri Gribenko
visitParagraphComment(const ParagraphComment * C)3199e605113SDmitri Gribenko void CommentASTToHTMLConverter::visitParagraphComment(
3209e605113SDmitri Gribenko const ParagraphComment *C) {
3219e605113SDmitri Gribenko if (C->isWhitespace())
3229e605113SDmitri Gribenko return;
3239e605113SDmitri Gribenko
3249e605113SDmitri Gribenko Result << "<p>";
3259e605113SDmitri Gribenko for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
3269e605113SDmitri Gribenko I != E; ++I) {
3279e605113SDmitri Gribenko visit(*I);
3289e605113SDmitri Gribenko }
3299e605113SDmitri Gribenko Result << "</p>";
3309e605113SDmitri Gribenko }
3319e605113SDmitri Gribenko
visitBlockCommandComment(const BlockCommandComment * C)3329e605113SDmitri Gribenko void CommentASTToHTMLConverter::visitBlockCommandComment(
3339e605113SDmitri Gribenko const BlockCommandComment *C) {
3349e605113SDmitri Gribenko const CommandInfo *Info = Traits.getCommandInfo(C->getCommandID());
3359e605113SDmitri Gribenko if (Info->IsBriefCommand) {
3369e605113SDmitri Gribenko Result << "<p class=\"para-brief\">";
3379e605113SDmitri Gribenko visitNonStandaloneParagraphComment(C->getParagraph());
3389e605113SDmitri Gribenko Result << "</p>";
3399e605113SDmitri Gribenko return;
3409e605113SDmitri Gribenko }
3419e605113SDmitri Gribenko if (Info->IsReturnsCommand) {
3429e605113SDmitri Gribenko Result << "<p class=\"para-returns\">"
3439e605113SDmitri Gribenko "<span class=\"word-returns\">Returns</span> ";
3449e605113SDmitri Gribenko visitNonStandaloneParagraphComment(C->getParagraph());
3459e605113SDmitri Gribenko Result << "</p>";
3469e605113SDmitri Gribenko return;
3479e605113SDmitri Gribenko }
3489e605113SDmitri Gribenko // We don't know anything about this command. Just render the paragraph.
3499e605113SDmitri Gribenko visit(C->getParagraph());
3509e605113SDmitri Gribenko }
3519e605113SDmitri Gribenko
visitParamCommandComment(const ParamCommandComment * C)3529e605113SDmitri Gribenko void CommentASTToHTMLConverter::visitParamCommandComment(
3539e605113SDmitri Gribenko const ParamCommandComment *C) {
3549e605113SDmitri Gribenko if (C->isParamIndexValid()) {
3559e605113SDmitri Gribenko if (C->isVarArgParam()) {
3569e605113SDmitri Gribenko Result << "<dt class=\"param-name-index-vararg\">";
3579e605113SDmitri Gribenko appendToResultWithHTMLEscaping(C->getParamNameAsWritten());
3589e605113SDmitri Gribenko } else {
3599e605113SDmitri Gribenko Result << "<dt class=\"param-name-index-"
3609e605113SDmitri Gribenko << C->getParamIndex()
3619e605113SDmitri Gribenko << "\">";
3629e605113SDmitri Gribenko appendToResultWithHTMLEscaping(C->getParamName(FC));
3639e605113SDmitri Gribenko }
3649e605113SDmitri Gribenko } else {
3659e605113SDmitri Gribenko Result << "<dt class=\"param-name-index-invalid\">";
3669e605113SDmitri Gribenko appendToResultWithHTMLEscaping(C->getParamNameAsWritten());
3679e605113SDmitri Gribenko }
3689e605113SDmitri Gribenko Result << "</dt>";
3699e605113SDmitri Gribenko
3709e605113SDmitri Gribenko if (C->isParamIndexValid()) {
3719e605113SDmitri Gribenko if (C->isVarArgParam())
3729e605113SDmitri Gribenko Result << "<dd class=\"param-descr-index-vararg\">";
3739e605113SDmitri Gribenko else
3749e605113SDmitri Gribenko Result << "<dd class=\"param-descr-index-"
3759e605113SDmitri Gribenko << C->getParamIndex()
3769e605113SDmitri Gribenko << "\">";
3779e605113SDmitri Gribenko } else
3789e605113SDmitri Gribenko Result << "<dd class=\"param-descr-index-invalid\">";
3799e605113SDmitri Gribenko
3809e605113SDmitri Gribenko visitNonStandaloneParagraphComment(C->getParagraph());
3819e605113SDmitri Gribenko Result << "</dd>";
3829e605113SDmitri Gribenko }
3839e605113SDmitri Gribenko
visitTParamCommandComment(const TParamCommandComment * C)3849e605113SDmitri Gribenko void CommentASTToHTMLConverter::visitTParamCommandComment(
3859e605113SDmitri Gribenko const TParamCommandComment *C) {
3869e605113SDmitri Gribenko if (C->isPositionValid()) {
3879e605113SDmitri Gribenko if (C->getDepth() == 1)
3889e605113SDmitri Gribenko Result << "<dt class=\"tparam-name-index-"
3899e605113SDmitri Gribenko << C->getIndex(0)
3909e605113SDmitri Gribenko << "\">";
3919e605113SDmitri Gribenko else
3929e605113SDmitri Gribenko Result << "<dt class=\"tparam-name-index-other\">";
3939e605113SDmitri Gribenko appendToResultWithHTMLEscaping(C->getParamName(FC));
3949e605113SDmitri Gribenko } else {
3959e605113SDmitri Gribenko Result << "<dt class=\"tparam-name-index-invalid\">";
3969e605113SDmitri Gribenko appendToResultWithHTMLEscaping(C->getParamNameAsWritten());
3979e605113SDmitri Gribenko }
3989e605113SDmitri Gribenko
3999e605113SDmitri Gribenko Result << "</dt>";
4009e605113SDmitri Gribenko
4019e605113SDmitri Gribenko if (C->isPositionValid()) {
4029e605113SDmitri Gribenko if (C->getDepth() == 1)
4039e605113SDmitri Gribenko Result << "<dd class=\"tparam-descr-index-"
4049e605113SDmitri Gribenko << C->getIndex(0)
4059e605113SDmitri Gribenko << "\">";
4069e605113SDmitri Gribenko else
4079e605113SDmitri Gribenko Result << "<dd class=\"tparam-descr-index-other\">";
4089e605113SDmitri Gribenko } else
4099e605113SDmitri Gribenko Result << "<dd class=\"tparam-descr-index-invalid\">";
4109e605113SDmitri Gribenko
4119e605113SDmitri Gribenko visitNonStandaloneParagraphComment(C->getParagraph());
4129e605113SDmitri Gribenko Result << "</dd>";
4139e605113SDmitri Gribenko }
4149e605113SDmitri Gribenko
visitVerbatimBlockComment(const VerbatimBlockComment * C)4159e605113SDmitri Gribenko void CommentASTToHTMLConverter::visitVerbatimBlockComment(
4169e605113SDmitri Gribenko const VerbatimBlockComment *C) {
4179e605113SDmitri Gribenko unsigned NumLines = C->getNumLines();
4189e605113SDmitri Gribenko if (NumLines == 0)
4199e605113SDmitri Gribenko return;
4209e605113SDmitri Gribenko
4219e605113SDmitri Gribenko Result << "<pre>";
4229e605113SDmitri Gribenko for (unsigned i = 0; i != NumLines; ++i) {
4239e605113SDmitri Gribenko appendToResultWithHTMLEscaping(C->getText(i));
4249e605113SDmitri Gribenko if (i + 1 != NumLines)
4259e605113SDmitri Gribenko Result << '\n';
4269e605113SDmitri Gribenko }
4279e605113SDmitri Gribenko Result << "</pre>";
4289e605113SDmitri Gribenko }
4299e605113SDmitri Gribenko
visitVerbatimBlockLineComment(const VerbatimBlockLineComment * C)4309e605113SDmitri Gribenko void CommentASTToHTMLConverter::visitVerbatimBlockLineComment(
4319e605113SDmitri Gribenko const VerbatimBlockLineComment *C) {
4329e605113SDmitri Gribenko llvm_unreachable("should not see this AST node");
4339e605113SDmitri Gribenko }
4349e605113SDmitri Gribenko
visitVerbatimLineComment(const VerbatimLineComment * C)4359e605113SDmitri Gribenko void CommentASTToHTMLConverter::visitVerbatimLineComment(
4369e605113SDmitri Gribenko const VerbatimLineComment *C) {
4379e605113SDmitri Gribenko Result << "<pre>";
4389e605113SDmitri Gribenko appendToResultWithHTMLEscaping(C->getText());
4399e605113SDmitri Gribenko Result << "</pre>";
4409e605113SDmitri Gribenko }
4419e605113SDmitri Gribenko
visitFullComment(const FullComment * C)4429e605113SDmitri Gribenko void CommentASTToHTMLConverter::visitFullComment(const FullComment *C) {
4439e605113SDmitri Gribenko FullCommentParts Parts(C, Traits);
4449e605113SDmitri Gribenko
4459e605113SDmitri Gribenko bool FirstParagraphIsBrief = false;
4469e605113SDmitri Gribenko if (Parts.Headerfile)
4479e605113SDmitri Gribenko visit(Parts.Headerfile);
4489e605113SDmitri Gribenko if (Parts.Brief)
4499e605113SDmitri Gribenko visit(Parts.Brief);
4509e605113SDmitri Gribenko else if (Parts.FirstParagraph) {
4519e605113SDmitri Gribenko Result << "<p class=\"para-brief\">";
4529e605113SDmitri Gribenko visitNonStandaloneParagraphComment(Parts.FirstParagraph);
4539e605113SDmitri Gribenko Result << "</p>";
4549e605113SDmitri Gribenko FirstParagraphIsBrief = true;
4559e605113SDmitri Gribenko }
4569e605113SDmitri Gribenko
4579e605113SDmitri Gribenko for (unsigned i = 0, e = Parts.MiscBlocks.size(); i != e; ++i) {
4589e605113SDmitri Gribenko const Comment *C = Parts.MiscBlocks[i];
4599e605113SDmitri Gribenko if (FirstParagraphIsBrief && C == Parts.FirstParagraph)
4609e605113SDmitri Gribenko continue;
4619e605113SDmitri Gribenko visit(C);
4629e605113SDmitri Gribenko }
4639e605113SDmitri Gribenko
4649e605113SDmitri Gribenko if (Parts.TParams.size() != 0) {
4659e605113SDmitri Gribenko Result << "<dl>";
4669e605113SDmitri Gribenko for (unsigned i = 0, e = Parts.TParams.size(); i != e; ++i)
4679e605113SDmitri Gribenko visit(Parts.TParams[i]);
4689e605113SDmitri Gribenko Result << "</dl>";
4699e605113SDmitri Gribenko }
4709e605113SDmitri Gribenko
4719e605113SDmitri Gribenko if (Parts.Params.size() != 0) {
4729e605113SDmitri Gribenko Result << "<dl>";
4739e605113SDmitri Gribenko for (unsigned i = 0, e = Parts.Params.size(); i != e; ++i)
4749e605113SDmitri Gribenko visit(Parts.Params[i]);
4759e605113SDmitri Gribenko Result << "</dl>";
4769e605113SDmitri Gribenko }
4779e605113SDmitri Gribenko
4789e605113SDmitri Gribenko if (Parts.Returns.size() != 0) {
4799e605113SDmitri Gribenko Result << "<div class=\"result-discussion\">";
4809e605113SDmitri Gribenko for (unsigned i = 0, e = Parts.Returns.size(); i != e; ++i)
4819e605113SDmitri Gribenko visit(Parts.Returns[i]);
4829e605113SDmitri Gribenko Result << "</div>";
4839e605113SDmitri Gribenko }
4849e605113SDmitri Gribenko
4859e605113SDmitri Gribenko }
4869e605113SDmitri Gribenko
visitNonStandaloneParagraphComment(const ParagraphComment * C)4879e605113SDmitri Gribenko void CommentASTToHTMLConverter::visitNonStandaloneParagraphComment(
4889e605113SDmitri Gribenko const ParagraphComment *C) {
4899e605113SDmitri Gribenko if (!C)
4909e605113SDmitri Gribenko return;
4919e605113SDmitri Gribenko
4929e605113SDmitri Gribenko for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
4939e605113SDmitri Gribenko I != E; ++I) {
4949e605113SDmitri Gribenko visit(*I);
4959e605113SDmitri Gribenko }
4969e605113SDmitri Gribenko }
4979e605113SDmitri Gribenko
appendToResultWithHTMLEscaping(StringRef S)4989e605113SDmitri Gribenko void CommentASTToHTMLConverter::appendToResultWithHTMLEscaping(StringRef S) {
4999e605113SDmitri Gribenko for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I) {
5009e605113SDmitri Gribenko const char C = *I;
5019e605113SDmitri Gribenko switch (C) {
5029e605113SDmitri Gribenko case '&':
5039e605113SDmitri Gribenko Result << "&";
5049e605113SDmitri Gribenko break;
5059e605113SDmitri Gribenko case '<':
5069e605113SDmitri Gribenko Result << "<";
5079e605113SDmitri Gribenko break;
5089e605113SDmitri Gribenko case '>':
5099e605113SDmitri Gribenko Result << ">";
5109e605113SDmitri Gribenko break;
5119e605113SDmitri Gribenko case '"':
5129e605113SDmitri Gribenko Result << """;
5139e605113SDmitri Gribenko break;
5149e605113SDmitri Gribenko case '\'':
5159e605113SDmitri Gribenko Result << "'";
5169e605113SDmitri Gribenko break;
5179e605113SDmitri Gribenko case '/':
5189e605113SDmitri Gribenko Result << "/";
5199e605113SDmitri Gribenko break;
5209e605113SDmitri Gribenko default:
5219e605113SDmitri Gribenko Result << C;
5229e605113SDmitri Gribenko break;
5239e605113SDmitri Gribenko }
5249e605113SDmitri Gribenko }
5259e605113SDmitri Gribenko }
5269e605113SDmitri Gribenko
5279e605113SDmitri Gribenko namespace {
5289e605113SDmitri Gribenko class CommentASTToXMLConverter :
5299e605113SDmitri Gribenko public ConstCommentVisitor<CommentASTToXMLConverter> {
5309e605113SDmitri Gribenko public:
5319e605113SDmitri Gribenko /// \param Str accumulator for XML.
CommentASTToXMLConverter(const FullComment * FC,SmallVectorImpl<char> & Str,const CommandTraits & Traits,const SourceManager & SM)5329e605113SDmitri Gribenko CommentASTToXMLConverter(const FullComment *FC,
5339e605113SDmitri Gribenko SmallVectorImpl<char> &Str,
5349e605113SDmitri Gribenko const CommandTraits &Traits,
535d21485d2SDaniel Jasper const SourceManager &SM) :
536d21485d2SDaniel Jasper FC(FC), Result(Str), Traits(Traits), SM(SM) { }
5379e605113SDmitri Gribenko
5389e605113SDmitri Gribenko // Inline content.
5399e605113SDmitri Gribenko void visitTextComment(const TextComment *C);
5409e605113SDmitri Gribenko void visitInlineCommandComment(const InlineCommandComment *C);
5419e605113SDmitri Gribenko void visitHTMLStartTagComment(const HTMLStartTagComment *C);
5429e605113SDmitri Gribenko void visitHTMLEndTagComment(const HTMLEndTagComment *C);
5439e605113SDmitri Gribenko
5449e605113SDmitri Gribenko // Block content.
5459e605113SDmitri Gribenko void visitParagraphComment(const ParagraphComment *C);
5469e605113SDmitri Gribenko
5479e605113SDmitri Gribenko void appendParagraphCommentWithKind(const ParagraphComment *C,
5489e605113SDmitri Gribenko StringRef Kind);
5499e605113SDmitri Gribenko
5509e605113SDmitri Gribenko void visitBlockCommandComment(const BlockCommandComment *C);
5519e605113SDmitri Gribenko void visitParamCommandComment(const ParamCommandComment *C);
5529e605113SDmitri Gribenko void visitTParamCommandComment(const TParamCommandComment *C);
5539e605113SDmitri Gribenko void visitVerbatimBlockComment(const VerbatimBlockComment *C);
5549e605113SDmitri Gribenko void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C);
5559e605113SDmitri Gribenko void visitVerbatimLineComment(const VerbatimLineComment *C);
5569e605113SDmitri Gribenko
5579e605113SDmitri Gribenko void visitFullComment(const FullComment *C);
5589e605113SDmitri Gribenko
5599e605113SDmitri Gribenko // Helpers.
5609e605113SDmitri Gribenko void appendToResultWithXMLEscaping(StringRef S);
5616db07e2aSDmitri Gribenko void appendToResultWithCDATAEscaping(StringRef S);
5629e605113SDmitri Gribenko
5639e605113SDmitri Gribenko void formatTextOfDeclaration(const DeclInfo *DI,
5649e605113SDmitri Gribenko SmallString<128> &Declaration);
5659e605113SDmitri Gribenko
5669e605113SDmitri Gribenko private:
5679e605113SDmitri Gribenko const FullComment *FC;
5689e605113SDmitri Gribenko
5699e605113SDmitri Gribenko /// Output stream for XML.
5709e605113SDmitri Gribenko llvm::raw_svector_ostream Result;
5719e605113SDmitri Gribenko
5729e605113SDmitri Gribenko const CommandTraits &Traits;
5739e605113SDmitri Gribenko const SourceManager &SM;
5749e605113SDmitri Gribenko };
5759e605113SDmitri Gribenko
getSourceTextOfDeclaration(const DeclInfo * ThisDecl,SmallVectorImpl<char> & Str)5769e605113SDmitri Gribenko void getSourceTextOfDeclaration(const DeclInfo *ThisDecl,
5779e605113SDmitri Gribenko SmallVectorImpl<char> &Str) {
5789e605113SDmitri Gribenko ASTContext &Context = ThisDecl->CurrentDecl->getASTContext();
5799e605113SDmitri Gribenko const LangOptions &LangOpts = Context.getLangOpts();
5809e605113SDmitri Gribenko llvm::raw_svector_ostream OS(Str);
5819e605113SDmitri Gribenko PrintingPolicy PPolicy(LangOpts);
5829e605113SDmitri Gribenko PPolicy.PolishForDeclaration = true;
5839e605113SDmitri Gribenko PPolicy.TerseOutput = true;
58436070ed8SAlex Lorenz PPolicy.ConstantsAsWritten = true;
5859e605113SDmitri Gribenko ThisDecl->CurrentDecl->print(OS, PPolicy,
5869e605113SDmitri Gribenko /*Indentation*/0, /*PrintInstantiation*/false);
5879e605113SDmitri Gribenko }
5889e605113SDmitri Gribenko
formatTextOfDeclaration(const DeclInfo * DI,SmallString<128> & Declaration)5899e605113SDmitri Gribenko void CommentASTToXMLConverter::formatTextOfDeclaration(
5909e605113SDmitri Gribenko const DeclInfo *DI, SmallString<128> &Declaration) {
5910772c423SBenjamin Kramer // Formatting API expects null terminated input string.
5920772c423SBenjamin Kramer StringRef StringDecl(Declaration.c_str(), Declaration.size());
5939e605113SDmitri Gribenko
5949e605113SDmitri Gribenko // Formatter specific code.
595528d682fSDaniel Jasper unsigned Offset = 0;
5969e605113SDmitri Gribenko unsigned Length = Declaration.size();
5979e605113SDmitri Gribenko
59832eaa864SKrasimir Georgiev format::FormatStyle Style = format::getLLVMStyle();
59932eaa864SKrasimir Georgiev Style.FixNamespaceComments = false;
600528d682fSDaniel Jasper tooling::Replacements Replaces =
601e48c1b56SKrasimir Georgiev reformat(Style, StringDecl, tooling::Range(Offset, Length), "xmldecl.xd");
602528d682fSDaniel Jasper auto FormattedStringDecl = applyAllReplacements(StringDecl, Replaces);
603528d682fSDaniel Jasper if (static_cast<bool>(FormattedStringDecl)) {
604528d682fSDaniel Jasper Declaration = *FormattedStringDecl;
605528d682fSDaniel Jasper }
6069e605113SDmitri Gribenko }
6079e605113SDmitri Gribenko
6089e605113SDmitri Gribenko } // end unnamed namespace
6099e605113SDmitri Gribenko
visitTextComment(const TextComment * C)6109e605113SDmitri Gribenko void CommentASTToXMLConverter::visitTextComment(const TextComment *C) {
6119e605113SDmitri Gribenko appendToResultWithXMLEscaping(C->getText());
6129e605113SDmitri Gribenko }
6139e605113SDmitri Gribenko
visitInlineCommandComment(const InlineCommandComment * C)6149e605113SDmitri Gribenko void CommentASTToXMLConverter::visitInlineCommandComment(
6159e605113SDmitri Gribenko const InlineCommandComment *C) {
6169e605113SDmitri Gribenko // Nothing to render if no arguments supplied.
6179e605113SDmitri Gribenko if (C->getNumArgs() == 0)
6189e605113SDmitri Gribenko return;
6199e605113SDmitri Gribenko
6209e605113SDmitri Gribenko // Nothing to render if argument is empty.
6219e605113SDmitri Gribenko StringRef Arg0 = C->getArgText(0);
6229e605113SDmitri Gribenko if (Arg0.empty())
6239e605113SDmitri Gribenko return;
6249e605113SDmitri Gribenko
6259e605113SDmitri Gribenko switch (C->getRenderKind()) {
6269e605113SDmitri Gribenko case InlineCommandComment::RenderNormal:
6279e605113SDmitri Gribenko for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) {
6289e605113SDmitri Gribenko appendToResultWithXMLEscaping(C->getArgText(i));
6299e605113SDmitri Gribenko Result << " ";
6309e605113SDmitri Gribenko }
6319e605113SDmitri Gribenko return;
6329e605113SDmitri Gribenko case InlineCommandComment::RenderBold:
6339e605113SDmitri Gribenko assert(C->getNumArgs() == 1);
6349e605113SDmitri Gribenko Result << "<bold>";
6359e605113SDmitri Gribenko appendToResultWithXMLEscaping(Arg0);
6369e605113SDmitri Gribenko Result << "</bold>";
6379e605113SDmitri Gribenko return;
6389e605113SDmitri Gribenko case InlineCommandComment::RenderMonospaced:
6399e605113SDmitri Gribenko assert(C->getNumArgs() == 1);
6409e605113SDmitri Gribenko Result << "<monospaced>";
6419e605113SDmitri Gribenko appendToResultWithXMLEscaping(Arg0);
6429e605113SDmitri Gribenko Result << "</monospaced>";
6439e605113SDmitri Gribenko return;
6449e605113SDmitri Gribenko case InlineCommandComment::RenderEmphasized:
6459e605113SDmitri Gribenko assert(C->getNumArgs() == 1);
6469e605113SDmitri Gribenko Result << "<emphasized>";
6479e605113SDmitri Gribenko appendToResultWithXMLEscaping(Arg0);
6489e605113SDmitri Gribenko Result << "</emphasized>";
6499e605113SDmitri Gribenko return;
650be1a9b38SMark de Wever case InlineCommandComment::RenderAnchor:
651be1a9b38SMark de Wever assert(C->getNumArgs() == 1);
652be1a9b38SMark de Wever Result << "<anchor id=\"" << Arg0 << "\"></anchor>";
653be1a9b38SMark de Wever return;
6549e605113SDmitri Gribenko }
6559e605113SDmitri Gribenko }
6569e605113SDmitri Gribenko
visitHTMLStartTagComment(const HTMLStartTagComment * C)6579e605113SDmitri Gribenko void CommentASTToXMLConverter::visitHTMLStartTagComment(
6589e605113SDmitri Gribenko const HTMLStartTagComment *C) {
65993043620SDmitri Gribenko Result << "<rawHTML";
6600b2026deSDmitri Gribenko if (C->isMalformed())
6610b2026deSDmitri Gribenko Result << " isMalformed=\"1\"";
6626db07e2aSDmitri Gribenko Result << ">";
6636db07e2aSDmitri Gribenko {
6646db07e2aSDmitri Gribenko SmallString<32> Tag;
6656db07e2aSDmitri Gribenko {
6666db07e2aSDmitri Gribenko llvm::raw_svector_ostream TagOS(Tag);
6676db07e2aSDmitri Gribenko printHTMLStartTagComment(C, TagOS);
6686db07e2aSDmitri Gribenko }
6696db07e2aSDmitri Gribenko appendToResultWithCDATAEscaping(Tag);
6706db07e2aSDmitri Gribenko }
6716db07e2aSDmitri Gribenko Result << "</rawHTML>";
6729e605113SDmitri Gribenko }
6739e605113SDmitri Gribenko
6749e605113SDmitri Gribenko void
visitHTMLEndTagComment(const HTMLEndTagComment * C)6759e605113SDmitri Gribenko CommentASTToXMLConverter::visitHTMLEndTagComment(const HTMLEndTagComment *C) {
67693043620SDmitri Gribenko Result << "<rawHTML";
6770b2026deSDmitri Gribenko if (C->isMalformed())
6780b2026deSDmitri Gribenko Result << " isMalformed=\"1\"";
67993043620SDmitri Gribenko Result << "></" << C->getTagName() << "></rawHTML>";
6809e605113SDmitri Gribenko }
6819e605113SDmitri Gribenko
6829e605113SDmitri Gribenko void
visitParagraphComment(const ParagraphComment * C)6839e605113SDmitri Gribenko CommentASTToXMLConverter::visitParagraphComment(const ParagraphComment *C) {
6849e605113SDmitri Gribenko appendParagraphCommentWithKind(C, StringRef());
6859e605113SDmitri Gribenko }
6869e605113SDmitri Gribenko
appendParagraphCommentWithKind(const ParagraphComment * C,StringRef ParagraphKind)6879e605113SDmitri Gribenko void CommentASTToXMLConverter::appendParagraphCommentWithKind(
6889e605113SDmitri Gribenko const ParagraphComment *C,
6899e605113SDmitri Gribenko StringRef ParagraphKind) {
6909e605113SDmitri Gribenko if (C->isWhitespace())
6919e605113SDmitri Gribenko return;
6929e605113SDmitri Gribenko
6939e605113SDmitri Gribenko if (ParagraphKind.empty())
6949e605113SDmitri Gribenko Result << "<Para>";
6959e605113SDmitri Gribenko else
6969e605113SDmitri Gribenko Result << "<Para kind=\"" << ParagraphKind << "\">";
6979e605113SDmitri Gribenko
6989e605113SDmitri Gribenko for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
6999e605113SDmitri Gribenko I != E; ++I) {
7009e605113SDmitri Gribenko visit(*I);
7019e605113SDmitri Gribenko }
7029e605113SDmitri Gribenko Result << "</Para>";
7039e605113SDmitri Gribenko }
7049e605113SDmitri Gribenko
visitBlockCommandComment(const BlockCommandComment * C)7059e605113SDmitri Gribenko void CommentASTToXMLConverter::visitBlockCommandComment(
7069e605113SDmitri Gribenko const BlockCommandComment *C) {
7079e605113SDmitri Gribenko StringRef ParagraphKind;
7089e605113SDmitri Gribenko
7099e605113SDmitri Gribenko switch (C->getCommandID()) {
7109e605113SDmitri Gribenko case CommandTraits::KCI_attention:
7119e605113SDmitri Gribenko case CommandTraits::KCI_author:
7129e605113SDmitri Gribenko case CommandTraits::KCI_authors:
7139e605113SDmitri Gribenko case CommandTraits::KCI_bug:
7149e605113SDmitri Gribenko case CommandTraits::KCI_copyright:
7159e605113SDmitri Gribenko case CommandTraits::KCI_date:
7169e605113SDmitri Gribenko case CommandTraits::KCI_invariant:
7179e605113SDmitri Gribenko case CommandTraits::KCI_note:
7189e605113SDmitri Gribenko case CommandTraits::KCI_post:
7199e605113SDmitri Gribenko case CommandTraits::KCI_pre:
7209e605113SDmitri Gribenko case CommandTraits::KCI_remark:
7219e605113SDmitri Gribenko case CommandTraits::KCI_remarks:
7229e605113SDmitri Gribenko case CommandTraits::KCI_sa:
7239e605113SDmitri Gribenko case CommandTraits::KCI_see:
7249e605113SDmitri Gribenko case CommandTraits::KCI_since:
7259e605113SDmitri Gribenko case CommandTraits::KCI_todo:
7269e605113SDmitri Gribenko case CommandTraits::KCI_version:
7279e605113SDmitri Gribenko case CommandTraits::KCI_warning:
7289e605113SDmitri Gribenko ParagraphKind = C->getCommandName(Traits);
7294dc0b1acSReid Kleckner break;
7309e605113SDmitri Gribenko default:
7319e605113SDmitri Gribenko break;
7329e605113SDmitri Gribenko }
7339e605113SDmitri Gribenko
7349e605113SDmitri Gribenko appendParagraphCommentWithKind(C->getParagraph(), ParagraphKind);
7359e605113SDmitri Gribenko }
7369e605113SDmitri Gribenko
visitParamCommandComment(const ParamCommandComment * C)7379e605113SDmitri Gribenko void CommentASTToXMLConverter::visitParamCommandComment(
7389e605113SDmitri Gribenko const ParamCommandComment *C) {
7399e605113SDmitri Gribenko Result << "<Parameter><Name>";
7409e605113SDmitri Gribenko appendToResultWithXMLEscaping(C->isParamIndexValid()
7419e605113SDmitri Gribenko ? C->getParamName(FC)
7429e605113SDmitri Gribenko : C->getParamNameAsWritten());
7439e605113SDmitri Gribenko Result << "</Name>";
7449e605113SDmitri Gribenko
7459e605113SDmitri Gribenko if (C->isParamIndexValid()) {
7469e605113SDmitri Gribenko if (C->isVarArgParam())
7479e605113SDmitri Gribenko Result << "<IsVarArg />";
7489e605113SDmitri Gribenko else
7499e605113SDmitri Gribenko Result << "<Index>" << C->getParamIndex() << "</Index>";
7509e605113SDmitri Gribenko }
7519e605113SDmitri Gribenko
7529e605113SDmitri Gribenko Result << "<Direction isExplicit=\"" << C->isDirectionExplicit() << "\">";
7539e605113SDmitri Gribenko switch (C->getDirection()) {
7549e605113SDmitri Gribenko case ParamCommandComment::In:
7559e605113SDmitri Gribenko Result << "in";
7569e605113SDmitri Gribenko break;
7579e605113SDmitri Gribenko case ParamCommandComment::Out:
7589e605113SDmitri Gribenko Result << "out";
7599e605113SDmitri Gribenko break;
7609e605113SDmitri Gribenko case ParamCommandComment::InOut:
7619e605113SDmitri Gribenko Result << "in,out";
7629e605113SDmitri Gribenko break;
7639e605113SDmitri Gribenko }
7649e605113SDmitri Gribenko Result << "</Direction><Discussion>";
7659e605113SDmitri Gribenko visit(C->getParagraph());
7669e605113SDmitri Gribenko Result << "</Discussion></Parameter>";
7679e605113SDmitri Gribenko }
7689e605113SDmitri Gribenko
visitTParamCommandComment(const TParamCommandComment * C)7699e605113SDmitri Gribenko void CommentASTToXMLConverter::visitTParamCommandComment(
7709e605113SDmitri Gribenko const TParamCommandComment *C) {
7719e605113SDmitri Gribenko Result << "<Parameter><Name>";
7729e605113SDmitri Gribenko appendToResultWithXMLEscaping(C->isPositionValid() ? C->getParamName(FC)
7739e605113SDmitri Gribenko : C->getParamNameAsWritten());
7749e605113SDmitri Gribenko Result << "</Name>";
7759e605113SDmitri Gribenko
7769e605113SDmitri Gribenko if (C->isPositionValid() && C->getDepth() == 1) {
7779e605113SDmitri Gribenko Result << "<Index>" << C->getIndex(0) << "</Index>";
7789e605113SDmitri Gribenko }
7799e605113SDmitri Gribenko
7809e605113SDmitri Gribenko Result << "<Discussion>";
7819e605113SDmitri Gribenko visit(C->getParagraph());
7829e605113SDmitri Gribenko Result << "</Discussion></Parameter>";
7839e605113SDmitri Gribenko }
7849e605113SDmitri Gribenko
visitVerbatimBlockComment(const VerbatimBlockComment * C)7859e605113SDmitri Gribenko void CommentASTToXMLConverter::visitVerbatimBlockComment(
7869e605113SDmitri Gribenko const VerbatimBlockComment *C) {
7879e605113SDmitri Gribenko unsigned NumLines = C->getNumLines();
7889e605113SDmitri Gribenko if (NumLines == 0)
7899e605113SDmitri Gribenko return;
7909e605113SDmitri Gribenko
7919e605113SDmitri Gribenko switch (C->getCommandID()) {
7929e605113SDmitri Gribenko case CommandTraits::KCI_code:
7939e605113SDmitri Gribenko Result << "<Verbatim xml:space=\"preserve\" kind=\"code\">";
7949e605113SDmitri Gribenko break;
7959e605113SDmitri Gribenko default:
7969e605113SDmitri Gribenko Result << "<Verbatim xml:space=\"preserve\" kind=\"verbatim\">";
7979e605113SDmitri Gribenko break;
7989e605113SDmitri Gribenko }
7999e605113SDmitri Gribenko for (unsigned i = 0; i != NumLines; ++i) {
8009e605113SDmitri Gribenko appendToResultWithXMLEscaping(C->getText(i));
8019e605113SDmitri Gribenko if (i + 1 != NumLines)
8029e605113SDmitri Gribenko Result << '\n';
8039e605113SDmitri Gribenko }
8049e605113SDmitri Gribenko Result << "</Verbatim>";
8059e605113SDmitri Gribenko }
8069e605113SDmitri Gribenko
visitVerbatimBlockLineComment(const VerbatimBlockLineComment * C)8079e605113SDmitri Gribenko void CommentASTToXMLConverter::visitVerbatimBlockLineComment(
8089e605113SDmitri Gribenko const VerbatimBlockLineComment *C) {
8099e605113SDmitri Gribenko llvm_unreachable("should not see this AST node");
8109e605113SDmitri Gribenko }
8119e605113SDmitri Gribenko
visitVerbatimLineComment(const VerbatimLineComment * C)8129e605113SDmitri Gribenko void CommentASTToXMLConverter::visitVerbatimLineComment(
8139e605113SDmitri Gribenko const VerbatimLineComment *C) {
8149e605113SDmitri Gribenko Result << "<Verbatim xml:space=\"preserve\" kind=\"verbatim\">";
8159e605113SDmitri Gribenko appendToResultWithXMLEscaping(C->getText());
8169e605113SDmitri Gribenko Result << "</Verbatim>";
8179e605113SDmitri Gribenko }
8189e605113SDmitri Gribenko
visitFullComment(const FullComment * C)8199e605113SDmitri Gribenko void CommentASTToXMLConverter::visitFullComment(const FullComment *C) {
8209e605113SDmitri Gribenko FullCommentParts Parts(C, Traits);
8219e605113SDmitri Gribenko
8229e605113SDmitri Gribenko const DeclInfo *DI = C->getDeclInfo();
8239e605113SDmitri Gribenko StringRef RootEndTag;
8249e605113SDmitri Gribenko if (DI) {
8259e605113SDmitri Gribenko switch (DI->getKind()) {
8269e605113SDmitri Gribenko case DeclInfo::OtherKind:
8279e605113SDmitri Gribenko RootEndTag = "</Other>";
8289e605113SDmitri Gribenko Result << "<Other";
8299e605113SDmitri Gribenko break;
8309e605113SDmitri Gribenko case DeclInfo::FunctionKind:
8319e605113SDmitri Gribenko RootEndTag = "</Function>";
8329e605113SDmitri Gribenko Result << "<Function";
8339e605113SDmitri Gribenko switch (DI->TemplateKind) {
8349e605113SDmitri Gribenko case DeclInfo::NotTemplate:
8359e605113SDmitri Gribenko break;
8369e605113SDmitri Gribenko case DeclInfo::Template:
8379e605113SDmitri Gribenko Result << " templateKind=\"template\"";
8389e605113SDmitri Gribenko break;
8399e605113SDmitri Gribenko case DeclInfo::TemplateSpecialization:
8409e605113SDmitri Gribenko Result << " templateKind=\"specialization\"";
8419e605113SDmitri Gribenko break;
8429e605113SDmitri Gribenko case DeclInfo::TemplatePartialSpecialization:
8439e605113SDmitri Gribenko llvm_unreachable("partial specializations of functions "
8449e605113SDmitri Gribenko "are not allowed in C++");
8459e605113SDmitri Gribenko }
8469e605113SDmitri Gribenko if (DI->IsInstanceMethod)
8479e605113SDmitri Gribenko Result << " isInstanceMethod=\"1\"";
8489e605113SDmitri Gribenko if (DI->IsClassMethod)
8499e605113SDmitri Gribenko Result << " isClassMethod=\"1\"";
8509e605113SDmitri Gribenko break;
8519e605113SDmitri Gribenko case DeclInfo::ClassKind:
8529e605113SDmitri Gribenko RootEndTag = "</Class>";
8539e605113SDmitri Gribenko Result << "<Class";
8549e605113SDmitri Gribenko switch (DI->TemplateKind) {
8559e605113SDmitri Gribenko case DeclInfo::NotTemplate:
8569e605113SDmitri Gribenko break;
8579e605113SDmitri Gribenko case DeclInfo::Template:
8589e605113SDmitri Gribenko Result << " templateKind=\"template\"";
8599e605113SDmitri Gribenko break;
8609e605113SDmitri Gribenko case DeclInfo::TemplateSpecialization:
8619e605113SDmitri Gribenko Result << " templateKind=\"specialization\"";
8629e605113SDmitri Gribenko break;
8639e605113SDmitri Gribenko case DeclInfo::TemplatePartialSpecialization:
8649e605113SDmitri Gribenko Result << " templateKind=\"partialSpecialization\"";
8659e605113SDmitri Gribenko break;
8669e605113SDmitri Gribenko }
8679e605113SDmitri Gribenko break;
8689e605113SDmitri Gribenko case DeclInfo::VariableKind:
8699e605113SDmitri Gribenko RootEndTag = "</Variable>";
8709e605113SDmitri Gribenko Result << "<Variable";
8719e605113SDmitri Gribenko break;
8729e605113SDmitri Gribenko case DeclInfo::NamespaceKind:
8739e605113SDmitri Gribenko RootEndTag = "</Namespace>";
8749e605113SDmitri Gribenko Result << "<Namespace";
8759e605113SDmitri Gribenko break;
8769e605113SDmitri Gribenko case DeclInfo::TypedefKind:
8779e605113SDmitri Gribenko RootEndTag = "</Typedef>";
8789e605113SDmitri Gribenko Result << "<Typedef";
8799e605113SDmitri Gribenko break;
8809e605113SDmitri Gribenko case DeclInfo::EnumKind:
8819e605113SDmitri Gribenko RootEndTag = "</Enum>";
8829e605113SDmitri Gribenko Result << "<Enum";
8839e605113SDmitri Gribenko break;
8849e605113SDmitri Gribenko }
8859e605113SDmitri Gribenko
8869e605113SDmitri Gribenko {
8879e605113SDmitri Gribenko // Print line and column number.
8889e605113SDmitri Gribenko SourceLocation Loc = DI->CurrentDecl->getLocation();
8899e605113SDmitri Gribenko std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
8909e605113SDmitri Gribenko FileID FID = LocInfo.first;
8919e605113SDmitri Gribenko unsigned FileOffset = LocInfo.second;
8929e605113SDmitri Gribenko
8938b563665SYaron Keren if (FID.isValid()) {
8949e605113SDmitri Gribenko if (const FileEntry *FE = SM.getFileEntryForID(FID)) {
8959e605113SDmitri Gribenko Result << " file=\"";
8969e605113SDmitri Gribenko appendToResultWithXMLEscaping(FE->getName());
8979e605113SDmitri Gribenko Result << "\"";
8989e605113SDmitri Gribenko }
8999e605113SDmitri Gribenko Result << " line=\"" << SM.getLineNumber(FID, FileOffset)
9009e605113SDmitri Gribenko << "\" column=\"" << SM.getColumnNumber(FID, FileOffset)
9019e605113SDmitri Gribenko << "\"";
9029e605113SDmitri Gribenko }
9039e605113SDmitri Gribenko }
9049e605113SDmitri Gribenko
9059e605113SDmitri Gribenko // Finish the root tag.
9069e605113SDmitri Gribenko Result << ">";
9079e605113SDmitri Gribenko
9089e605113SDmitri Gribenko bool FoundName = false;
9099e605113SDmitri Gribenko if (const NamedDecl *ND = dyn_cast<NamedDecl>(DI->CommentDecl)) {
9109e605113SDmitri Gribenko if (DeclarationName DeclName = ND->getDeclName()) {
9119e605113SDmitri Gribenko Result << "<Name>";
9129e605113SDmitri Gribenko std::string Name = DeclName.getAsString();
9139e605113SDmitri Gribenko appendToResultWithXMLEscaping(Name);
9149e605113SDmitri Gribenko FoundName = true;
9159e605113SDmitri Gribenko Result << "</Name>";
9169e605113SDmitri Gribenko }
9179e605113SDmitri Gribenko }
9189e605113SDmitri Gribenko if (!FoundName)
9199e605113SDmitri Gribenko Result << "<Name><anonymous></Name>";
9209e605113SDmitri Gribenko
9219e605113SDmitri Gribenko {
9229e605113SDmitri Gribenko // Print USR.
9239e605113SDmitri Gribenko SmallString<128> USR;
9249e605113SDmitri Gribenko generateUSRForDecl(DI->CommentDecl, USR);
9259e605113SDmitri Gribenko if (!USR.empty()) {
9269e605113SDmitri Gribenko Result << "<USR>";
9279e605113SDmitri Gribenko appendToResultWithXMLEscaping(USR);
9289e605113SDmitri Gribenko Result << "</USR>";
9299e605113SDmitri Gribenko }
9309e605113SDmitri Gribenko }
9319e605113SDmitri Gribenko } else {
9329e605113SDmitri Gribenko // No DeclInfo -- just emit some root tag and name tag.
9339e605113SDmitri Gribenko RootEndTag = "</Other>";
9349e605113SDmitri Gribenko Result << "<Other><Name>unknown</Name>";
9359e605113SDmitri Gribenko }
9369e605113SDmitri Gribenko
9379e605113SDmitri Gribenko if (Parts.Headerfile) {
9389e605113SDmitri Gribenko Result << "<Headerfile>";
9399e605113SDmitri Gribenko visit(Parts.Headerfile);
9409e605113SDmitri Gribenko Result << "</Headerfile>";
9419e605113SDmitri Gribenko }
9429e605113SDmitri Gribenko
9439e605113SDmitri Gribenko {
9449e605113SDmitri Gribenko // Pretty-print the declaration.
9459e605113SDmitri Gribenko Result << "<Declaration>";
9469e605113SDmitri Gribenko SmallString<128> Declaration;
9479e605113SDmitri Gribenko getSourceTextOfDeclaration(DI, Declaration);
9489e605113SDmitri Gribenko formatTextOfDeclaration(DI, Declaration);
9499e605113SDmitri Gribenko appendToResultWithXMLEscaping(Declaration);
9509e605113SDmitri Gribenko Result << "</Declaration>";
9519e605113SDmitri Gribenko }
9529e605113SDmitri Gribenko
9539e605113SDmitri Gribenko bool FirstParagraphIsBrief = false;
9549e605113SDmitri Gribenko if (Parts.Brief) {
9559e605113SDmitri Gribenko Result << "<Abstract>";
9569e605113SDmitri Gribenko visit(Parts.Brief);
9579e605113SDmitri Gribenko Result << "</Abstract>";
9589e605113SDmitri Gribenko } else if (Parts.FirstParagraph) {
9599e605113SDmitri Gribenko Result << "<Abstract>";
9609e605113SDmitri Gribenko visit(Parts.FirstParagraph);
9619e605113SDmitri Gribenko Result << "</Abstract>";
9629e605113SDmitri Gribenko FirstParagraphIsBrief = true;
9639e605113SDmitri Gribenko }
9649e605113SDmitri Gribenko
9659e605113SDmitri Gribenko if (Parts.TParams.size() != 0) {
9669e605113SDmitri Gribenko Result << "<TemplateParameters>";
9679e605113SDmitri Gribenko for (unsigned i = 0, e = Parts.TParams.size(); i != e; ++i)
9689e605113SDmitri Gribenko visit(Parts.TParams[i]);
9699e605113SDmitri Gribenko Result << "</TemplateParameters>";
9709e605113SDmitri Gribenko }
9719e605113SDmitri Gribenko
9729e605113SDmitri Gribenko if (Parts.Params.size() != 0) {
9739e605113SDmitri Gribenko Result << "<Parameters>";
9749e605113SDmitri Gribenko for (unsigned i = 0, e = Parts.Params.size(); i != e; ++i)
9759e605113SDmitri Gribenko visit(Parts.Params[i]);
9769e605113SDmitri Gribenko Result << "</Parameters>";
9779e605113SDmitri Gribenko }
9789e605113SDmitri Gribenko
9799e605113SDmitri Gribenko if (Parts.Exceptions.size() != 0) {
9809e605113SDmitri Gribenko Result << "<Exceptions>";
9819e605113SDmitri Gribenko for (unsigned i = 0, e = Parts.Exceptions.size(); i != e; ++i)
9829e605113SDmitri Gribenko visit(Parts.Exceptions[i]);
9839e605113SDmitri Gribenko Result << "</Exceptions>";
9849e605113SDmitri Gribenko }
9859e605113SDmitri Gribenko
9869e605113SDmitri Gribenko if (Parts.Returns.size() != 0) {
9879e605113SDmitri Gribenko Result << "<ResultDiscussion>";
9889e605113SDmitri Gribenko for (unsigned i = 0, e = Parts.Returns.size(); i != e; ++i)
9899e605113SDmitri Gribenko visit(Parts.Returns[i]);
9909e605113SDmitri Gribenko Result << "</ResultDiscussion>";
9919e605113SDmitri Gribenko }
9929e605113SDmitri Gribenko
9939e605113SDmitri Gribenko if (DI->CommentDecl->hasAttrs()) {
9949e605113SDmitri Gribenko const AttrVec &Attrs = DI->CommentDecl->getAttrs();
9959e605113SDmitri Gribenko for (unsigned i = 0, e = Attrs.size(); i != e; i++) {
9969e605113SDmitri Gribenko const AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(Attrs[i]);
9979e605113SDmitri Gribenko if (!AA) {
9989e605113SDmitri Gribenko if (const DeprecatedAttr *DA = dyn_cast<DeprecatedAttr>(Attrs[i])) {
9999e605113SDmitri Gribenko if (DA->getMessage().empty())
10009e605113SDmitri Gribenko Result << "<Deprecated/>";
10019e605113SDmitri Gribenko else {
10029e605113SDmitri Gribenko Result << "<Deprecated>";
10039e605113SDmitri Gribenko appendToResultWithXMLEscaping(DA->getMessage());
10049e605113SDmitri Gribenko Result << "</Deprecated>";
10059e605113SDmitri Gribenko }
10069e605113SDmitri Gribenko }
10079e605113SDmitri Gribenko else if (const UnavailableAttr *UA = dyn_cast<UnavailableAttr>(Attrs[i])) {
10089e605113SDmitri Gribenko if (UA->getMessage().empty())
10099e605113SDmitri Gribenko Result << "<Unavailable/>";
10109e605113SDmitri Gribenko else {
10119e605113SDmitri Gribenko Result << "<Unavailable>";
10129e605113SDmitri Gribenko appendToResultWithXMLEscaping(UA->getMessage());
10139e605113SDmitri Gribenko Result << "</Unavailable>";
10149e605113SDmitri Gribenko }
10159e605113SDmitri Gribenko }
10169e605113SDmitri Gribenko continue;
10179e605113SDmitri Gribenko }
10189e605113SDmitri Gribenko
10199e605113SDmitri Gribenko // 'availability' attribute.
10209e605113SDmitri Gribenko Result << "<Availability";
10219e605113SDmitri Gribenko StringRef Distribution;
10229e605113SDmitri Gribenko if (AA->getPlatform()) {
10239e605113SDmitri Gribenko Distribution = AvailabilityAttr::getPrettyPlatformName(
10249e605113SDmitri Gribenko AA->getPlatform()->getName());
10259e605113SDmitri Gribenko if (Distribution.empty())
10269e605113SDmitri Gribenko Distribution = AA->getPlatform()->getName();
10279e605113SDmitri Gribenko }
10289e605113SDmitri Gribenko Result << " distribution=\"" << Distribution << "\">";
10299e605113SDmitri Gribenko VersionTuple IntroducedInVersion = AA->getIntroduced();
10309e605113SDmitri Gribenko if (!IntroducedInVersion.empty()) {
10319e605113SDmitri Gribenko Result << "<IntroducedInVersion>"
10329e605113SDmitri Gribenko << IntroducedInVersion.getAsString()
10339e605113SDmitri Gribenko << "</IntroducedInVersion>";
10349e605113SDmitri Gribenko }
10359e605113SDmitri Gribenko VersionTuple DeprecatedInVersion = AA->getDeprecated();
10369e605113SDmitri Gribenko if (!DeprecatedInVersion.empty()) {
10379e605113SDmitri Gribenko Result << "<DeprecatedInVersion>"
10389e605113SDmitri Gribenko << DeprecatedInVersion.getAsString()
10399e605113SDmitri Gribenko << "</DeprecatedInVersion>";
10409e605113SDmitri Gribenko }
10419e605113SDmitri Gribenko VersionTuple RemovedAfterVersion = AA->getObsoleted();
10429e605113SDmitri Gribenko if (!RemovedAfterVersion.empty()) {
10439e605113SDmitri Gribenko Result << "<RemovedAfterVersion>"
10449e605113SDmitri Gribenko << RemovedAfterVersion.getAsString()
10459e605113SDmitri Gribenko << "</RemovedAfterVersion>";
10469e605113SDmitri Gribenko }
10479e605113SDmitri Gribenko StringRef DeprecationSummary = AA->getMessage();
10489e605113SDmitri Gribenko if (!DeprecationSummary.empty()) {
10499e605113SDmitri Gribenko Result << "<DeprecationSummary>";
10509e605113SDmitri Gribenko appendToResultWithXMLEscaping(DeprecationSummary);
10519e605113SDmitri Gribenko Result << "</DeprecationSummary>";
10529e605113SDmitri Gribenko }
10539e605113SDmitri Gribenko if (AA->getUnavailable())
10549e605113SDmitri Gribenko Result << "<Unavailable/>";
10559e605113SDmitri Gribenko Result << "</Availability>";
10569e605113SDmitri Gribenko }
10579e605113SDmitri Gribenko }
10589e605113SDmitri Gribenko
10599e605113SDmitri Gribenko {
10609e605113SDmitri Gribenko bool StartTagEmitted = false;
10619e605113SDmitri Gribenko for (unsigned i = 0, e = Parts.MiscBlocks.size(); i != e; ++i) {
10629e605113SDmitri Gribenko const Comment *C = Parts.MiscBlocks[i];
10639e605113SDmitri Gribenko if (FirstParagraphIsBrief && C == Parts.FirstParagraph)
10649e605113SDmitri Gribenko continue;
10659e605113SDmitri Gribenko if (!StartTagEmitted) {
10669e605113SDmitri Gribenko Result << "<Discussion>";
10679e605113SDmitri Gribenko StartTagEmitted = true;
10689e605113SDmitri Gribenko }
10699e605113SDmitri Gribenko visit(C);
10709e605113SDmitri Gribenko }
10719e605113SDmitri Gribenko if (StartTagEmitted)
10729e605113SDmitri Gribenko Result << "</Discussion>";
10739e605113SDmitri Gribenko }
10749e605113SDmitri Gribenko
10759e605113SDmitri Gribenko Result << RootEndTag;
10769e605113SDmitri Gribenko }
10779e605113SDmitri Gribenko
appendToResultWithXMLEscaping(StringRef S)10789e605113SDmitri Gribenko void CommentASTToXMLConverter::appendToResultWithXMLEscaping(StringRef S) {
10799e605113SDmitri Gribenko for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I) {
10809e605113SDmitri Gribenko const char C = *I;
10819e605113SDmitri Gribenko switch (C) {
10829e605113SDmitri Gribenko case '&':
10839e605113SDmitri Gribenko Result << "&";
10849e605113SDmitri Gribenko break;
10859e605113SDmitri Gribenko case '<':
10869e605113SDmitri Gribenko Result << "<";
10879e605113SDmitri Gribenko break;
10889e605113SDmitri Gribenko case '>':
10899e605113SDmitri Gribenko Result << ">";
10909e605113SDmitri Gribenko break;
10919e605113SDmitri Gribenko case '"':
10929e605113SDmitri Gribenko Result << """;
10939e605113SDmitri Gribenko break;
10949e605113SDmitri Gribenko case '\'':
10959e605113SDmitri Gribenko Result << "'";
10969e605113SDmitri Gribenko break;
10979e605113SDmitri Gribenko default:
10989e605113SDmitri Gribenko Result << C;
10999e605113SDmitri Gribenko break;
11009e605113SDmitri Gribenko }
11019e605113SDmitri Gribenko }
11029e605113SDmitri Gribenko }
11039e605113SDmitri Gribenko
appendToResultWithCDATAEscaping(StringRef S)11046db07e2aSDmitri Gribenko void CommentASTToXMLConverter::appendToResultWithCDATAEscaping(StringRef S) {
11056db07e2aSDmitri Gribenko if (S.empty())
11066db07e2aSDmitri Gribenko return;
11076db07e2aSDmitri Gribenko
11086db07e2aSDmitri Gribenko Result << "<![CDATA[";
11096db07e2aSDmitri Gribenko while (!S.empty()) {
11106db07e2aSDmitri Gribenko size_t Pos = S.find("]]>");
11116db07e2aSDmitri Gribenko if (Pos == 0) {
11126db07e2aSDmitri Gribenko Result << "]]]]><![CDATA[>";
11136db07e2aSDmitri Gribenko S = S.drop_front(3);
11146db07e2aSDmitri Gribenko continue;
11156db07e2aSDmitri Gribenko }
11166db07e2aSDmitri Gribenko if (Pos == StringRef::npos)
11176db07e2aSDmitri Gribenko Pos = S.size();
11186db07e2aSDmitri Gribenko
11196db07e2aSDmitri Gribenko Result << S.substr(0, Pos);
11206db07e2aSDmitri Gribenko
11216db07e2aSDmitri Gribenko S = S.drop_front(Pos);
11226db07e2aSDmitri Gribenko }
11236db07e2aSDmitri Gribenko Result << "]]>";
11246db07e2aSDmitri Gribenko }
11256db07e2aSDmitri Gribenko
CommentToXMLConverter()1126d21485d2SDaniel Jasper CommentToXMLConverter::CommentToXMLConverter() {}
~CommentToXMLConverter()1127637d1e66SAngel Garcia Gomez CommentToXMLConverter::~CommentToXMLConverter() {}
1128795f6a9dSNico Weber
convertCommentToHTML(const FullComment * FC,SmallVectorImpl<char> & HTML,const ASTContext & Context)11299e605113SDmitri Gribenko void CommentToXMLConverter::convertCommentToHTML(const FullComment *FC,
11309e605113SDmitri Gribenko SmallVectorImpl<char> &HTML,
11319e605113SDmitri Gribenko const ASTContext &Context) {
11329e605113SDmitri Gribenko CommentASTToHTMLConverter Converter(FC, HTML,
11339e605113SDmitri Gribenko Context.getCommentCommandTraits());
11349e605113SDmitri Gribenko Converter.visit(FC);
11359e605113SDmitri Gribenko }
11369e605113SDmitri Gribenko
convertHTMLTagNodeToText(const comments::HTMLTagComment * HTC,SmallVectorImpl<char> & Text,const ASTContext & Context)11379e605113SDmitri Gribenko void CommentToXMLConverter::convertHTMLTagNodeToText(
11389e605113SDmitri Gribenko const comments::HTMLTagComment *HTC, SmallVectorImpl<char> &Text,
11399e605113SDmitri Gribenko const ASTContext &Context) {
1140236bde3dSCraig Topper CommentASTToHTMLConverter Converter(nullptr, Text,
11419e605113SDmitri Gribenko Context.getCommentCommandTraits());
11429e605113SDmitri Gribenko Converter.visit(HTC);
11439e605113SDmitri Gribenko }
11449e605113SDmitri Gribenko
convertCommentToXML(const FullComment * FC,SmallVectorImpl<char> & XML,const ASTContext & Context)11459e605113SDmitri Gribenko void CommentToXMLConverter::convertCommentToXML(const FullComment *FC,
11469e605113SDmitri Gribenko SmallVectorImpl<char> &XML,
11479e605113SDmitri Gribenko const ASTContext &Context) {
11489e605113SDmitri Gribenko CommentASTToXMLConverter Converter(FC, XML, Context.getCommentCommandTraits(),
1149d21485d2SDaniel Jasper Context.getSourceManager());
11509e605113SDmitri Gribenko Converter.visit(FC);
11519e605113SDmitri Gribenko }
1152