blob: 9cc05ed4e127e9c671d858a463080b585ab18635 [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
14#include "clang-c/Index.h"
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +000015#include "CXComment.h"
Dmitri Gribenko740c0fb2012-08-07 17:54:38 +000016#include "CXCursor.h"
Chandler Carruthcc0694c2012-12-04 09:25:21 +000017#include "CXString.h"
Chandler Carruth575bc3ba2015-01-14 11:23:58 +000018#include "clang-c/Documentation.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 Gribenko740c0fb2012-08-07 17:54:38 +000022#include "llvm/ADT/StringSwitch.h"
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +000023#include "llvm/Support/ErrorHandling.h"
Dmitri Gribenko5de4c062012-07-30 17:49:32 +000024#include <climits>
25
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +000026using namespace clang;
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +000027using namespace clang::comments;
28using namespace clang::cxcomment;
29
30extern "C" {
31
Alp Toker59c6bc52014-04-28 02:39:27 +000032CXComment clang_Cursor_getParsedComment(CXCursor C) {
33 using namespace clang::cxcursor;
34
35 if (!clang_isDeclaration(C.kind))
Craig Topper69186e72014-06-08 08:38:04 +000036 return createCXComment(nullptr, nullptr);
Alp Toker59c6bc52014-04-28 02:39:27 +000037
38 const Decl *D = getCursorDecl(C);
39 const ASTContext &Context = getCursorContext(C);
Craig Topper69186e72014-06-08 08:38:04 +000040 const FullComment *FC = Context.getCommentForDecl(D, /*PP=*/nullptr);
Alp Toker59c6bc52014-04-28 02:39:27 +000041
42 return createCXComment(FC, getCursorTU(C));
43}
44
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +000045enum 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
Dmitri Gribenko34df2202012-07-31 22:37:06 +000075 case Comment::TParamCommandCommentKind:
76 return CXComment_TParamCommand;
77
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +000078 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
93unsigned 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
101CXComment clang_Comment_getChild(CXComment CXC, unsigned ChildIdx) {
102 const Comment *C = getASTNode(CXC);
103 if (!C || ChildIdx >= C->child_count())
Craig Topper69186e72014-06-08 08:38:04 +0000104 return createCXComment(nullptr, nullptr);
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000105
Dmitri Gribenko7acbf002012-09-10 20:32:42 +0000106 return createCXComment(*(C->child_begin() + ChildIdx), CXC.TranslationUnit);
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000107}
108
109unsigned 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
123unsigned 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
131CXString clang_TextComment_getText(CXComment CXC) {
132 const TextComment *TC = getASTNodeAs<TextComment>(CXC);
133 if (!TC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000134 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000135
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000136 return cxstring::createRef(TC->getText());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000137}
138
139CXString clang_InlineCommandComment_getCommandName(CXComment CXC) {
140 const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
141 if (!ICC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000142 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000143
Dmitri Gribenko7acbf002012-09-10 20:32:42 +0000144 const CommandTraits &Traits = getCommandTraits(CXC);
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000145 return cxstring::createRef(ICC->getCommandName(Traits));
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000146}
147
Dmitri Gribenkod73e4ce2012-07-23 16:43:01 +0000148enum CXCommentInlineCommandRenderKind
149clang_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
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000170unsigned 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
178CXString clang_InlineCommandComment_getArgText(CXComment CXC,
179 unsigned ArgIdx) {
180 const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
181 if (!ICC || ArgIdx >= ICC->getNumArgs())
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000182 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000183
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000184 return cxstring::createRef(ICC->getArgText(ArgIdx));
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000185}
186
187CXString clang_HTMLTagComment_getTagName(CXComment CXC) {
188 const HTMLTagComment *HTC = getASTNodeAs<HTMLTagComment>(CXC);
189 if (!HTC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000190 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000191
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000192 return cxstring::createRef(HTC->getTagName());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000193}
194
195unsigned 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
203unsigned 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
211CXString clang_HTMLStartTag_getAttrName(CXComment CXC, unsigned AttrIdx) {
212 const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
213 if (!HST || AttrIdx >= HST->getNumAttrs())
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000214 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000215
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000216 return cxstring::createRef(HST->getAttr(AttrIdx).Name);
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000217}
218
219CXString clang_HTMLStartTag_getAttrValue(CXComment CXC, unsigned AttrIdx) {
220 const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
221 if (!HST || AttrIdx >= HST->getNumAttrs())
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000222 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000223
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000224 return cxstring::createRef(HST->getAttr(AttrIdx).Value);
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000225}
226
227CXString clang_BlockCommandComment_getCommandName(CXComment CXC) {
228 const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
229 if (!BCC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000230 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000231
Dmitri Gribenko7acbf002012-09-10 20:32:42 +0000232 const CommandTraits &Traits = getCommandTraits(CXC);
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000233 return cxstring::createRef(BCC->getCommandName(Traits));
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000234}
235
236unsigned 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
244CXString clang_BlockCommandComment_getArgText(CXComment CXC,
245 unsigned ArgIdx) {
246 const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
247 if (!BCC || ArgIdx >= BCC->getNumArgs())
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000248 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000249
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000250 return cxstring::createRef(BCC->getArgText(ArgIdx));
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000251}
252
253CXComment clang_BlockCommandComment_getParagraph(CXComment CXC) {
254 const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
255 if (!BCC)
Craig Topper69186e72014-06-08 08:38:04 +0000256 return createCXComment(nullptr, nullptr);
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000257
Dmitri Gribenko7acbf002012-09-10 20:32:42 +0000258 return createCXComment(BCC->getParagraph(), CXC.TranslationUnit);
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000259}
260
261CXString clang_ParamCommandComment_getParamName(CXComment CXC) {
262 const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
Dmitri Gribenko378458d2012-07-23 19:41:49 +0000263 if (!PCC || !PCC->hasParamName())
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000264 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000265
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000266 return cxstring::createRef(PCC->getParamNameAsWritten());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000267}
268
269unsigned 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
277unsigned clang_ParamCommandComment_getParamIndex(CXComment CXC) {
278 const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
Dmitri Gribenko02489eb2013-06-24 04:41:32 +0000279 if (!PCC || !PCC->isParamIndexValid() || PCC->isVarArgParam())
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000280 return ParamCommandComment::InvalidParamIndex;
281
282 return PCC->getParamIndex();
283}
284
285unsigned 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
293enum 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
Dmitri Gribenko34df2202012-07-31 22:37:06 +0000312CXString clang_TParamCommandComment_getParamName(CXComment CXC) {
313 const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
314 if (!TPCC || !TPCC->hasParamName())
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000315 return cxstring::createNull();
Dmitri Gribenko34df2202012-07-31 22:37:06 +0000316
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000317 return cxstring::createRef(TPCC->getParamNameAsWritten());
Dmitri Gribenko34df2202012-07-31 22:37:06 +0000318}
319
320unsigned 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
328unsigned 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
336unsigned 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
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000344CXString clang_VerbatimBlockLineComment_getText(CXComment CXC) {
345 const VerbatimBlockLineComment *VBL =
346 getASTNodeAs<VerbatimBlockLineComment>(CXC);
347 if (!VBL)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000348 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000349
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000350 return cxstring::createRef(VBL->getText());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000351}
352
353CXString clang_VerbatimLineComment_getText(CXComment CXC) {
354 const VerbatimLineComment *VLC = getASTNodeAs<VerbatimLineComment>(CXC);
355 if (!VLC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000356 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000357
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000358 return cxstring::createRef(VLC->getText());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000359}
360
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000361//===----------------------------------------------------------------------===//
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000362// Converting comments to XML.
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000363//===----------------------------------------------------------------------===//
364
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000365CXString clang_HTMLTagComment_getAsString(CXComment CXC) {
366 const HTMLTagComment *HTC = getASTNodeAs<HTMLTagComment>(CXC);
367 if (!HTC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000368 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000369
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000370 CXTranslationUnit TU = CXC.TranslationUnit;
371 if (!TU->CommentToXML)
Dmitri Gribenko15076d52013-11-14 00:36:24 +0000372 TU->CommentToXML = new clang::index::CommentToXMLConverter();
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000373
374 SmallString<128> Text;
375 TU->CommentToXML->convertHTMLTagNodeToText(
376 HTC, Text, cxtu::getASTUnit(TU)->getASTContext());
377 return cxstring::createDup(Text.str());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000378}
379
380CXString clang_FullComment_getAsHTML(CXComment CXC) {
381 const FullComment *FC = getASTNodeAs<FullComment>(CXC);
382 if (!FC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000383 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000384
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000385 CXTranslationUnit TU = CXC.TranslationUnit;
386 if (!TU->CommentToXML)
Dmitri Gribenko15076d52013-11-14 00:36:24 +0000387 TU->CommentToXML = new clang::index::CommentToXMLConverter();
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000388
Dmitri Gribenko4c6d7a22012-07-21 01:47:43 +0000389 SmallString<1024> HTML;
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000390 TU->CommentToXML
391 ->convertCommentToHTML(FC, HTML, cxtu::getASTUnit(TU)->getASTContext());
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000392 return cxstring::createDup(HTML.str());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000393}
394
Dmitri Gribenko7acbf002012-09-10 20:32:42 +0000395CXString clang_FullComment_getAsXML(CXComment CXC) {
Dmitri Gribenko740c0fb2012-08-07 17:54:38 +0000396 const FullComment *FC = getASTNodeAs<FullComment>(CXC);
397 if (!FC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000398 return cxstring::createNull();
Dmitri Gribenkoba82fea2013-01-26 21:39:50 +0000399
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000400 CXTranslationUnit TU = CXC.TranslationUnit;
401 if (!TU->CommentToXML)
Dmitri Gribenko15076d52013-11-14 00:36:24 +0000402 TU->CommentToXML = new clang::index::CommentToXMLConverter();
Dmitri Gribenko740c0fb2012-08-07 17:54:38 +0000403
404 SmallString<1024> XML;
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000405 TU->CommentToXML
406 ->convertCommentToXML(FC, XML, cxtu::getASTUnit(TU)->getASTContext());
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000407 return cxstring::createDup(XML.str());
Dmitri Gribenko740c0fb2012-08-07 17:54:38 +0000408}
409
410} // end extern "C"
411