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