18#include "llvm/ADT/StringExtras.h"
19#include "llvm/ADT/TinyPtrVector.h"
20#include "llvm/Support/raw_ostream.h"
30class ParamCommandCommentCompareIndex {
49 return LHSIndex < RHSIndex;
57class TParamCommandCommentComparePosition {
82struct FullCommentParts {
93 llvm::TinyPtrVector<const BlockCommandComment *> Exceptions;
99 Brief(nullptr), Headerfile(nullptr), FirstParagraph(nullptr) {
105 switch (Child->getCommentKind()) {
109 case Comment::ParagraphCommentKind: {
116 MiscBlocks.push_back(PC);
120 case Comment::BlockCommandCommentKind: {
132 Returns.push_back(BCC);
136 Exceptions.push_back(BCC);
139 MiscBlocks.push_back(BCC);
143 case Comment::ParamCommandCommentKind: {
151 Params.push_back(PCC);
155 case Comment::TParamCommandCommentKind: {
163 TParams.push_back(TPCC);
167 case Comment::VerbatimBlockCommentKind:
168 MiscBlocks.push_back(cast<BlockCommandComment>(Child));
171 case Comment::VerbatimLineCommentKind: {
175 MiscBlocks.push_back(VLC);
179 case Comment::TextCommentKind:
180 case Comment::InlineCommandCommentKind:
181 case Comment::HTMLStartTagCommentKind:
182 case Comment::HTMLEndTagCommentKind:
183 case Comment::VerbatimBlockLineCommentKind:
184 case Comment::FullCommentKind:
185 llvm_unreachable(
"AST node of this kind can't be a child of "
193 llvm::stable_sort(Params, ParamCommandCommentCompareIndex());
194 llvm::stable_sort(TParams, TParamCommandCommentComparePosition());
198 llvm::raw_svector_ostream &Result) {
199 Result <<
"<" <<
C->getTagName();
201 if (
C->getNumAttrs() != 0) {
202 for (
unsigned i = 0, e =
C->getNumAttrs(); i != e; i++) {
206 if (!
Attr.Value.empty())
207 Result <<
"=\"" <<
Attr.Value <<
"\"";
211 if (!
C->isSelfClosing())
217class CommentASTToHTMLConverter :
224 FC(FC), Result(Str), Traits(Traits)
250 void appendToResultWithHTMLEscaping(StringRef S);
255 llvm::raw_svector_ostream
Result;
261void CommentASTToHTMLConverter::visitTextComment(
const TextComment *
C) {
262 appendToResultWithHTMLEscaping(
C->getText());
265void CommentASTToHTMLConverter::visitInlineCommandComment(
268 if (
C->getNumArgs() == 0)
272 StringRef Arg0 =
C->getArgText(0);
276 switch (
C->getRenderKind()) {
278 for (
unsigned i = 0, e =
C->getNumArgs(); i != e; ++i) {
279 appendToResultWithHTMLEscaping(
C->getArgText(i));
285 assert(
C->getNumArgs() == 1);
287 appendToResultWithHTMLEscaping(Arg0);
291 assert(
C->getNumArgs() == 1);
293 appendToResultWithHTMLEscaping(Arg0);
297 assert(
C->getNumArgs() == 1);
299 appendToResultWithHTMLEscaping(Arg0);
303 assert(
C->getNumArgs() == 1);
304 Result <<
"<span id=\"" << Arg0 <<
"\"></span>";
309void CommentASTToHTMLConverter::visitHTMLStartTagComment(
311 printHTMLStartTagComment(
C, Result);
314void CommentASTToHTMLConverter::visitHTMLEndTagComment(
316 Result <<
"</" <<
C->getTagName() <<
">";
319void CommentASTToHTMLConverter::visitParagraphComment(
321 if (
C->isWhitespace())
332void CommentASTToHTMLConverter::visitBlockCommandComment(
336 Result <<
"<p class=\"para-brief\">";
337 visitNonStandaloneParagraphComment(
C->getParagraph());
342 Result <<
"<p class=\"para-returns\">"
343 "<span class=\"word-returns\">Returns</span> ";
344 visitNonStandaloneParagraphComment(
C->getParagraph());
349 visit(
C->getParagraph());
352void CommentASTToHTMLConverter::visitParamCommandComment(
354 if (
C->isParamIndexValid()) {
355 if (
C->isVarArgParam()) {
356 Result <<
"<dt class=\"param-name-index-vararg\">";
357 appendToResultWithHTMLEscaping(
C->getParamNameAsWritten());
359 Result <<
"<dt class=\"param-name-index-"
360 <<
C->getParamIndex()
362 appendToResultWithHTMLEscaping(
C->getParamName(FC));
365 Result <<
"<dt class=\"param-name-index-invalid\">";
366 appendToResultWithHTMLEscaping(
C->getParamNameAsWritten());
370 if (
C->isParamIndexValid()) {
371 if (
C->isVarArgParam())
372 Result <<
"<dd class=\"param-descr-index-vararg\">";
374 Result <<
"<dd class=\"param-descr-index-"
375 <<
C->getParamIndex()
378 Result <<
"<dd class=\"param-descr-index-invalid\">";
380 visitNonStandaloneParagraphComment(
C->getParagraph());
384void CommentASTToHTMLConverter::visitTParamCommandComment(
386 if (
C->isPositionValid()) {
387 if (
C->getDepth() == 1)
388 Result <<
"<dt class=\"tparam-name-index-"
392 Result <<
"<dt class=\"tparam-name-index-other\">";
393 appendToResultWithHTMLEscaping(
C->getParamName(FC));
395 Result <<
"<dt class=\"tparam-name-index-invalid\">";
396 appendToResultWithHTMLEscaping(
C->getParamNameAsWritten());
401 if (
C->isPositionValid()) {
402 if (
C->getDepth() == 1)
403 Result <<
"<dd class=\"tparam-descr-index-"
407 Result <<
"<dd class=\"tparam-descr-index-other\">";
409 Result <<
"<dd class=\"tparam-descr-index-invalid\">";
411 visitNonStandaloneParagraphComment(
C->getParagraph());
415void CommentASTToHTMLConverter::visitVerbatimBlockComment(
417 unsigned NumLines =
C->getNumLines();
422 for (
unsigned i = 0; i != NumLines; ++i) {
423 appendToResultWithHTMLEscaping(
C->getText(i));
424 if (i + 1 != NumLines)
430void CommentASTToHTMLConverter::visitVerbatimBlockLineComment(
432 llvm_unreachable(
"should not see this AST node");
435void CommentASTToHTMLConverter::visitVerbatimLineComment(
438 appendToResultWithHTMLEscaping(
C->getText());
442void CommentASTToHTMLConverter::visitFullComment(
const FullComment *
C) {
443 FullCommentParts Parts(
C, Traits);
445 bool FirstParagraphIsBrief =
false;
446 if (Parts.Headerfile)
447 visit(Parts.Headerfile);
450 else if (Parts.FirstParagraph) {
451 Result <<
"<p class=\"para-brief\">";
452 visitNonStandaloneParagraphComment(Parts.FirstParagraph);
454 FirstParagraphIsBrief =
true;
457 for (
unsigned i = 0, e = Parts.MiscBlocks.size(); i != e; ++i) {
458 const Comment *
C = Parts.MiscBlocks[i];
459 if (FirstParagraphIsBrief &&
C == Parts.FirstParagraph)
464 if (Parts.TParams.size() != 0) {
466 for (
unsigned i = 0, e = Parts.TParams.size(); i != e; ++i)
467 visit(Parts.TParams[i]);
471 if (Parts.Params.size() != 0) {
473 for (
unsigned i = 0, e = Parts.Params.size(); i != e; ++i)
474 visit(Parts.Params[i]);
478 if (Parts.Returns.size() != 0) {
479 Result <<
"<div class=\"result-discussion\">";
480 for (
unsigned i = 0, e = Parts.Returns.size(); i != e; ++i)
481 visit(Parts.Returns[i]);
487void CommentASTToHTMLConverter::visitNonStandaloneParagraphComment(
498void CommentASTToHTMLConverter::appendToResultWithHTMLEscaping(StringRef S) {
499 for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I) {
528class CommentASTToXMLConverter :
536 FC(FC), Result(Str), Traits(Traits),
SM(
SM) { }
560 void appendToResultWithXMLEscaping(StringRef S);
561 void appendToResultWithCDATAEscaping(StringRef S);
563 void formatTextOfDeclaration(
const DeclInfo *DI,
570 llvm::raw_svector_ostream
Result;
576void getSourceTextOfDeclaration(
const DeclInfo *ThisDecl,
580 llvm::raw_svector_ostream OS(Str);
582 PPolicy.PolishForDeclaration =
true;
583 PPolicy.TerseOutput =
true;
584 PPolicy.ConstantsAsWritten =
true;
589void CommentASTToXMLConverter::formatTextOfDeclaration(
599 Style.FixNamespaceComments =
false;
603 if (
static_cast<bool>(FormattedStringDecl)) {
610void CommentASTToXMLConverter::visitTextComment(
const TextComment *
C) {
611 appendToResultWithXMLEscaping(
C->getText());
614void CommentASTToXMLConverter::visitInlineCommandComment(
617 if (
C->getNumArgs() == 0)
621 StringRef Arg0 =
C->getArgText(0);
625 switch (
C->getRenderKind()) {
627 for (
unsigned i = 0, e =
C->getNumArgs(); i != e; ++i) {
628 appendToResultWithXMLEscaping(
C->getArgText(i));
633 assert(
C->getNumArgs() == 1);
635 appendToResultWithXMLEscaping(Arg0);
639 assert(
C->getNumArgs() == 1);
640 Result <<
"<monospaced>";
641 appendToResultWithXMLEscaping(Arg0);
642 Result <<
"</monospaced>";
645 assert(
C->getNumArgs() == 1);
646 Result <<
"<emphasized>";
647 appendToResultWithXMLEscaping(Arg0);
648 Result <<
"</emphasized>";
651 assert(
C->getNumArgs() == 1);
652 Result <<
"<anchor id=\"" << Arg0 <<
"\"></anchor>";
657void CommentASTToXMLConverter::visitHTMLStartTagComment(
659 Result <<
"<rawHTML";
660 if (
C->isMalformed())
661 Result <<
" isMalformed=\"1\"";
666 llvm::raw_svector_ostream TagOS(Tag);
667 printHTMLStartTagComment(
C, TagOS);
669 appendToResultWithCDATAEscaping(Tag);
671 Result <<
"</rawHTML>";
676 Result <<
"<rawHTML";
677 if (
C->isMalformed())
678 Result <<
" isMalformed=\"1\"";
679 Result <<
"></" <<
C->getTagName() <<
"></rawHTML>";
684 appendParagraphCommentWithKind(
C, StringRef());
687void CommentASTToXMLConverter::appendParagraphCommentWithKind(
689 StringRef ParagraphKind) {
690 if (
C->isWhitespace())
693 if (ParagraphKind.empty())
696 Result <<
"<Para kind=\"" << ParagraphKind <<
"\">";
705void CommentASTToXMLConverter::visitBlockCommandComment(
707 StringRef ParagraphKind;
709 switch (
C->getCommandID()) {
710 case CommandTraits::KCI_attention:
711 case CommandTraits::KCI_author:
712 case CommandTraits::KCI_authors:
713 case CommandTraits::KCI_bug:
714 case CommandTraits::KCI_copyright:
715 case CommandTraits::KCI_date:
716 case CommandTraits::KCI_invariant:
717 case CommandTraits::KCI_note:
718 case CommandTraits::KCI_post:
719 case CommandTraits::KCI_pre:
720 case CommandTraits::KCI_remark:
721 case CommandTraits::KCI_remarks:
722 case CommandTraits::KCI_sa:
723 case CommandTraits::KCI_see:
724 case CommandTraits::KCI_since:
725 case CommandTraits::KCI_todo:
726 case CommandTraits::KCI_version:
727 case CommandTraits::KCI_warning:
728 ParagraphKind =
C->getCommandName(Traits);
734 appendParagraphCommentWithKind(
C->getParagraph(), ParagraphKind);
737void CommentASTToXMLConverter::visitParamCommandComment(
739 Result <<
"<Parameter><Name>";
740 appendToResultWithXMLEscaping(
C->isParamIndexValid()
741 ?
C->getParamName(FC)
742 :
C->getParamNameAsWritten());
745 if (
C->isParamIndexValid()) {
746 if (
C->isVarArgParam())
747 Result <<
"<IsVarArg />";
749 Result <<
"<Index>" <<
C->getParamIndex() <<
"</Index>";
752 Result <<
"<Direction isExplicit=\"" <<
C->isDirectionExplicit() <<
"\">";
753 switch (
C->getDirection()) {
764 Result <<
"</Direction><Discussion>";
765 visit(
C->getParagraph());
766 Result <<
"</Discussion></Parameter>";
769void CommentASTToXMLConverter::visitTParamCommandComment(
771 Result <<
"<Parameter><Name>";
772 appendToResultWithXMLEscaping(
C->isPositionValid() ?
C->getParamName(FC)
773 :
C->getParamNameAsWritten());
776 if (
C->isPositionValid() &&
C->getDepth() == 1) {
777 Result <<
"<Index>" <<
C->getIndex(0) <<
"</Index>";
780 Result <<
"<Discussion>";
781 visit(
C->getParagraph());
782 Result <<
"</Discussion></Parameter>";
785void CommentASTToXMLConverter::visitVerbatimBlockComment(
787 unsigned NumLines =
C->getNumLines();
791 switch (
C->getCommandID()) {
792 case CommandTraits::KCI_code:
793 Result <<
"<Verbatim xml:space=\"preserve\" kind=\"code\">";
796 Result <<
"<Verbatim xml:space=\"preserve\" kind=\"verbatim\">";
799 for (
unsigned i = 0; i != NumLines; ++i) {
800 appendToResultWithXMLEscaping(
C->getText(i));
801 if (i + 1 != NumLines)
804 Result <<
"</Verbatim>";
807void CommentASTToXMLConverter::visitVerbatimBlockLineComment(
809 llvm_unreachable(
"should not see this AST node");
812void CommentASTToXMLConverter::visitVerbatimLineComment(
814 Result <<
"<Verbatim xml:space=\"preserve\" kind=\"verbatim\">";
815 appendToResultWithXMLEscaping(
C->getText());
816 Result <<
"</Verbatim>";
819void CommentASTToXMLConverter::visitFullComment(
const FullComment *
C) {
820 FullCommentParts Parts(
C, Traits);
823 StringRef RootEndTag;
827 RootEndTag =
"</Other>";
831 RootEndTag =
"</Function>";
832 Result <<
"<Function";
837 Result <<
" templateKind=\"template\"";
840 Result <<
" templateKind=\"specialization\"";
843 llvm_unreachable(
"partial specializations of functions "
844 "are not allowed in C++");
847 Result <<
" isInstanceMethod=\"1\"";
849 Result <<
" isClassMethod=\"1\"";
852 RootEndTag =
"</Class>";
858 Result <<
" templateKind=\"template\"";
861 Result <<
" templateKind=\"specialization\"";
864 Result <<
" templateKind=\"partialSpecialization\"";
869 RootEndTag =
"</Variable>";
870 Result <<
"<Variable";
873 RootEndTag =
"</Namespace>";
874 Result <<
"<Namespace";
877 RootEndTag =
"</Typedef>";
878 Result <<
"<Typedef";
881 RootEndTag =
"</Enum>";
889 std::pair<FileID, unsigned> LocInfo =
SM.getDecomposedLoc(Loc);
890 FileID FID = LocInfo.first;
891 unsigned FileOffset = LocInfo.second;
894 if (
const FileEntry *FE =
SM.getFileEntryForID(FID)) {
895 Result <<
" file=\"";
896 appendToResultWithXMLEscaping(FE->getName());
899 Result <<
" line=\"" <<
SM.getLineNumber(FID, FileOffset)
900 <<
"\" column=\"" <<
SM.getColumnNumber(FID, FileOffset)
908 bool FoundName =
false;
912 std::string Name = DeclName.getAsString();
913 appendToResultWithXMLEscaping(Name);
919 Result <<
"<Name><anonymous></Name>";
927 appendToResultWithXMLEscaping(USR);
933 RootEndTag =
"</Other>";
934 Result <<
"<Other><Name>unknown</Name>";
937 if (Parts.Headerfile) {
938 Result <<
"<Headerfile>";
939 visit(Parts.Headerfile);
940 Result <<
"</Headerfile>";
945 Result <<
"<Declaration>";
950 Result <<
"</Declaration>";
953 bool FirstParagraphIsBrief =
false;
955 Result <<
"<Abstract>";
957 Result <<
"</Abstract>";
958 }
else if (Parts.FirstParagraph) {
959 Result <<
"<Abstract>";
960 visit(Parts.FirstParagraph);
961 Result <<
"</Abstract>";
962 FirstParagraphIsBrief =
true;
965 if (Parts.TParams.size() != 0) {
966 Result <<
"<TemplateParameters>";
967 for (
unsigned i = 0, e = Parts.TParams.size(); i != e; ++i)
968 visit(Parts.TParams[i]);
969 Result <<
"</TemplateParameters>";
972 if (Parts.Params.size() != 0) {
973 Result <<
"<Parameters>";
974 for (
unsigned i = 0, e = Parts.Params.size(); i != e; ++i)
975 visit(Parts.Params[i]);
976 Result <<
"</Parameters>";
979 if (Parts.Exceptions.size() != 0) {
980 Result <<
"<Exceptions>";
981 for (
unsigned i = 0, e = Parts.Exceptions.size(); i != e; ++i)
982 visit(Parts.Exceptions[i]);
983 Result <<
"</Exceptions>";
986 if (Parts.Returns.size() != 0) {
987 Result <<
"<ResultDiscussion>";
988 for (
unsigned i = 0, e = Parts.Returns.size(); i != e; ++i)
989 visit(Parts.Returns[i]);
990 Result <<
"</ResultDiscussion>";
995 for (
unsigned i = 0, e = Attrs.size(); i != e; i++) {
996 const AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(Attrs[i]);
998 if (
const DeprecatedAttr *DA = dyn_cast<DeprecatedAttr>(Attrs[i])) {
999 if (DA->getMessage().empty())
1000 Result <<
"<Deprecated/>";
1002 Result <<
"<Deprecated>";
1003 appendToResultWithXMLEscaping(DA->getMessage());
1004 Result <<
"</Deprecated>";
1007 else if (
const UnavailableAttr *UA = dyn_cast<UnavailableAttr>(Attrs[i])) {
1008 if (UA->getMessage().empty())
1009 Result <<
"<Unavailable/>";
1011 Result <<
"<Unavailable>";
1012 appendToResultWithXMLEscaping(UA->getMessage());
1013 Result <<
"</Unavailable>";
1020 Result <<
"<Availability";
1021 StringRef Distribution;
1022 if (AA->getPlatform()) {
1023 Distribution = AvailabilityAttr::getPrettyPlatformName(
1024 AA->getPlatform()->getName());
1025 if (Distribution.empty())
1026 Distribution = AA->getPlatform()->getName();
1028 Result <<
" distribution=\"" << Distribution <<
"\">";
1029 VersionTuple IntroducedInVersion = AA->getIntroduced();
1030 if (!IntroducedInVersion.empty()) {
1031 Result <<
"<IntroducedInVersion>"
1032 << IntroducedInVersion.getAsString()
1033 <<
"</IntroducedInVersion>";
1035 VersionTuple DeprecatedInVersion = AA->getDeprecated();
1036 if (!DeprecatedInVersion.empty()) {
1037 Result <<
"<DeprecatedInVersion>"
1038 << DeprecatedInVersion.getAsString()
1039 <<
"</DeprecatedInVersion>";
1041 VersionTuple RemovedAfterVersion = AA->getObsoleted();
1042 if (!RemovedAfterVersion.empty()) {
1043 Result <<
"<RemovedAfterVersion>"
1044 << RemovedAfterVersion.getAsString()
1045 <<
"</RemovedAfterVersion>";
1047 StringRef DeprecationSummary = AA->getMessage();
1048 if (!DeprecationSummary.empty()) {
1049 Result <<
"<DeprecationSummary>";
1050 appendToResultWithXMLEscaping(DeprecationSummary);
1051 Result <<
"</DeprecationSummary>";
1053 if (AA->getUnavailable())
1054 Result <<
"<Unavailable/>";
1055 Result <<
"</Availability>";
1060 bool StartTagEmitted =
false;
1061 for (
unsigned i = 0, e = Parts.MiscBlocks.size(); i != e; ++i) {
1062 const Comment *
C = Parts.MiscBlocks[i];
1063 if (FirstParagraphIsBrief &&
C == Parts.FirstParagraph)
1065 if (!StartTagEmitted) {
1066 Result <<
"<Discussion>";
1067 StartTagEmitted =
true;
1071 if (StartTagEmitted)
1072 Result <<
"</Discussion>";
1075 Result << RootEndTag;
1078void CommentASTToXMLConverter::appendToResultWithXMLEscaping(StringRef S) {
1079 for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I) {
1104void CommentASTToXMLConverter::appendToResultWithCDATAEscaping(StringRef S) {
1108 Result <<
"<![CDATA[";
1109 while (!S.empty()) {
1110 size_t Pos = S.find(
"]]>");
1112 Result <<
"]]]]><![CDATA[>";
1113 S = S.drop_front(3);
1116 if (Pos == StringRef::npos)
1119 Result << S.substr(0, Pos);
1121 S = S.drop_front(Pos);
1132 CommentASTToHTMLConverter Converter(FC, HTML,
1134 Converter.visit(FC);
1140 CommentASTToHTMLConverter Converter(
nullptr,
Text,
1142 Converter.visit(HTC);
1150 Converter.visit(FC);
Defines the clang::ASTContext interface.
Defines the clang::FileManager interface and associated types.
Defines the SourceManager interface.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
comments::CommandTraits & getCommentCommandTraits() const
const LangOptions & getLangOpts() const
Attr - This represents one attribute.
ASTContext & getASTContext() const LLVM_READONLY
SourceLocation getLocation() const
void print(raw_ostream &Out, unsigned Indentation=0, bool PrintInstantiation=false) const
The name of a declaration.
Cached information about one file (either on disk or in the virtual file system).
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
This represents a decl that may have a name.
Encodes a location in the source.
This class handles loading and caching of source files into memory.
bool generateUSRForDecl(const Decl *D, SmallVectorImpl< char > &Buf)
Generate a USR for a Decl, including the USR prefix.
@ C
Languages that the frontend can parse and compile.
@ Result
The result type of a method or function.
Describes how types, statements, expressions, and declarations should be printed.