CXComment.cpp revision 86cfda2fcccc84e92fb7f27e85b58312440ca8de
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
25using namespace clang;
26using 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
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
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())
90    return createCXComment(NULL, NULL);
91
92  return createCXComment(*(C->child_begin() + ChildIdx), CXC.TranslationUnit);
93}
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)
120    return cxstring::createNull();
121
122  return cxstring::createRef(TC->getText());
123}
124
125CXString 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
134enum 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
156unsigned 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())
168    return cxstring::createNull();
169
170  return cxstring::createRef(ICC->getArgText(ArgIdx));
171}
172
173CXString 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
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())
200    return cxstring::createNull();
201
202  return cxstring::createRef(HST->getAttr(AttrIdx).Name);
203}
204
205CXString 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
213CXString 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
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())
234    return cxstring::createNull();
235
236  return cxstring::createRef(BCC->getArgText(ArgIdx));
237}
238
239CXComment 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
247CXString 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
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);
265  if (!PCC || !PCC->isParamIndexValid() || PCC->isVarArgParam())
266    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
298CXString 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
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
330CXString 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
339CXString 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
351CXString 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 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
366CXString 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 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
381CXString 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 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