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