blob: 028fdf1d3a8b2d34831d1cf09a535e5377ab1b1f [file] [log] [blame]
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +00001//===- 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
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +000014#include "CXComment.h"
Dmitri Gribenko740c0fb2012-08-07 17:54:38 +000015#include "CXCursor.h"
Chandler Carruthcc0694c2012-12-04 09:25:21 +000016#include "CXString.h"
Chandler Carruth575bc3ba2015-01-14 11:23:58 +000017#include "clang-c/Documentation.h"
Mehdi Amini9670f842016-07-18 19:02:11 +000018#include "clang-c/Index.h"
Dmitri Gribenko740c0fb2012-08-07 17:54:38 +000019#include "clang/AST/Decl.h"
Dmitri Gribenko9e605112013-11-13 22:16:51 +000020#include "clang/Index/CommentToXML.h"
Fariborz Jahanian9b7ab872012-12-18 23:02:59 +000021#include "llvm/ADT/StringExtras.h"
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +000022#include "llvm/Support/ErrorHandling.h"
Dmitri Gribenko5de4c062012-07-30 17:49:32 +000023#include <climits>
24
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +000025using namespace clang;
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +000026using namespace clang::comments;
27using namespace clang::cxcomment;
28
Alp Toker59c6bc52014-04-28 02:39:27 +000029CXComment clang_Cursor_getParsedComment(CXCursor C) {
30 using namespace clang::cxcursor;
31
32 if (!clang_isDeclaration(C.kind))
Craig Topper69186e72014-06-08 08:38:04 +000033 return createCXComment(nullptr, nullptr);
Alp Toker59c6bc52014-04-28 02:39:27 +000034
35 const Decl *D = getCursorDecl(C);
36 const ASTContext &Context = getCursorContext(C);
Craig Topper69186e72014-06-08 08:38:04 +000037 const FullComment *FC = Context.getCommentForDecl(D, /*PP=*/nullptr);
Alp Toker59c6bc52014-04-28 02:39:27 +000038
39 return createCXComment(FC, getCursorTU(C));
40}
41
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +000042enum CXCommentKind clang_Comment_getKind(CXComment CXC) {
43 const Comment *C = getASTNode(CXC);
44 if (!C)
45 return CXComment_Null;
46
47 switch (C->getCommentKind()) {
48 case Comment::NoCommentKind:
49 return CXComment_Null;
50
51 case Comment::TextCommentKind:
52 return CXComment_Text;
53
54 case Comment::InlineCommandCommentKind:
55 return CXComment_InlineCommand;
56
57 case Comment::HTMLStartTagCommentKind:
58 return CXComment_HTMLStartTag;
59
60 case Comment::HTMLEndTagCommentKind:
61 return CXComment_HTMLEndTag;
62
63 case Comment::ParagraphCommentKind:
64 return CXComment_Paragraph;
65
66 case Comment::BlockCommandCommentKind:
67 return CXComment_BlockCommand;
68
69 case Comment::ParamCommandCommentKind:
70 return CXComment_ParamCommand;
71
Dmitri Gribenko34df2202012-07-31 22:37:06 +000072 case Comment::TParamCommandCommentKind:
73 return CXComment_TParamCommand;
74
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +000075 case Comment::VerbatimBlockCommentKind:
76 return CXComment_VerbatimBlockCommand;
77
78 case Comment::VerbatimBlockLineCommentKind:
79 return CXComment_VerbatimBlockLine;
80
81 case Comment::VerbatimLineCommentKind:
82 return CXComment_VerbatimLine;
83
84 case Comment::FullCommentKind:
85 return CXComment_FullComment;
86 }
87 llvm_unreachable("unknown CommentKind");
88}
89
90unsigned clang_Comment_getNumChildren(CXComment CXC) {
91 const Comment *C = getASTNode(CXC);
92 if (!C)
93 return 0;
94
95 return C->child_count();
96}
97
98CXComment clang_Comment_getChild(CXComment CXC, unsigned ChildIdx) {
99 const Comment *C = getASTNode(CXC);
100 if (!C || ChildIdx >= C->child_count())
Craig Topper69186e72014-06-08 08:38:04 +0000101 return createCXComment(nullptr, nullptr);
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000102
Dmitri Gribenko7acbf002012-09-10 20:32:42 +0000103 return createCXComment(*(C->child_begin() + ChildIdx), CXC.TranslationUnit);
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000104}
105
106unsigned clang_Comment_isWhitespace(CXComment CXC) {
107 const Comment *C = getASTNode(CXC);
108 if (!C)
109 return false;
110
111 if (const TextComment *TC = dyn_cast<TextComment>(C))
112 return TC->isWhitespace();
113
114 if (const ParagraphComment *PC = dyn_cast<ParagraphComment>(C))
115 return PC->isWhitespace();
116
117 return false;
118}
119
120unsigned clang_InlineContentComment_hasTrailingNewline(CXComment CXC) {
121 const InlineContentComment *ICC = getASTNodeAs<InlineContentComment>(CXC);
122 if (!ICC)
123 return false;
124
125 return ICC->hasTrailingNewline();
126}
127
128CXString clang_TextComment_getText(CXComment CXC) {
129 const TextComment *TC = getASTNodeAs<TextComment>(CXC);
130 if (!TC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000131 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000132
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000133 return cxstring::createRef(TC->getText());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000134}
135
136CXString clang_InlineCommandComment_getCommandName(CXComment CXC) {
137 const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
138 if (!ICC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000139 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000140
Dmitri Gribenko7acbf002012-09-10 20:32:42 +0000141 const CommandTraits &Traits = getCommandTraits(CXC);
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000142 return cxstring::createRef(ICC->getCommandName(Traits));
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000143}
144
Dmitri Gribenkod73e4ce2012-07-23 16:43:01 +0000145enum CXCommentInlineCommandRenderKind
146clang_InlineCommandComment_getRenderKind(CXComment CXC) {
147 const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
148 if (!ICC)
149 return CXCommentInlineCommandRenderKind_Normal;
150
151 switch (ICC->getRenderKind()) {
152 case InlineCommandComment::RenderNormal:
153 return CXCommentInlineCommandRenderKind_Normal;
154
155 case InlineCommandComment::RenderBold:
156 return CXCommentInlineCommandRenderKind_Bold;
157
158 case InlineCommandComment::RenderMonospaced:
159 return CXCommentInlineCommandRenderKind_Monospaced;
160
161 case InlineCommandComment::RenderEmphasized:
162 return CXCommentInlineCommandRenderKind_Emphasized;
163 }
164 llvm_unreachable("unknown InlineCommandComment::RenderKind");
165}
166
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000167unsigned clang_InlineCommandComment_getNumArgs(CXComment CXC) {
168 const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
169 if (!ICC)
170 return 0;
171
172 return ICC->getNumArgs();
173}
174
175CXString clang_InlineCommandComment_getArgText(CXComment CXC,
176 unsigned ArgIdx) {
177 const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
178 if (!ICC || ArgIdx >= ICC->getNumArgs())
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000179 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000180
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000181 return cxstring::createRef(ICC->getArgText(ArgIdx));
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000182}
183
184CXString clang_HTMLTagComment_getTagName(CXComment CXC) {
185 const HTMLTagComment *HTC = getASTNodeAs<HTMLTagComment>(CXC);
186 if (!HTC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000187 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000188
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000189 return cxstring::createRef(HTC->getTagName());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000190}
191
192unsigned clang_HTMLStartTagComment_isSelfClosing(CXComment CXC) {
193 const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
194 if (!HST)
195 return false;
196
197 return HST->isSelfClosing();
198}
199
200unsigned clang_HTMLStartTag_getNumAttrs(CXComment CXC) {
201 const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
202 if (!HST)
203 return 0;
204
205 return HST->getNumAttrs();
206}
207
208CXString clang_HTMLStartTag_getAttrName(CXComment CXC, unsigned AttrIdx) {
209 const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
210 if (!HST || AttrIdx >= HST->getNumAttrs())
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000211 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000212
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000213 return cxstring::createRef(HST->getAttr(AttrIdx).Name);
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000214}
215
216CXString clang_HTMLStartTag_getAttrValue(CXComment CXC, unsigned AttrIdx) {
217 const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
218 if (!HST || AttrIdx >= HST->getNumAttrs())
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000219 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000220
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000221 return cxstring::createRef(HST->getAttr(AttrIdx).Value);
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000222}
223
224CXString clang_BlockCommandComment_getCommandName(CXComment CXC) {
225 const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
226 if (!BCC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000227 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000228
Dmitri Gribenko7acbf002012-09-10 20:32:42 +0000229 const CommandTraits &Traits = getCommandTraits(CXC);
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000230 return cxstring::createRef(BCC->getCommandName(Traits));
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000231}
232
233unsigned clang_BlockCommandComment_getNumArgs(CXComment CXC) {
234 const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
235 if (!BCC)
236 return 0;
237
238 return BCC->getNumArgs();
239}
240
241CXString clang_BlockCommandComment_getArgText(CXComment CXC,
242 unsigned ArgIdx) {
243 const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
244 if (!BCC || ArgIdx >= BCC->getNumArgs())
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000245 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000246
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000247 return cxstring::createRef(BCC->getArgText(ArgIdx));
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000248}
249
250CXComment clang_BlockCommandComment_getParagraph(CXComment CXC) {
251 const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
252 if (!BCC)
Craig Topper69186e72014-06-08 08:38:04 +0000253 return createCXComment(nullptr, nullptr);
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000254
Dmitri Gribenko7acbf002012-09-10 20:32:42 +0000255 return createCXComment(BCC->getParagraph(), CXC.TranslationUnit);
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000256}
257
258CXString clang_ParamCommandComment_getParamName(CXComment CXC) {
259 const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
Dmitri Gribenko378458d2012-07-23 19:41:49 +0000260 if (!PCC || !PCC->hasParamName())
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000261 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000262
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000263 return cxstring::createRef(PCC->getParamNameAsWritten());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000264}
265
266unsigned clang_ParamCommandComment_isParamIndexValid(CXComment CXC) {
267 const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
268 if (!PCC)
269 return false;
270
271 return PCC->isParamIndexValid();
272}
273
274unsigned clang_ParamCommandComment_getParamIndex(CXComment CXC) {
275 const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
Dmitri Gribenko02489eb2013-06-24 04:41:32 +0000276 if (!PCC || !PCC->isParamIndexValid() || PCC->isVarArgParam())
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000277 return ParamCommandComment::InvalidParamIndex;
278
279 return PCC->getParamIndex();
280}
281
282unsigned clang_ParamCommandComment_isDirectionExplicit(CXComment CXC) {
283 const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
284 if (!PCC)
285 return false;
286
287 return PCC->isDirectionExplicit();
288}
289
290enum CXCommentParamPassDirection clang_ParamCommandComment_getDirection(
291 CXComment CXC) {
292 const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
293 if (!PCC)
294 return CXCommentParamPassDirection_In;
295
296 switch (PCC->getDirection()) {
297 case ParamCommandComment::In:
298 return CXCommentParamPassDirection_In;
299
300 case ParamCommandComment::Out:
301 return CXCommentParamPassDirection_Out;
302
303 case ParamCommandComment::InOut:
304 return CXCommentParamPassDirection_InOut;
305 }
306 llvm_unreachable("unknown ParamCommandComment::PassDirection");
307}
308
Dmitri Gribenko34df2202012-07-31 22:37:06 +0000309CXString clang_TParamCommandComment_getParamName(CXComment CXC) {
310 const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
311 if (!TPCC || !TPCC->hasParamName())
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000312 return cxstring::createNull();
Dmitri Gribenko34df2202012-07-31 22:37:06 +0000313
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000314 return cxstring::createRef(TPCC->getParamNameAsWritten());
Dmitri Gribenko34df2202012-07-31 22:37:06 +0000315}
316
317unsigned clang_TParamCommandComment_isParamPositionValid(CXComment CXC) {
318 const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
319 if (!TPCC)
320 return false;
321
322 return TPCC->isPositionValid();
323}
324
325unsigned clang_TParamCommandComment_getDepth(CXComment CXC) {
326 const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
327 if (!TPCC || !TPCC->isPositionValid())
328 return 0;
329
330 return TPCC->getDepth();
331}
332
333unsigned clang_TParamCommandComment_getIndex(CXComment CXC, unsigned Depth) {
334 const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
335 if (!TPCC || !TPCC->isPositionValid() || Depth >= TPCC->getDepth())
336 return 0;
337
338 return TPCC->getIndex(Depth);
339}
340
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000341CXString clang_VerbatimBlockLineComment_getText(CXComment CXC) {
342 const VerbatimBlockLineComment *VBL =
343 getASTNodeAs<VerbatimBlockLineComment>(CXC);
344 if (!VBL)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000345 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000346
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000347 return cxstring::createRef(VBL->getText());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000348}
349
350CXString clang_VerbatimLineComment_getText(CXComment CXC) {
351 const VerbatimLineComment *VLC = getASTNodeAs<VerbatimLineComment>(CXC);
352 if (!VLC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000353 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000354
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000355 return cxstring::createRef(VLC->getText());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000356}
357
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000358//===----------------------------------------------------------------------===//
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000359// Converting comments to XML.
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000360//===----------------------------------------------------------------------===//
361
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000362CXString clang_HTMLTagComment_getAsString(CXComment CXC) {
363 const HTMLTagComment *HTC = getASTNodeAs<HTMLTagComment>(CXC);
364 if (!HTC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000365 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000366
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000367 CXTranslationUnit TU = CXC.TranslationUnit;
368 if (!TU->CommentToXML)
Dmitri Gribenko15076d52013-11-14 00:36:24 +0000369 TU->CommentToXML = new clang::index::CommentToXMLConverter();
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000370
371 SmallString<128> Text;
372 TU->CommentToXML->convertHTMLTagNodeToText(
373 HTC, Text, cxtu::getASTUnit(TU)->getASTContext());
374 return cxstring::createDup(Text.str());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000375}
376
377CXString clang_FullComment_getAsHTML(CXComment CXC) {
378 const FullComment *FC = getASTNodeAs<FullComment>(CXC);
379 if (!FC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000380 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000381
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000382 CXTranslationUnit TU = CXC.TranslationUnit;
383 if (!TU->CommentToXML)
Dmitri Gribenko15076d52013-11-14 00:36:24 +0000384 TU->CommentToXML = new clang::index::CommentToXMLConverter();
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000385
Dmitri Gribenko4c6d7a22012-07-21 01:47:43 +0000386 SmallString<1024> HTML;
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000387 TU->CommentToXML
388 ->convertCommentToHTML(FC, HTML, cxtu::getASTUnit(TU)->getASTContext());
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000389 return cxstring::createDup(HTML.str());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000390}
391
Dmitri Gribenko7acbf002012-09-10 20:32:42 +0000392CXString clang_FullComment_getAsXML(CXComment CXC) {
Dmitri Gribenko740c0fb2012-08-07 17:54:38 +0000393 const FullComment *FC = getASTNodeAs<FullComment>(CXC);
394 if (!FC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000395 return cxstring::createNull();
Dmitri Gribenkoba82fea2013-01-26 21:39:50 +0000396
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000397 CXTranslationUnit TU = CXC.TranslationUnit;
398 if (!TU->CommentToXML)
Dmitri Gribenko15076d52013-11-14 00:36:24 +0000399 TU->CommentToXML = new clang::index::CommentToXMLConverter();
Dmitri Gribenko740c0fb2012-08-07 17:54:38 +0000400
401 SmallString<1024> XML;
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000402 TU->CommentToXML
403 ->convertCommentToXML(FC, XML, cxtu::getASTUnit(TU)->getASTContext());
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000404 return cxstring::createDup(XML.str());
Dmitri Gribenko740c0fb2012-08-07 17:54:38 +0000405}
406