CXComment.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. //===- CXComment.cpp - libclang APIs for manipulating CXComments ----------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file defines all libclang APIs related to walking comment AST.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "CXComment.h"
  13. #include "CXCursor.h"
  14. #include "CXString.h"
  15. #include "clang-c/Documentation.h"
  16. #include "clang-c/Index.h"
  17. #include "clang/AST/Decl.h"
  18. #include "clang/Index/CommentToXML.h"
  19. #include "llvm/ADT/StringExtras.h"
  20. #include "llvm/Support/ErrorHandling.h"
  21. #include <climits>
  22. using namespace clang;
  23. using namespace clang::comments;
  24. using namespace clang::cxcomment;
  25. CXComment clang_Cursor_getParsedComment(CXCursor C) {
  26. using namespace clang::cxcursor;
  27. if (!clang_isDeclaration(C.kind))
  28. return createCXComment(nullptr, nullptr);
  29. const Decl *D = getCursorDecl(C);
  30. const ASTContext &Context = getCursorContext(C);
  31. const FullComment *FC = Context.getCommentForDecl(D, /*PP=*/nullptr);
  32. return createCXComment(FC, getCursorTU(C));
  33. }
  34. enum CXCommentKind clang_Comment_getKind(CXComment CXC) {
  35. const Comment *C = getASTNode(CXC);
  36. if (!C)
  37. return CXComment_Null;
  38. switch (C->getCommentKind()) {
  39. case Comment::NoCommentKind:
  40. return CXComment_Null;
  41. case Comment::TextCommentKind:
  42. return CXComment_Text;
  43. case Comment::InlineCommandCommentKind:
  44. return CXComment_InlineCommand;
  45. case Comment::HTMLStartTagCommentKind:
  46. return CXComment_HTMLStartTag;
  47. case Comment::HTMLEndTagCommentKind:
  48. return CXComment_HTMLEndTag;
  49. case Comment::ParagraphCommentKind:
  50. return CXComment_Paragraph;
  51. case Comment::BlockCommandCommentKind:
  52. return CXComment_BlockCommand;
  53. case Comment::ParamCommandCommentKind:
  54. return CXComment_ParamCommand;
  55. case Comment::TParamCommandCommentKind:
  56. return CXComment_TParamCommand;
  57. case Comment::VerbatimBlockCommentKind:
  58. return CXComment_VerbatimBlockCommand;
  59. case Comment::VerbatimBlockLineCommentKind:
  60. return CXComment_VerbatimBlockLine;
  61. case Comment::VerbatimLineCommentKind:
  62. return CXComment_VerbatimLine;
  63. case Comment::FullCommentKind:
  64. return CXComment_FullComment;
  65. }
  66. llvm_unreachable("unknown CommentKind");
  67. }
  68. unsigned clang_Comment_getNumChildren(CXComment CXC) {
  69. const Comment *C = getASTNode(CXC);
  70. if (!C)
  71. return 0;
  72. return C->child_count();
  73. }
  74. CXComment clang_Comment_getChild(CXComment CXC, unsigned ChildIdx) {
  75. const Comment *C = getASTNode(CXC);
  76. if (!C || ChildIdx >= C->child_count())
  77. return createCXComment(nullptr, nullptr);
  78. return createCXComment(*(C->child_begin() + ChildIdx), CXC.TranslationUnit);
  79. }
  80. unsigned clang_Comment_isWhitespace(CXComment CXC) {
  81. const Comment *C = getASTNode(CXC);
  82. if (!C)
  83. return false;
  84. if (const TextComment *TC = dyn_cast<TextComment>(C))
  85. return TC->isWhitespace();
  86. if (const ParagraphComment *PC = dyn_cast<ParagraphComment>(C))
  87. return PC->isWhitespace();
  88. return false;
  89. }
  90. unsigned clang_InlineContentComment_hasTrailingNewline(CXComment CXC) {
  91. const InlineContentComment *ICC = getASTNodeAs<InlineContentComment>(CXC);
  92. if (!ICC)
  93. return false;
  94. return ICC->hasTrailingNewline();
  95. }
  96. CXString clang_TextComment_getText(CXComment CXC) {
  97. const TextComment *TC = getASTNodeAs<TextComment>(CXC);
  98. if (!TC)
  99. return cxstring::createNull();
  100. return cxstring::createRef(TC->getText());
  101. }
  102. CXString clang_InlineCommandComment_getCommandName(CXComment CXC) {
  103. const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
  104. if (!ICC)
  105. return cxstring::createNull();
  106. const CommandTraits &Traits = getCommandTraits(CXC);
  107. return cxstring::createRef(ICC->getCommandName(Traits));
  108. }
  109. enum CXCommentInlineCommandRenderKind
  110. clang_InlineCommandComment_getRenderKind(CXComment CXC) {
  111. const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
  112. if (!ICC)
  113. return CXCommentInlineCommandRenderKind_Normal;
  114. switch (ICC->getRenderKind()) {
  115. case InlineCommandComment::RenderNormal:
  116. return CXCommentInlineCommandRenderKind_Normal;
  117. case InlineCommandComment::RenderBold:
  118. return CXCommentInlineCommandRenderKind_Bold;
  119. case InlineCommandComment::RenderMonospaced:
  120. return CXCommentInlineCommandRenderKind_Monospaced;
  121. case InlineCommandComment::RenderEmphasized:
  122. return CXCommentInlineCommandRenderKind_Emphasized;
  123. case InlineCommandComment::RenderAnchor:
  124. return CXCommentInlineCommandRenderKind_Anchor;
  125. }
  126. llvm_unreachable("unknown InlineCommandComment::RenderKind");
  127. }
  128. unsigned clang_InlineCommandComment_getNumArgs(CXComment CXC) {
  129. const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
  130. if (!ICC)
  131. return 0;
  132. return ICC->getNumArgs();
  133. }
  134. CXString clang_InlineCommandComment_getArgText(CXComment CXC,
  135. unsigned ArgIdx) {
  136. const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
  137. if (!ICC || ArgIdx >= ICC->getNumArgs())
  138. return cxstring::createNull();
  139. return cxstring::createRef(ICC->getArgText(ArgIdx));
  140. }
  141. CXString clang_HTMLTagComment_getTagName(CXComment CXC) {
  142. const HTMLTagComment *HTC = getASTNodeAs<HTMLTagComment>(CXC);
  143. if (!HTC)
  144. return cxstring::createNull();
  145. return cxstring::createRef(HTC->getTagName());
  146. }
  147. unsigned clang_HTMLStartTagComment_isSelfClosing(CXComment CXC) {
  148. const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
  149. if (!HST)
  150. return false;
  151. return HST->isSelfClosing();
  152. }
  153. unsigned clang_HTMLStartTag_getNumAttrs(CXComment CXC) {
  154. const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
  155. if (!HST)
  156. return 0;
  157. return HST->getNumAttrs();
  158. }
  159. CXString clang_HTMLStartTag_getAttrName(CXComment CXC, unsigned AttrIdx) {
  160. const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
  161. if (!HST || AttrIdx >= HST->getNumAttrs())
  162. return cxstring::createNull();
  163. return cxstring::createRef(HST->getAttr(AttrIdx).Name);
  164. }
  165. CXString clang_HTMLStartTag_getAttrValue(CXComment CXC, unsigned AttrIdx) {
  166. const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
  167. if (!HST || AttrIdx >= HST->getNumAttrs())
  168. return cxstring::createNull();
  169. return cxstring::createRef(HST->getAttr(AttrIdx).Value);
  170. }
  171. CXString clang_BlockCommandComment_getCommandName(CXComment CXC) {
  172. const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
  173. if (!BCC)
  174. return cxstring::createNull();
  175. const CommandTraits &Traits = getCommandTraits(CXC);
  176. return cxstring::createRef(BCC->getCommandName(Traits));
  177. }
  178. unsigned clang_BlockCommandComment_getNumArgs(CXComment CXC) {
  179. const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
  180. if (!BCC)
  181. return 0;
  182. return BCC->getNumArgs();
  183. }
  184. CXString clang_BlockCommandComment_getArgText(CXComment CXC,
  185. unsigned ArgIdx) {
  186. const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
  187. if (!BCC || ArgIdx >= BCC->getNumArgs())
  188. return cxstring::createNull();
  189. return cxstring::createRef(BCC->getArgText(ArgIdx));
  190. }
  191. CXComment clang_BlockCommandComment_getParagraph(CXComment CXC) {
  192. const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
  193. if (!BCC)
  194. return createCXComment(nullptr, nullptr);
  195. return createCXComment(BCC->getParagraph(), CXC.TranslationUnit);
  196. }
  197. CXString clang_ParamCommandComment_getParamName(CXComment CXC) {
  198. const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
  199. if (!PCC || !PCC->hasParamName())
  200. return cxstring::createNull();
  201. return cxstring::createRef(PCC->getParamNameAsWritten());
  202. }
  203. unsigned clang_ParamCommandComment_isParamIndexValid(CXComment CXC) {
  204. const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
  205. if (!PCC)
  206. return false;
  207. return PCC->isParamIndexValid();
  208. }
  209. unsigned clang_ParamCommandComment_getParamIndex(CXComment CXC) {
  210. const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
  211. if (!PCC || !PCC->isParamIndexValid() || PCC->isVarArgParam())
  212. return ParamCommandComment::InvalidParamIndex;
  213. return PCC->getParamIndex();
  214. }
  215. unsigned clang_ParamCommandComment_isDirectionExplicit(CXComment CXC) {
  216. const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
  217. if (!PCC)
  218. return false;
  219. return PCC->isDirectionExplicit();
  220. }
  221. enum CXCommentParamPassDirection clang_ParamCommandComment_getDirection(
  222. CXComment CXC) {
  223. const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
  224. if (!PCC)
  225. return CXCommentParamPassDirection_In;
  226. switch (PCC->getDirection()) {
  227. case ParamCommandComment::In:
  228. return CXCommentParamPassDirection_In;
  229. case ParamCommandComment::Out:
  230. return CXCommentParamPassDirection_Out;
  231. case ParamCommandComment::InOut:
  232. return CXCommentParamPassDirection_InOut;
  233. }
  234. llvm_unreachable("unknown ParamCommandComment::PassDirection");
  235. }
  236. CXString clang_TParamCommandComment_getParamName(CXComment CXC) {
  237. const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
  238. if (!TPCC || !TPCC->hasParamName())
  239. return cxstring::createNull();
  240. return cxstring::createRef(TPCC->getParamNameAsWritten());
  241. }
  242. unsigned clang_TParamCommandComment_isParamPositionValid(CXComment CXC) {
  243. const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
  244. if (!TPCC)
  245. return false;
  246. return TPCC->isPositionValid();
  247. }
  248. unsigned clang_TParamCommandComment_getDepth(CXComment CXC) {
  249. const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
  250. if (!TPCC || !TPCC->isPositionValid())
  251. return 0;
  252. return TPCC->getDepth();
  253. }
  254. unsigned clang_TParamCommandComment_getIndex(CXComment CXC, unsigned Depth) {
  255. const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
  256. if (!TPCC || !TPCC->isPositionValid() || Depth >= TPCC->getDepth())
  257. return 0;
  258. return TPCC->getIndex(Depth);
  259. }
  260. CXString clang_VerbatimBlockLineComment_getText(CXComment CXC) {
  261. const VerbatimBlockLineComment *VBL =
  262. getASTNodeAs<VerbatimBlockLineComment>(CXC);
  263. if (!VBL)
  264. return cxstring::createNull();
  265. return cxstring::createRef(VBL->getText());
  266. }
  267. CXString clang_VerbatimLineComment_getText(CXComment CXC) {
  268. const VerbatimLineComment *VLC = getASTNodeAs<VerbatimLineComment>(CXC);
  269. if (!VLC)
  270. return cxstring::createNull();
  271. return cxstring::createRef(VLC->getText());
  272. }
  273. //===----------------------------------------------------------------------===//
  274. // Converting comments to XML.
  275. //===----------------------------------------------------------------------===//
  276. CXString clang_HTMLTagComment_getAsString(CXComment CXC) {
  277. const HTMLTagComment *HTC = getASTNodeAs<HTMLTagComment>(CXC);
  278. if (!HTC)
  279. return cxstring::createNull();
  280. CXTranslationUnit TU = CXC.TranslationUnit;
  281. if (!TU->CommentToXML)
  282. TU->CommentToXML = new clang::index::CommentToXMLConverter();
  283. SmallString<128> Text;
  284. TU->CommentToXML->convertHTMLTagNodeToText(
  285. HTC, Text, cxtu::getASTUnit(TU)->getASTContext());
  286. return cxstring::createDup(Text.str());
  287. }
  288. CXString clang_FullComment_getAsHTML(CXComment CXC) {
  289. const FullComment *FC = getASTNodeAs<FullComment>(CXC);
  290. if (!FC)
  291. return cxstring::createNull();
  292. CXTranslationUnit TU = CXC.TranslationUnit;
  293. if (!TU->CommentToXML)
  294. TU->CommentToXML = new clang::index::CommentToXMLConverter();
  295. SmallString<1024> HTML;
  296. TU->CommentToXML
  297. ->convertCommentToHTML(FC, HTML, cxtu::getASTUnit(TU)->getASTContext());
  298. return cxstring::createDup(HTML.str());
  299. }
  300. CXString clang_FullComment_getAsXML(CXComment CXC) {
  301. const FullComment *FC = getASTNodeAs<FullComment>(CXC);
  302. if (!FC)
  303. return cxstring::createNull();
  304. CXTranslationUnit TU = CXC.TranslationUnit;
  305. if (!TU->CommentToXML)
  306. TU->CommentToXML = new clang::index::CommentToXMLConverter();
  307. SmallString<1024> XML;
  308. TU->CommentToXML
  309. ->convertCommentToXML(FC, XML, cxtu::getASTUnit(TU)->getASTContext());
  310. return cxstring::createDup(XML.str());
  311. }