(N)); break; case ASTNodeKind::TextAndInline: printTextAndInline(cast(N)); break; case ASTNodeKind::PlainText: printPlainText(cast (N)); break; case ASTNodeKind::Emphasis: printEmphasis(cast (N)); break; case ASTNodeKind::StrongEmphasis: printStrongEmphasis(cast (N)); break; case ASTNodeKind::InterpretedText: printInterpretedText(cast (N)); break; case ASTNodeKind::InlineLiteral: printInlineLiteral(cast (N)); break; case ASTNodeKind::HyperlinkReference: printHyperlinkReference(cast (N)); break; case ASTNodeKind::InlineHyperlinkTarget: printInlineHyperlinkTarget(cast (N)); break; case ASTNodeKind::FootnoteReference: printFootnoteReference(cast (N)); break; case ASTNodeKind::CitationReference: printCitationReference(cast (N)); break; case ASTNodeKind::SubstitutionReference: printSubstitutionReference(cast (N)); break; case ASTNodeKind::PrivateExtension: llvm_unreachable("implement"); } } void printParagraph(const Paragraph *P) { printTextAndInline(P->getContent()); } void printBulletList(const BulletList *BL) { printRawHTML(" "); for (unsigned i = 0, e = BL->getNumItems(); i != e; ++i) { printRawHTML("
"); } void printEnumeratedList(const EnumeratedList *EL) { printRawHTML("- "); for (const auto *N : BL->getItemChildren(i)) { printASTNode(N); } printRawHTML("
"); } printRawHTML(""); for (unsigned i = 0, e = EL->getNumItems(); i != e; ++i) { printRawHTML("
"); } void printDefinitionListItem(const DefinitionListItem *DLI) { printRawHTML("- "); for (const auto *N : EL->getItemChildren(i)) { printASTNode(N); } printRawHTML("
"); } printRawHTML(""); printASTNode(DLI->getTerm()); printRawHTML(" "); for (const auto *N : DLI->getClassifiers()) { printASTNode(N); } printRawHTML(""); for (const auto *N : DLI->getDefinitionChildren()) { printASTNode(N); } printRawHTML(" "); } void printDefinitionList(const DefinitionList *DL) { printRawHTML(""); for (const auto *N : DL->getChildren()) { printASTNode(N); } printRawHTML("
"); } void printField(const Field *F) { printRawHTML(""); printASTNode(F->getName()); printRawHTML(" "); printRawHTML(""); for (const auto *N : F->getBodyChildren()) { printASTNode(N); } printRawHTML(" "); } void printFieldList(const FieldList *FL) { printRawHTML(""); for (const auto *F : FL->getChildren()) { printASTNode(F); } printRawHTML("
"); } void printBlockQuote(const BlockQuote *BQ) { printRawHTML(""); for (const auto *N : BQ->getChildren()) { printASTNode(N); } printRawHTML(""); } void printTextAndInline(const TextAndInline *T) { for (const auto *IC : T->getChildren()) { printASTNode(IC); } } void printPlainText(const PlainText *PT) { appendWithXMLEscaping(OS, PT->getLinePart().Text); } void printEmphasis(const Emphasis *E) { printRawHTML(""); for (const auto *IC : E->getChildren()) { printASTNode(IC); } printRawHTML(""); } void printStrongEmphasis(const StrongEmphasis *SE) { printRawHTML(""); for (const auto *IC : SE->getChildren()) { printASTNode(IC); } printRawHTML(""); } void printInterpretedText(const InterpretedText *IT) { // FIXME: check role. printRawHTML(""); for (const auto *IC : IT->getChildren()) { printASTNode(IC); } printRawHTML(""); } void printInlineLiteral(const InlineLiteral *IL) { printRawHTML(""); for (const auto *IC : IL->getChildren()) { printASTNode(IC); } printRawHTML(""); } void printHyperlinkReference(const HyperlinkReference *HR) { // FIXME: print as a hyperlink. for (const auto *IC : HR->getChildren()) { printASTNode(IC); } } void printInlineHyperlinkTarget(const InlineHyperlinkTarget *IHT) { // FIXME: print link anchor. for (const auto *IC : IHT->getChildren()) { printASTNode(IC); } } void printFootnoteReference(const FootnoteReference *FR) { // FIXME: XML format does not support footnotes. Skip them for now. } void printCitationReference(const CitationReference *CR) { // FIXME: XML format does not support citations. Skip them for now. } void printSubstitutionReference(const SubstitutionReference *SR) { // FIXME: we don't resolve substitutions yet. } void printOrphanField(const Field *F) { printRawHTML(""); printField(F); printRawHTML("
"); } void printAsParameter(const comments::ParamField *PF) { OS << ""; } void printAsReturns(const Field *F) { for (const auto *N : F->getBodyChildren()) { printASTNode(N); } } void visitFullComment(const FullComment *FC); }; } // unnamed namespace void CommentToXMLConverter::visitFullComment(const FullComment *FC) { const Decl *D = FC->getDecl(); const auto &Parts = FC->getParts(TheCommentContext); StringRef RootEndTag; if (isa "; OS << PF->getParamName().Text; OS << " in "; for (const auto *N : PF->getBodyChildren()) { OS << " "; printASTNode(N); OS << " "; } OS << "(D)) { OS << " (D) || isa (D) || isa (D)) { OS << " getLoc(); if (Loc.isValid()) { const auto &SM = D->getASTContext().SourceMgr; unsigned BufferID = SM.findBufferContainingLoc(Loc); StringRef FileName = SM.getIdentifierForBuffer(BufferID); auto LineAndColumn = SM.getLineAndColumn(Loc); OS << " file=\""; appendWithXMLEscaping(OS, FileName); OS << "\""; OS << " line=\"" << LineAndColumn.first << "\" column=\"" << LineAndColumn.second << "\""; } } // Finish the root tag. OS << ">"; auto *VD = dyn_cast (D); OS << " "; if (VD && VD->hasName()) OS << VD->getFullName(); OS << " "; if (VD) { llvm::SmallString<64> SS; bool Failed; { llvm::raw_svector_ostream OS(SS); Failed = ide::printDeclUSR(VD, OS); } if (!Failed && !SS.empty()) { OS << "" << SS << " "; } } { PrintOptions PO; PO.PrintDefaultParameterPlaceholder = true; PO.SkipImplicit = true; PO.PrintImplicitAttrs = false; PO.PrintFunctionRepresentationAttrs = false; OS << ""; llvm::SmallString<32> DeclSS; { llvm::raw_svector_ostream DeclOS(DeclSS); D->print(DeclOS, PO); } appendWithXMLEscaping(OS, DeclSS); OS << " "; } if (Parts.Brief) { OS << ""; OS << " "; } if (!Parts.MiscTopLevelNodes.empty()) { OS << ""; printASTNode(Parts.Brief); OS << " "; OS << ""; for (const auto *N : Parts.MiscTopLevelNodes) { OS << " "; } if (!Parts.Params.empty()) { OS << ""; if (const auto *F = dyn_cast "; continue; } printASTNode(N); OS << ""; } OS << "(N)) { printOrphanField(F); OS << " "; for (const auto *N : Parts.Params) { printAsParameter(N); } OS << " "; } if (!Parts.Returns.empty()) { OS << ""; for (const auto *N : Parts.Returns) { OS << " "; } OS << RootEndTag; } static bool getClangDocumentationCommentAsXML(const clang::Decl *D, raw_ostream &OS) { const auto &ClangContext = D->getASTContext(); const clang::comments::FullComment *FC = ClangContext.getCommentForDecl(D, /*PP=*/nullptr); if (!FC) return false; // FIXME: hang the converter object somewhere so that it is persistent // between requests to this AST. clang::index::CommentToXMLConverter Converter; llvm::SmallString<1024> XML; Converter.convertCommentToXML(FC, XML, ClangContext); OS << XML; return true; } bool ide::getDocumentationCommentAsXML(const Decl *D, raw_ostream &OS) { auto MaybeClangNode = D->getClangNode(); if (MaybeClangNode) { if (auto *CD = MaybeClangNode.getAsDecl()) return getClangDocumentationCommentAsXML(CD, OS); return false; } CommentContext TheCommentContext; auto *FC = getFullComment(TheCommentContext, D); if (!FC) return false; CommentToXMLConverter Converter(TheCommentContext, OS); Converter.visitFullComment(FC); OS.flush(); return true; } //===----------------------------------------------------------------------===// // Conversion to Doxygen. //===----------------------------------------------------------------------===// namespace { struct CommentToDoxygenConverter { CommentContext &TheCommentContext; raw_ostream &OS; unsigned PendingNewlines = 1; CommentToDoxygenConverter(CommentContext &TheCommentContext, raw_ostream &OS) : TheCommentContext(TheCommentContext), OS(OS) {} void print(StringRef Text) { for (unsigned i = 0; i != PendingNewlines; ++i) { OS << "\n///"; if (i == PendingNewlines - 1) OS << " "; } PendingNewlines = 0; OS << Text; } void printNewline() { PendingNewlines++; } void printASTNode(const ReSTASTNode *N) { switch (N->getKind()) { case ASTNodeKind::Document: llvm_unreachable("should never happen"); break; case ASTNodeKind::Section: case ASTNodeKind::Topic: case ASTNodeKind::Sidebar: case ASTNodeKind::Title: case ASTNodeKind::Subtitle: case ASTNodeKind::Transition: llvm_unreachable("implement"); case ASTNodeKind::Paragraph: printParagraph(cast"; printAsReturns(N); OS << " "; } OS << "(N)); break; case ASTNodeKind::BulletList: printBulletList(cast (N)); break; case ASTNodeKind::EnumeratedList: printEnumeratedList(cast (N)); break; case ASTNodeKind::DefinitionListItem: printDefinitionListItem(cast (N)); break; case ASTNodeKind::DefinitionList: printDefinitionList(cast (N)); break; case ASTNodeKind::Field: printField(cast (N)); break; case ASTNodeKind::FieldList: printFieldList(cast (N)); break; case ASTNodeKind::BlockQuote: printBlockQuote(cast (N)); break; case ASTNodeKind::TextAndInline: printTextAndInline(cast(N)); break; case ASTNodeKind::PlainText: printPlainText(cast (N)); break; case ASTNodeKind::Emphasis: printEmphasis(cast (N)); break; case ASTNodeKind::StrongEmphasis: printStrongEmphasis(cast (N)); break; case ASTNodeKind::InterpretedText: printInterpretedText(cast (N)); break; case ASTNodeKind::InlineLiteral: printInlineLiteral(cast (N)); break; case ASTNodeKind::HyperlinkReference: printHyperlinkReference(cast (N)); break; case ASTNodeKind::InlineHyperlinkTarget: printInlineHyperlinkTarget(cast (N)); break; case ASTNodeKind::FootnoteReference: printFootnoteReference(cast (N)); break; case ASTNodeKind::CitationReference: printCitationReference(cast (N)); break; case ASTNodeKind::SubstitutionReference: printSubstitutionReference(cast (N)); break; case ASTNodeKind::PrivateExtension: llvm_unreachable("implement"); } } void printParagraph(const Paragraph *P) { print(" "); printTextAndInline(P->getContent()); print("
"); } void printBulletList(const BulletList *BL) { print(""); for (unsigned i = 0, e = BL->getNumItems(); i != e; ++i) { print("
"); } void printEnumeratedList(const EnumeratedList *EL) { print("- "); for (const auto *N : BL->getItemChildren(i)) { printASTNode(N); } print("
"); } print(""); for (unsigned i = 0, e = EL->getNumItems(); i != e; ++i) { print("
"); } void printDefinitionListItem(const DefinitionListItem *DLI) { print("- "); for (const auto *N : EL->getItemChildren(i)) { printASTNode(N); } print("
"); } print(""); printASTNode(DLI->getTerm()); for (const auto *N : DLI->getClassifiers()) { printASTNode(N); } print(" "); print(""); for (const auto *N : DLI->getDefinitionChildren()) { printASTNode(N); } print(" "); } void printDefinitionList(const DefinitionList *DL) { print(""); for (const auto *N : DL->getChildren()) { printASTNode(N); } print("
"); } void printField(const Field *F) { print(""); printASTNode(F->getName()); print(" "); print(""); for (const auto *N : F->getBodyChildren()) { printASTNode(N); } print(" "); } void printFieldList(const FieldList *FL) { print(""); for (const auto *F : FL->getChildren()) { printASTNode(F); } print("
"); } void printBlockQuote(const BlockQuote *BQ) { print(""); for (const auto *N : BQ->getChildren()) { printASTNode(N); } print(""); } void printTextAndInline(const TextAndInline *T) { for (const auto *IC : T->getChildren()) { printASTNode(IC); } } void printPlainText(const PlainText *PT) { if (PT->getLinePart().Text == "\n") printNewline(); else print(PT->getLinePart().Text); } void printEmphasis(const Emphasis *E) { print(""); for (const auto *IC : E->getChildren()) { printASTNode(IC); } print(""); } void printStrongEmphasis(const StrongEmphasis *SE) { print(""); for (const auto *IC : SE->getChildren()) { printASTNode(IC); } print(""); } void printInterpretedText(const InterpretedText *IT) { // FIXME: check role. print(""); for (const auto *IC : IT->getChildren()) { printASTNode(IC); } print(""); } void printInlineLiteral(const InlineLiteral *IL) { print(""); for (const auto *IC : IL->getChildren()) { printASTNode(IC); } print(""); } void printHyperlinkReference(const HyperlinkReference *HR) { // FIXME: print as a hyperlink. for (const auto *IC : HR->getChildren()) { printASTNode(IC); } } void printInlineHyperlinkTarget(const InlineHyperlinkTarget *IHT) { // FIXME: print link anchor. for (const auto *IC : IHT->getChildren()) { printASTNode(IC); } } void printFootnoteReference(const FootnoteReference *FR) { // Doxygen does not support footnotes. } void printCitationReference(const CitationReference *CR) { // Doxygen does not support citations. } void printSubstitutionReference(const SubstitutionReference *SR) { // FIXME: we don't resolve substitutions yet. } void printOrphanField(const Field *F) { print(""); printField(F); print("
"); } void printBlockCommandContent(ArrayRefNodes) { if (Nodes.size() == 0) return; print(" "); if (Nodes.size() == 1) { if (const auto *P = dyn_cast (Nodes[0])) { printTextAndInline(P->getContent()); return; } } for (const auto *N : Nodes) { printASTNode(N); } } void printAsDoxygenParam(const comments::ParamField *PF) { print("\\param "); print(PF->getParamName().Text); printBlockCommandContent(PF->getBodyChildren()); printNewline(); } void printAsDoxygenReturns(const Field *F) { print("\\returns"); printBlockCommandContent(F->getBodyChildren()); printNewline(); } }; } // unnamed namespace void ide::getDocumentationCommentAsDoxygen(CommentContext &TheCommentContext, const FullComment *FC, raw_ostream &OS) { CommentToDoxygenConverter Converter(TheCommentContext, OS); const auto &Parts = FC->getParts(TheCommentContext); if (Parts.Brief) { Converter.printTextAndInline(Parts.Brief->getContent()); Converter.printNewline(); Converter.printNewline(); } for (const auto *N : Parts.MiscTopLevelNodes) { if (const auto *F = dyn_cast (N)) { Converter.printOrphanField(F); Converter.printNewline(); continue; } if (const auto *P = dyn_cast (N)) { Converter.printTextAndInline(P->getContent()); Converter.printNewline(); Converter.printNewline(); continue; } Converter.printASTNode(N); Converter.printNewline(); } for (const auto *N : Parts.Params) { Converter.printAsDoxygenParam(N); Converter.printNewline(); } for (const auto *N : Parts.Returns) { Converter.printAsDoxygenReturns(N); Converter.printNewline(); } if (Converter.PendingNewlines != 0) OS << "\n"; }