blob: 21057cb66ea841044eebd38c3fa44ab3b58780fc [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"
Dmitri Gribenko740c0fb2012-08-07 17:54:38 +000018#include "clang/AST/Decl.h"
Dmitri Gribenko9e605112013-11-13 22:16:51 +000019#include "clang/Index/CommentToXML.h"
Fariborz Jahanian9b7ab872012-12-18 23:02:59 +000020#include "llvm/ADT/StringExtras.h"
Dmitri Gribenko740c0fb2012-08-07 17:54:38 +000021#include "llvm/ADT/StringSwitch.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
29extern "C" {
30
31enum 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
Dmitri Gribenko34df2202012-07-31 22:37:06 +000061 case Comment::TParamCommandCommentKind:
62 return CXComment_TParamCommand;
63
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +000064 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
79unsigned 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
87CXComment clang_Comment_getChild(CXComment CXC, unsigned ChildIdx) {
88 const Comment *C = getASTNode(CXC);
89 if (!C || ChildIdx >= C->child_count())
Dmitri Gribenko7acbf002012-09-10 20:32:42 +000090 return createCXComment(NULL, NULL);
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +000091
Dmitri Gribenko7acbf002012-09-10 20:32:42 +000092 return createCXComment(*(C->child_begin() + ChildIdx), CXC.TranslationUnit);
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +000093}
94
95unsigned 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
109unsigned 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
117CXString clang_TextComment_getText(CXComment CXC) {
118 const TextComment *TC = getASTNodeAs<TextComment>(CXC);
119 if (!TC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000120 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000121
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000122 return cxstring::createRef(TC->getText());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000123}
124
125CXString clang_InlineCommandComment_getCommandName(CXComment CXC) {
126 const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
127 if (!ICC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000128 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000129
Dmitri Gribenko7acbf002012-09-10 20:32:42 +0000130 const CommandTraits &Traits = getCommandTraits(CXC);
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000131 return cxstring::createRef(ICC->getCommandName(Traits));
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000132}
133
Dmitri Gribenkod73e4ce2012-07-23 16:43:01 +0000134enum CXCommentInlineCommandRenderKind
135clang_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
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000156unsigned 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
164CXString clang_InlineCommandComment_getArgText(CXComment CXC,
165 unsigned ArgIdx) {
166 const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
167 if (!ICC || ArgIdx >= ICC->getNumArgs())
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000168 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000169
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000170 return cxstring::createRef(ICC->getArgText(ArgIdx));
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000171}
172
173CXString clang_HTMLTagComment_getTagName(CXComment CXC) {
174 const HTMLTagComment *HTC = getASTNodeAs<HTMLTagComment>(CXC);
175 if (!HTC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000176 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000177
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000178 return cxstring::createRef(HTC->getTagName());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000179}
180
181unsigned 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
189unsigned 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
197CXString clang_HTMLStartTag_getAttrName(CXComment CXC, unsigned AttrIdx) {
198 const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
199 if (!HST || AttrIdx >= HST->getNumAttrs())
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000200 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000201
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000202 return cxstring::createRef(HST->getAttr(AttrIdx).Name);
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000203}
204
205CXString clang_HTMLStartTag_getAttrValue(CXComment CXC, unsigned AttrIdx) {
206 const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
207 if (!HST || AttrIdx >= HST->getNumAttrs())
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000208 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000209
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000210 return cxstring::createRef(HST->getAttr(AttrIdx).Value);
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000211}
212
213CXString clang_BlockCommandComment_getCommandName(CXComment CXC) {
214 const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
215 if (!BCC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000216 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000217
Dmitri Gribenko7acbf002012-09-10 20:32:42 +0000218 const CommandTraits &Traits = getCommandTraits(CXC);
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000219 return cxstring::createRef(BCC->getCommandName(Traits));
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000220}
221
222unsigned 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
230CXString clang_BlockCommandComment_getArgText(CXComment CXC,
231 unsigned ArgIdx) {
232 const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
233 if (!BCC || ArgIdx >= BCC->getNumArgs())
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000234 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000235
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000236 return cxstring::createRef(BCC->getArgText(ArgIdx));
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000237}
238
239CXComment clang_BlockCommandComment_getParagraph(CXComment CXC) {
240 const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
241 if (!BCC)
Dmitri Gribenko7acbf002012-09-10 20:32:42 +0000242 return createCXComment(NULL, NULL);
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000243
Dmitri Gribenko7acbf002012-09-10 20:32:42 +0000244 return createCXComment(BCC->getParagraph(), CXC.TranslationUnit);
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000245}
246
247CXString clang_ParamCommandComment_getParamName(CXComment CXC) {
248 const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
Dmitri Gribenko378458d2012-07-23 19:41:49 +0000249 if (!PCC || !PCC->hasParamName())
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000250 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000251
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000252 return cxstring::createRef(PCC->getParamNameAsWritten());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000253}
254
255unsigned 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
263unsigned clang_ParamCommandComment_getParamIndex(CXComment CXC) {
264 const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
Dmitri Gribenko02489eb2013-06-24 04:41:32 +0000265 if (!PCC || !PCC->isParamIndexValid() || PCC->isVarArgParam())
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000266 return ParamCommandComment::InvalidParamIndex;
267
268 return PCC->getParamIndex();
269}
270
271unsigned 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
279enum 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
Dmitri Gribenko34df2202012-07-31 22:37:06 +0000298CXString clang_TParamCommandComment_getParamName(CXComment CXC) {
299 const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
300 if (!TPCC || !TPCC->hasParamName())
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000301 return cxstring::createNull();
Dmitri Gribenko34df2202012-07-31 22:37:06 +0000302
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000303 return cxstring::createRef(TPCC->getParamNameAsWritten());
Dmitri Gribenko34df2202012-07-31 22:37:06 +0000304}
305
306unsigned 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
314unsigned 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
322unsigned 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
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000330CXString clang_VerbatimBlockLineComment_getText(CXComment CXC) {
331 const VerbatimBlockLineComment *VBL =
332 getASTNodeAs<VerbatimBlockLineComment>(CXC);
333 if (!VBL)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000334 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000335
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000336 return cxstring::createRef(VBL->getText());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000337}
338
339CXString clang_VerbatimLineComment_getText(CXComment CXC) {
340 const VerbatimLineComment *VLC = getASTNodeAs<VerbatimLineComment>(CXC);
341 if (!VLC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000342 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000343
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000344 return cxstring::createRef(VLC->getText());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000345}
346
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000347//===----------------------------------------------------------------------===//
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000348// Converting comments to XML.
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000349//===----------------------------------------------------------------------===//
350
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000351CXString clang_HTMLTagComment_getAsString(CXComment CXC) {
352 const HTMLTagComment *HTC = getASTNodeAs<HTMLTagComment>(CXC);
353 if (!HTC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000354 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000355
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000356 CXTranslationUnit TU = CXC.TranslationUnit;
357 if (!TU->CommentToXML)
358 TU->CommentToXML = new index::CommentToXMLConverter();
359
360 SmallString<128> Text;
361 TU->CommentToXML->convertHTMLTagNodeToText(
362 HTC, Text, cxtu::getASTUnit(TU)->getASTContext());
363 return cxstring::createDup(Text.str());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000364}
365
366CXString clang_FullComment_getAsHTML(CXComment CXC) {
367 const FullComment *FC = getASTNodeAs<FullComment>(CXC);
368 if (!FC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000369 return cxstring::createNull();
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000370
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000371 CXTranslationUnit TU = CXC.TranslationUnit;
372 if (!TU->CommentToXML)
373 TU->CommentToXML = new index::CommentToXMLConverter();
374
Dmitri Gribenko4c6d7a22012-07-21 01:47:43 +0000375 SmallString<1024> HTML;
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000376 TU->CommentToXML
377 ->convertCommentToHTML(FC, HTML, cxtu::getASTUnit(TU)->getASTContext());
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000378 return cxstring::createDup(HTML.str());
Dmitri Gribenko5e4fe002012-07-20 21:34:34 +0000379}
380
Dmitri Gribenko7acbf002012-09-10 20:32:42 +0000381CXString clang_FullComment_getAsXML(CXComment CXC) {
Dmitri Gribenko740c0fb2012-08-07 17:54:38 +0000382 const FullComment *FC = getASTNodeAs<FullComment>(CXC);
383 if (!FC)
Dmitri Gribenkof98dfba2013-02-01 14:13:32 +0000384 return cxstring::createNull();
Dmitri Gribenkoba82fea2013-01-26 21:39:50 +0000385
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000386 CXTranslationUnit TU = CXC.TranslationUnit;
387 if (!TU->CommentToXML)
388 TU->CommentToXML = new index::CommentToXMLConverter();
Dmitri Gribenko740c0fb2012-08-07 17:54:38 +0000389
390 SmallString<1024> XML;
Dmitri Gribenko9e605112013-11-13 22:16:51 +0000391 TU->CommentToXML
392 ->convertCommentToXML(FC, XML, cxtu::getASTUnit(TU)->getASTContext());
Dmitri Gribenko2f23e9c2013-02-02 02:19:29 +0000393 return cxstring::createDup(XML.str());
Dmitri Gribenko740c0fb2012-08-07 17:54:38 +0000394}
395
396} // end extern "C"
397