CXComment.cpp revision 262e60c1ccb5197e8e2ea49ada1196ed65183734
1ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko//===- CXComment.cpp - libclang APIs for manipulating CXComments ----------===//
2ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko//
3ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko//                     The LLVM Compiler Infrastructure
4ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko//
5ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko// This file is distributed under the University of Illinois Open Source
6ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko// License. See LICENSE.TXT for details.
7ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko//
8ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko//===----------------------------------------------------------------------===//
9ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko//
10ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko// This file defines all libclang APIs related to walking comment AST.
11ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko//
12ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko//===----------------------------------------------------------------------===//
13ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
14ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko#include "clang-c/Index.h"
15ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko#include "CXString.h"
16ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko#include "CXComment.h"
17f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko#include "CXCursor.h"
18ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
191bfb00dabf83d8c8b95b7276b4c0ae3fd64832c8Fariborz Jahanian#include "clang/AST/PrettyPrinter.h"
20ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko#include "clang/AST/CommentVisitor.h"
21d1db12540e572d6e3d998a4b770a6b2c7267d7fcDmitri Gribenko#include "clang/AST/CommentCommandTraits.h"
22f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko#include "clang/AST/Decl.h"
23ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
24f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko#include "llvm/ADT/StringSwitch.h"
25ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko#include "llvm/Support/ErrorHandling.h"
263e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko#include "llvm/Support/raw_ostream.h"
27ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
28221a6d74d48fb3eaa73b68eb04f253080bedd5fdDmitri Gribenko#include <climits>
29221a6d74d48fb3eaa73b68eb04f253080bedd5fdDmitri Gribenko
30ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkousing namespace clang;
31ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkousing namespace clang::cxstring;
32ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkousing namespace clang::comments;
33ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkousing namespace clang::cxcomment;
34ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
35ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkoextern "C" {
36ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
37ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkoenum CXCommentKind clang_Comment_getKind(CXComment CXC) {
38ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const Comment *C = getASTNode(CXC);
39ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!C)
40ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return CXComment_Null;
41ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
42ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  switch (C->getCommentKind()) {
43ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  case Comment::NoCommentKind:
44ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return CXComment_Null;
45ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
46ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  case Comment::TextCommentKind:
47ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return CXComment_Text;
48ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
49ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  case Comment::InlineCommandCommentKind:
50ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return CXComment_InlineCommand;
51ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
52ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  case Comment::HTMLStartTagCommentKind:
53ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return CXComment_HTMLStartTag;
54ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
55ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  case Comment::HTMLEndTagCommentKind:
56ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return CXComment_HTMLEndTag;
57ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
58ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  case Comment::ParagraphCommentKind:
59ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return CXComment_Paragraph;
60ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
61ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  case Comment::BlockCommandCommentKind:
62ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return CXComment_BlockCommand;
63ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
64ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  case Comment::ParamCommandCommentKind:
65ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return CXComment_ParamCommand;
66ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
6796b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  case Comment::TParamCommandCommentKind:
6896b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    return CXComment_TParamCommand;
6996b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko
70ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  case Comment::VerbatimBlockCommentKind:
71ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return CXComment_VerbatimBlockCommand;
72ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
73ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  case Comment::VerbatimBlockLineCommentKind:
74ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return CXComment_VerbatimBlockLine;
75ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
76ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  case Comment::VerbatimLineCommentKind:
77ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return CXComment_VerbatimLine;
78ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
79ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  case Comment::FullCommentKind:
80ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return CXComment_FullComment;
81ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  }
82ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  llvm_unreachable("unknown CommentKind");
83ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
84ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
85ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkounsigned clang_Comment_getNumChildren(CXComment CXC) {
86ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const Comment *C = getASTNode(CXC);
87ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!C)
88ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return 0;
89ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
90ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  return C->child_count();
91ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
92ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
93ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri GribenkoCXComment clang_Comment_getChild(CXComment CXC, unsigned ChildIdx) {
94ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const Comment *C = getASTNode(CXC);
95ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!C || ChildIdx >= C->child_count())
96e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko    return createCXComment(NULL, NULL);
97ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
98e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko  return createCXComment(*(C->child_begin() + ChildIdx), CXC.TranslationUnit);
99ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
100ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
101ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkounsigned clang_Comment_isWhitespace(CXComment CXC) {
102ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const Comment *C = getASTNode(CXC);
103ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!C)
104ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return false;
105ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
106ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (const TextComment *TC = dyn_cast<TextComment>(C))
107ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return TC->isWhitespace();
108ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
109ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (const ParagraphComment *PC = dyn_cast<ParagraphComment>(C))
110ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return PC->isWhitespace();
111ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
112ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  return false;
113ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
114ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
115ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkounsigned clang_InlineContentComment_hasTrailingNewline(CXComment CXC) {
116ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const InlineContentComment *ICC = getASTNodeAs<InlineContentComment>(CXC);
117ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!ICC)
118ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return false;
119ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
120ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  return ICC->hasTrailingNewline();
121ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
122ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
123ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri GribenkoCXString clang_TextComment_getText(CXComment CXC) {
124ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const TextComment *TC = getASTNodeAs<TextComment>(CXC);
125ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!TC)
126ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return createCXString((const char *) 0);
127ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
128ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  return createCXString(TC->getText(), /*DupString=*/ false);
129ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
130ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
131ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri GribenkoCXString clang_InlineCommandComment_getCommandName(CXComment CXC) {
132ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
133ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!ICC)
134ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return createCXString((const char *) 0);
135ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
136e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko  const CommandTraits &Traits = getCommandTraits(CXC);
137e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko  return createCXString(ICC->getCommandName(Traits), /*DupString=*/ false);
138ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
139ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
1402d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenkoenum CXCommentInlineCommandRenderKind
1412d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenkoclang_InlineCommandComment_getRenderKind(CXComment CXC) {
1422d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko  const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
1432d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko  if (!ICC)
1442d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko    return CXCommentInlineCommandRenderKind_Normal;
1452d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko
1462d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko  switch (ICC->getRenderKind()) {
1472d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko  case InlineCommandComment::RenderNormal:
1482d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko    return CXCommentInlineCommandRenderKind_Normal;
1492d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko
1502d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko  case InlineCommandComment::RenderBold:
1512d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko    return CXCommentInlineCommandRenderKind_Bold;
1522d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko
1532d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko  case InlineCommandComment::RenderMonospaced:
1542d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko    return CXCommentInlineCommandRenderKind_Monospaced;
1552d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko
1562d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko  case InlineCommandComment::RenderEmphasized:
1572d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko    return CXCommentInlineCommandRenderKind_Emphasized;
1582d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko  }
1592d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko  llvm_unreachable("unknown InlineCommandComment::RenderKind");
1602d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko}
1612d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko
162ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkounsigned clang_InlineCommandComment_getNumArgs(CXComment CXC) {
163ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
164ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!ICC)
165ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return 0;
166ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
167ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  return ICC->getNumArgs();
168ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
169ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
170ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri GribenkoCXString clang_InlineCommandComment_getArgText(CXComment CXC,
171ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko                                               unsigned ArgIdx) {
172ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
173ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!ICC || ArgIdx >= ICC->getNumArgs())
174ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return createCXString((const char *) 0);
175ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
176ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  return createCXString(ICC->getArgText(ArgIdx), /*DupString=*/ false);
177ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
178ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
179ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri GribenkoCXString clang_HTMLTagComment_getTagName(CXComment CXC) {
180ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const HTMLTagComment *HTC = getASTNodeAs<HTMLTagComment>(CXC);
181ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!HTC)
182ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return createCXString((const char *) 0);
183ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
184ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  return createCXString(HTC->getTagName(), /*DupString=*/ false);
185ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
186ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
187ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkounsigned clang_HTMLStartTagComment_isSelfClosing(CXComment CXC) {
188ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
189ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!HST)
190ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return false;
191ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
192ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  return HST->isSelfClosing();
193ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
194ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
195ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkounsigned clang_HTMLStartTag_getNumAttrs(CXComment CXC) {
196ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
197ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!HST)
198ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return 0;
199ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
200ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  return HST->getNumAttrs();
201ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
202ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
203ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri GribenkoCXString clang_HTMLStartTag_getAttrName(CXComment CXC, unsigned AttrIdx) {
204ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
205ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!HST || AttrIdx >= HST->getNumAttrs())
206ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return createCXString((const char *) 0);
207ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
208ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  return createCXString(HST->getAttr(AttrIdx).Name, /*DupString=*/ false);
209ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
210ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
211ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri GribenkoCXString clang_HTMLStartTag_getAttrValue(CXComment CXC, unsigned AttrIdx) {
212ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
213ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!HST || AttrIdx >= HST->getNumAttrs())
214ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return createCXString((const char *) 0);
215ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
216ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  return createCXString(HST->getAttr(AttrIdx).Value, /*DupString=*/ false);
217ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
218ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
219ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri GribenkoCXString clang_BlockCommandComment_getCommandName(CXComment CXC) {
220ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
221ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!BCC)
222ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return createCXString((const char *) 0);
223ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
224e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko  const CommandTraits &Traits = getCommandTraits(CXC);
225e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko  return createCXString(BCC->getCommandName(Traits), /*DupString=*/ false);
226ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
227ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
228ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkounsigned clang_BlockCommandComment_getNumArgs(CXComment CXC) {
229ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
230ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!BCC)
231ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return 0;
232ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
233ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  return BCC->getNumArgs();
234ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
235ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
236ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri GribenkoCXString clang_BlockCommandComment_getArgText(CXComment CXC,
237ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko                                              unsigned ArgIdx) {
238ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
239ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!BCC || ArgIdx >= BCC->getNumArgs())
240ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return createCXString((const char *) 0);
241ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
242ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  return createCXString(BCC->getArgText(ArgIdx), /*DupString=*/ false);
243ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
244ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
245ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri GribenkoCXComment clang_BlockCommandComment_getParagraph(CXComment CXC) {
246ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
247ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!BCC)
248e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko    return createCXComment(NULL, NULL);
249ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
250e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko  return createCXComment(BCC->getParagraph(), CXC.TranslationUnit);
251ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
252ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
253ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri GribenkoCXString clang_ParamCommandComment_getParamName(CXComment CXC) {
254ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
2551f8c529a2a938a5055f440aa063ea0b49eafae98Dmitri Gribenko  if (!PCC || !PCC->hasParamName())
256ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return createCXString((const char *) 0);
257ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
258262e60c1ccb5197e8e2ea49ada1196ed65183734Fariborz Jahanian  return createCXString(PCC->getParamNameAsWritten(), /*DupString=*/ false);
259ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
260ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
261ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkounsigned clang_ParamCommandComment_isParamIndexValid(CXComment CXC) {
262ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
263ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!PCC)
264ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return false;
265ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
266ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  return PCC->isParamIndexValid();
267ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
268ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
269ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkounsigned clang_ParamCommandComment_getParamIndex(CXComment CXC) {
270ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
271b740316a122b5ceaaa7cf50557b1b39af5fbbf5fDmitri Gribenko  if (!PCC || !PCC->isParamIndexValid())
272ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return ParamCommandComment::InvalidParamIndex;
273ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
274ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  return PCC->getParamIndex();
275ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
276ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
277ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkounsigned clang_ParamCommandComment_isDirectionExplicit(CXComment CXC) {
278ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
279ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!PCC)
280ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return false;
281ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
282ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  return PCC->isDirectionExplicit();
283ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
284ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
285ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkoenum CXCommentParamPassDirection clang_ParamCommandComment_getDirection(
286ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko                                                            CXComment CXC) {
287ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
288ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!PCC)
289ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return CXCommentParamPassDirection_In;
290ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
291ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  switch (PCC->getDirection()) {
292ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  case ParamCommandComment::In:
293ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return CXCommentParamPassDirection_In;
294ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
295ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  case ParamCommandComment::Out:
296ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return CXCommentParamPassDirection_Out;
297ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
298ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  case ParamCommandComment::InOut:
299ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return CXCommentParamPassDirection_InOut;
300ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  }
301ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  llvm_unreachable("unknown ParamCommandComment::PassDirection");
302ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
303ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
30496b098674908eaa59a9128f3305cda6fbbdad563Dmitri GribenkoCXString clang_TParamCommandComment_getParamName(CXComment CXC) {
30596b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
30696b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  if (!TPCC || !TPCC->hasParamName())
30796b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    return createCXString((const char *) 0);
30896b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko
309262e60c1ccb5197e8e2ea49ada1196ed65183734Fariborz Jahanian  return createCXString(TPCC->getParamNameAsWritten(), /*DupString=*/ false);
31096b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko}
31196b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko
31296b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenkounsigned clang_TParamCommandComment_isParamPositionValid(CXComment CXC) {
31396b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
31496b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  if (!TPCC)
31596b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    return false;
31696b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko
31796b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  return TPCC->isPositionValid();
31896b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko}
31996b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko
32096b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenkounsigned clang_TParamCommandComment_getDepth(CXComment CXC) {
32196b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
32296b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  if (!TPCC || !TPCC->isPositionValid())
32396b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    return 0;
32496b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko
32596b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  return TPCC->getDepth();
32696b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko}
32796b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko
32896b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenkounsigned clang_TParamCommandComment_getIndex(CXComment CXC, unsigned Depth) {
32996b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
33096b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  if (!TPCC || !TPCC->isPositionValid() || Depth >= TPCC->getDepth())
33196b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    return 0;
33296b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko
33396b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  return TPCC->getIndex(Depth);
33496b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko}
33596b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko
336ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri GribenkoCXString clang_VerbatimBlockLineComment_getText(CXComment CXC) {
337ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const VerbatimBlockLineComment *VBL =
338ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko      getASTNodeAs<VerbatimBlockLineComment>(CXC);
339ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!VBL)
340ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return createCXString((const char *) 0);
341ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
342ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  return createCXString(VBL->getText(), /*DupString=*/ false);
343ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
344ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
345ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri GribenkoCXString clang_VerbatimLineComment_getText(CXComment CXC) {
346ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const VerbatimLineComment *VLC = getASTNodeAs<VerbatimLineComment>(CXC);
347ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!VLC)
348ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return createCXString((const char *) 0);
349ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
350ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  return createCXString(VLC->getText(), /*DupString=*/ false);
351ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
352ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
353ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko} // end extern "C"
354ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
355ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko//===----------------------------------------------------------------------===//
356ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko// Helpers for converting comment AST to HTML.
357ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko//===----------------------------------------------------------------------===//
358ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
359ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkonamespace {
360ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
361e5db09cf6772332c14dc7dc541de53f918f89125Dmitri Gribenko/// This comparison will sort parameters with valid index by index and
362e5db09cf6772332c14dc7dc541de53f918f89125Dmitri Gribenko/// invalid (unresolved) parameters last.
363ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkoclass ParamCommandCommentCompareIndex {
364ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkopublic:
365ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  bool operator()(const ParamCommandComment *LHS,
366ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko                  const ParamCommandComment *RHS) const {
367b740316a122b5ceaaa7cf50557b1b39af5fbbf5fDmitri Gribenko    unsigned LHSIndex = UINT_MAX;
368b740316a122b5ceaaa7cf50557b1b39af5fbbf5fDmitri Gribenko    unsigned RHSIndex = UINT_MAX;
369b740316a122b5ceaaa7cf50557b1b39af5fbbf5fDmitri Gribenko    if (LHS->isParamIndexValid())
370b740316a122b5ceaaa7cf50557b1b39af5fbbf5fDmitri Gribenko      LHSIndex = LHS->getParamIndex();
371b740316a122b5ceaaa7cf50557b1b39af5fbbf5fDmitri Gribenko    if (RHS->isParamIndexValid())
372b740316a122b5ceaaa7cf50557b1b39af5fbbf5fDmitri Gribenko      RHSIndex = RHS->getParamIndex();
373b740316a122b5ceaaa7cf50557b1b39af5fbbf5fDmitri Gribenko
374b740316a122b5ceaaa7cf50557b1b39af5fbbf5fDmitri Gribenko    return LHSIndex < RHSIndex;
375ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  }
376ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko};
377ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
37896b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko/// This comparison will sort template parameters in the following order:
37996b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko/// \li real template parameters (depth = 1) in index order;
38096b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko/// \li all other names (depth > 1);
38196b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko/// \li unresolved names.
38296b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenkoclass TParamCommandCommentComparePosition {
38396b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenkopublic:
38496b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  bool operator()(const TParamCommandComment *LHS,
38596b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko                  const TParamCommandComment *RHS) const {
38696b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    // Sort unresolved names last.
38796b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    if (!LHS->isPositionValid())
38896b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko      return false;
38996b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    if (!RHS->isPositionValid())
39096b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko      return true;
39196b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko
39296b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    if (LHS->getDepth() > 1)
39396b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko      return false;
39496b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    if (RHS->getDepth() > 1)
39596b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko      return true;
39696b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko
39796b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    // Sort template parameters in index order.
39896b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    if (LHS->getDepth() == 1 && RHS->getDepth() == 1)
39996b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko      return LHS->getIndex(0) < RHS->getIndex(0);
40096b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko
40196b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    // Leave all other names in source order.
40296b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    return true;
40396b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  }
40496b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko};
40596b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko
4062ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko/// Separate parts of a FullComment.
4072ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenkostruct FullCommentParts {
4082ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  /// Take a full comment apart and initialize members accordingly.
409e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko  FullCommentParts(const FullComment *C,
410e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko                   const CommandTraits &Traits);
4112ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko
4122ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  const BlockContentComment *Brief;
4132ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  const ParagraphComment *FirstParagraph;
4142ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  const BlockCommandComment *Returns;
4152ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  SmallVector<const ParamCommandComment *, 8> Params;
4162ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  SmallVector<const TParamCommandComment *, 4> TParams;
4172ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  SmallVector<const BlockContentComment *, 8> MiscBlocks;
4182ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko};
4192ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko
420e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri GribenkoFullCommentParts::FullCommentParts(const FullComment *C,
421e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko                                   const CommandTraits &Traits) :
4222ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    Brief(NULL), FirstParagraph(NULL), Returns(NULL) {
4232ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
4242ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko       I != E; ++I) {
4252ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    const Comment *Child = *I;
4262ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    if (!Child)
4272ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      continue;
4282ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    switch (Child->getCommentKind()) {
4292ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    case Comment::NoCommentKind:
4302ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      continue;
4312ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko
4322ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    case Comment::ParagraphCommentKind: {
4332ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      const ParagraphComment *PC = cast<ParagraphComment>(Child);
4342ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      if (PC->isWhitespace())
4352ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko        break;
4362ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      if (!FirstParagraph)
4372ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko        FirstParagraph = PC;
4382ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko
4392ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      MiscBlocks.push_back(PC);
4402ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      break;
4412ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    }
4422ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko
4432ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    case Comment::BlockCommandCommentKind: {
4442ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      const BlockCommandComment *BCC = cast<BlockCommandComment>(Child);
445e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko      const CommandInfo *Info = Traits.getCommandInfo(BCC->getCommandID());
446e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko      if (!Brief && Info->IsBriefCommand) {
4472ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko        Brief = BCC;
4482ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko        break;
4492ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      }
450e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko      if (!Returns && Info->IsReturnsCommand) {
4512ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko        Returns = BCC;
4522ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko        break;
4532ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      }
4542ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      MiscBlocks.push_back(BCC);
4552ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      break;
4562ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    }
4572ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko
4582ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    case Comment::ParamCommandCommentKind: {
4592ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      const ParamCommandComment *PCC = cast<ParamCommandComment>(Child);
4602ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      if (!PCC->hasParamName())
4612ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko        break;
4622ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko
4632ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      if (!PCC->isDirectionExplicit() && !PCC->hasNonWhitespaceParagraph())
4642ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko        break;
4652ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko
4662ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      Params.push_back(PCC);
4672ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      break;
4682ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    }
4692ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko
4702ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    case Comment::TParamCommandCommentKind: {
4712ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      const TParamCommandComment *TPCC = cast<TParamCommandComment>(Child);
4722ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      if (!TPCC->hasParamName())
4732ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko        break;
4742ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko
4752ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      if (!TPCC->hasNonWhitespaceParagraph())
4762ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko        break;
4772ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko
4782ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      TParams.push_back(TPCC);
4792ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      break;
4802ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    }
4812ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko
4822ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    case Comment::VerbatimBlockCommentKind:
4832ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      MiscBlocks.push_back(cast<BlockCommandComment>(Child));
4842ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      break;
4852ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko
48662290ae569016345b79d4e11dd93abc300e5a681Dmitri Gribenko    case Comment::VerbatimLineCommentKind: {
48762290ae569016345b79d4e11dd93abc300e5a681Dmitri Gribenko      const VerbatimLineComment *VLC = cast<VerbatimLineComment>(Child);
488e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko      const CommandInfo *Info = Traits.getCommandInfo(VLC->getCommandID());
489e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko      if (!Info->IsDeclarationCommand)
49062290ae569016345b79d4e11dd93abc300e5a681Dmitri Gribenko        MiscBlocks.push_back(VLC);
49162290ae569016345b79d4e11dd93abc300e5a681Dmitri Gribenko      break;
49262290ae569016345b79d4e11dd93abc300e5a681Dmitri Gribenko    }
49362290ae569016345b79d4e11dd93abc300e5a681Dmitri Gribenko
4942ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    case Comment::TextCommentKind:
4952ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    case Comment::InlineCommandCommentKind:
4962ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    case Comment::HTMLStartTagCommentKind:
4972ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    case Comment::HTMLEndTagCommentKind:
4982ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    case Comment::VerbatimBlockLineCommentKind:
4992ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    case Comment::FullCommentKind:
5002ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      llvm_unreachable("AST node of this kind can't be a child of "
5012ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko                       "a FullComment");
5022ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    }
5032ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  }
5042ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko
5052ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  // Sort params in order they are declared in the function prototype.
5062ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  // Unresolved parameters are put at the end of the list in the same order
5072ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  // they were seen in the comment.
5082ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  std::stable_sort(Params.begin(), Params.end(),
5092ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko                   ParamCommandCommentCompareIndex());
5102ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko
5112ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  std::stable_sort(TParams.begin(), TParams.end(),
5122ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko                   TParamCommandCommentComparePosition());
5132ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko}
5142ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko
5152ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenkovoid PrintHTMLStartTagComment(const HTMLStartTagComment *C,
5162ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko                              llvm::raw_svector_ostream &Result) {
5172ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  Result << "<" << C->getTagName();
5182ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko
5192ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  if (C->getNumAttrs() != 0) {
5202ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    for (unsigned i = 0, e = C->getNumAttrs(); i != e; i++) {
5212ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      Result << " ";
5222ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      const HTMLStartTagComment::Attribute &Attr = C->getAttr(i);
5232ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      Result << Attr.Name;
5242ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      if (!Attr.Value.empty())
5252ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko        Result << "=\"" << Attr.Value << "\"";
5262ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    }
5272ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  }
5282ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko
5292ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  if (!C->isSelfClosing())
5302ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    Result << ">";
5312ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  else
5322ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    Result << "/>";
5332ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko}
5342ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko
535ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkoclass CommentASTToHTMLConverter :
536ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    public ConstCommentVisitor<CommentASTToHTMLConverter> {
537ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkopublic:
5383e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko  /// \param Str accumulator for HTML.
539bf967be66ea8c51b66c61659c23240f762a56dbeFariborz Jahanian  CommentASTToHTMLConverter(FullComment *FC,
540bf967be66ea8c51b66c61659c23240f762a56dbeFariborz Jahanian                            SmallVectorImpl<char> &Str,
541e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko                            const CommandTraits &Traits) :
542bf967be66ea8c51b66c61659c23240f762a56dbeFariborz Jahanian      FC(FC), Result(Str), Traits(Traits)
543e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko  { }
544ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
545ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  // Inline content.
546ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  void visitTextComment(const TextComment *C);
547ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  void visitInlineCommandComment(const InlineCommandComment *C);
548ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  void visitHTMLStartTagComment(const HTMLStartTagComment *C);
549ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  void visitHTMLEndTagComment(const HTMLEndTagComment *C);
550ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
551ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  // Block content.
552ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  void visitParagraphComment(const ParagraphComment *C);
553ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  void visitBlockCommandComment(const BlockCommandComment *C);
554ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  void visitParamCommandComment(const ParamCommandComment *C);
55596b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  void visitTParamCommandComment(const TParamCommandComment *C);
556ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  void visitVerbatimBlockComment(const VerbatimBlockComment *C);
557ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C);
558ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  void visitVerbatimLineComment(const VerbatimLineComment *C);
559ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
560ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  void visitFullComment(const FullComment *C);
561ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
562ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  // Helpers.
563ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
564ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  /// Convert a paragraph that is not a block by itself (an argument to some
565ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  /// command).
566ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  void visitNonStandaloneParagraphComment(const ParagraphComment *C);
567ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
568ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  void appendToResultWithHTMLEscaping(StringRef S);
569ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
570ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkoprivate:
571bf967be66ea8c51b66c61659c23240f762a56dbeFariborz Jahanian  FullComment *FC;
5723e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko  /// Output stream for HTML.
5733e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko  llvm::raw_svector_ostream Result;
574e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko
575e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko  const CommandTraits &Traits;
576ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko};
577ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko} // end unnamed namespace
578ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
579ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkovoid CommentASTToHTMLConverter::visitTextComment(const TextComment *C) {
580ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  appendToResultWithHTMLEscaping(C->getText());
581ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
582ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
583ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkovoid CommentASTToHTMLConverter::visitInlineCommandComment(
584ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko                                  const InlineCommandComment *C) {
5852d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko  // Nothing to render if no arguments supplied.
5862d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko  if (C->getNumArgs() == 0)
5872d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko    return;
5882d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko
5892d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko  // Nothing to render if argument is empty.
5902d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko  StringRef Arg0 = C->getArgText(0);
5912d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko  if (Arg0.empty())
5922d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko    return;
5932d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko
5942d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko  switch (C->getRenderKind()) {
5952d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko  case InlineCommandComment::RenderNormal:
59659500fec689f7def27bb83bd21e19417ad527906Dmitri Gribenko    for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) {
59759500fec689f7def27bb83bd21e19417ad527906Dmitri Gribenko      appendToResultWithHTMLEscaping(C->getArgText(i));
59859500fec689f7def27bb83bd21e19417ad527906Dmitri Gribenko      Result << " ";
59959500fec689f7def27bb83bd21e19417ad527906Dmitri Gribenko    }
6002d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko    return;
6012d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko
6022d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko  case InlineCommandComment::RenderBold:
6032d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko    assert(C->getNumArgs() == 1);
60459500fec689f7def27bb83bd21e19417ad527906Dmitri Gribenko    Result << "<b>";
60559500fec689f7def27bb83bd21e19417ad527906Dmitri Gribenko    appendToResultWithHTMLEscaping(Arg0);
60659500fec689f7def27bb83bd21e19417ad527906Dmitri Gribenko    Result << "</b>";
607ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return;
6082d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko  case InlineCommandComment::RenderMonospaced:
6092d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko    assert(C->getNumArgs() == 1);
61059500fec689f7def27bb83bd21e19417ad527906Dmitri Gribenko    Result << "<tt>";
61159500fec689f7def27bb83bd21e19417ad527906Dmitri Gribenko    appendToResultWithHTMLEscaping(Arg0);
61259500fec689f7def27bb83bd21e19417ad527906Dmitri Gribenko    Result<< "</tt>";
613ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return;
6142d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko  case InlineCommandComment::RenderEmphasized:
6152d66a5016d4aacce362f89290261c8a1a6eef0d3Dmitri Gribenko    assert(C->getNumArgs() == 1);
61659500fec689f7def27bb83bd21e19417ad527906Dmitri Gribenko    Result << "<em>";
61759500fec689f7def27bb83bd21e19417ad527906Dmitri Gribenko    appendToResultWithHTMLEscaping(Arg0);
61859500fec689f7def27bb83bd21e19417ad527906Dmitri Gribenko    Result << "</em>";
619ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return;
620ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  }
621ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
622ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
623ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkovoid CommentASTToHTMLConverter::visitHTMLStartTagComment(
624ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko                                  const HTMLStartTagComment *C) {
6252ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  PrintHTMLStartTagComment(C, Result);
626ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
627ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
628ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkovoid CommentASTToHTMLConverter::visitHTMLEndTagComment(
629ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko                                  const HTMLEndTagComment *C) {
6303e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko  Result << "</" << C->getTagName() << ">";
631ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
632ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
633ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkovoid CommentASTToHTMLConverter::visitParagraphComment(
634ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko                                  const ParagraphComment *C) {
635ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (C->isWhitespace())
636ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return;
637ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
6383e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko  Result << "<p>";
639ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
640ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko       I != E; ++I) {
641ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    visit(*I);
642ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  }
6433e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko  Result << "</p>";
644ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
645ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
646ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkovoid CommentASTToHTMLConverter::visitBlockCommandComment(
647ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko                                  const BlockCommandComment *C) {
648e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko  const CommandInfo *Info = Traits.getCommandInfo(C->getCommandID());
649e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko  if (Info->IsBriefCommand) {
6503e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko    Result << "<p class=\"para-brief\">";
651ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    visitNonStandaloneParagraphComment(C->getParagraph());
6523e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko    Result << "</p>";
653ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return;
654ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  }
655e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko  if (Info->IsReturnsCommand) {
6563e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko    Result << "<p class=\"para-returns\">"
6573e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko              "<span class=\"word-returns\">Returns</span> ";
658ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    visitNonStandaloneParagraphComment(C->getParagraph());
6593e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko    Result << "</p>";
660ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return;
661ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  }
662ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  // We don't know anything about this command.  Just render the paragraph.
663ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  visit(C->getParagraph());
664ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
665ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
666ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkovoid CommentASTToHTMLConverter::visitParamCommandComment(
667ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko                                  const ParamCommandComment *C) {
6683e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko  if (C->isParamIndexValid()) {
6693e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko    Result << "<dt class=\"param-name-index-"
6703e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko           << C->getParamIndex()
6713e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko           << "\">";
672262e60c1ccb5197e8e2ea49ada1196ed65183734Fariborz Jahanian    appendToResultWithHTMLEscaping(C->getParamName(FC));
673262e60c1ccb5197e8e2ea49ada1196ed65183734Fariborz Jahanian  } else {
6743e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko    Result << "<dt class=\"param-name-index-invalid\">";
675262e60c1ccb5197e8e2ea49ada1196ed65183734Fariborz Jahanian    appendToResultWithHTMLEscaping(C->getParamNameAsWritten());
676262e60c1ccb5197e8e2ea49ada1196ed65183734Fariborz Jahanian  }
67759500fec689f7def27bb83bd21e19417ad527906Dmitri Gribenko  Result << "</dt>";
6783e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko
6793e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko  if (C->isParamIndexValid()) {
6803e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko    Result << "<dd class=\"param-descr-index-"
6813e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko           << C->getParamIndex()
6823e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko           << "\">";
6833e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko  } else
6843e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko    Result << "<dd class=\"param-descr-index-invalid\">";
6853e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko
686ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  visitNonStandaloneParagraphComment(C->getParagraph());
6873e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko  Result << "</dd>";
688ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
689ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
69096b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenkovoid CommentASTToHTMLConverter::visitTParamCommandComment(
69196b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko                                  const TParamCommandComment *C) {
69296b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  if (C->isPositionValid()) {
69396b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    if (C->getDepth() == 1)
6946a425525e52aba5a8e14db35d50a712be4e5e2e1Dmitri Gribenko      Result << "<dt class=\"tparam-name-index-"
69596b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko             << C->getIndex(0)
69696b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko             << "\">";
69796b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    else
6986a425525e52aba5a8e14db35d50a712be4e5e2e1Dmitri Gribenko      Result << "<dt class=\"tparam-name-index-other\">";
699262e60c1ccb5197e8e2ea49ada1196ed65183734Fariborz Jahanian    appendToResultWithHTMLEscaping(C->getParamName(FC));
700262e60c1ccb5197e8e2ea49ada1196ed65183734Fariborz Jahanian  } else {
70196b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    Result << "<dt class=\"tparam-name-index-invalid\">";
702262e60c1ccb5197e8e2ea49ada1196ed65183734Fariborz Jahanian    appendToResultWithHTMLEscaping(C->getParamNameAsWritten());
703262e60c1ccb5197e8e2ea49ada1196ed65183734Fariborz Jahanian  }
704262e60c1ccb5197e8e2ea49ada1196ed65183734Fariborz Jahanian
70559500fec689f7def27bb83bd21e19417ad527906Dmitri Gribenko  Result << "</dt>";
70696b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko
70796b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  if (C->isPositionValid()) {
70896b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    if (C->getDepth() == 1)
70996b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko      Result << "<dd class=\"tparam-descr-index-"
71096b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko             << C->getIndex(0)
71196b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko             << "\">";
71296b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    else
71396b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko      Result << "<dd class=\"tparam-descr-index-other\">";
71496b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  } else
71596b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    Result << "<dd class=\"tparam-descr-index-invalid\">";
71696b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko
71796b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  visitNonStandaloneParagraphComment(C->getParagraph());
71896b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  Result << "</dd>";
71996b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko}
72096b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko
721ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkovoid CommentASTToHTMLConverter::visitVerbatimBlockComment(
722ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko                                  const VerbatimBlockComment *C) {
723ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  unsigned NumLines = C->getNumLines();
724ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (NumLines == 0)
725ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return;
726ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
7273e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko  Result << "<pre>";
728ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  for (unsigned i = 0; i != NumLines; ++i) {
729ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    appendToResultWithHTMLEscaping(C->getText(i));
730ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    if (i + 1 != NumLines)
7313e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko      Result << '\n';
732ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  }
7333e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko  Result << "</pre>";
734ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
735ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
736ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkovoid CommentASTToHTMLConverter::visitVerbatimBlockLineComment(
737ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko                                  const VerbatimBlockLineComment *C) {
738ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  llvm_unreachable("should not see this AST node");
739ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
740ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
741ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkovoid CommentASTToHTMLConverter::visitVerbatimLineComment(
742ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko                                  const VerbatimLineComment *C) {
7433e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko  Result << "<pre>";
744ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  appendToResultWithHTMLEscaping(C->getText());
7453e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko  Result << "</pre>";
746ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
747ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
748ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkovoid CommentASTToHTMLConverter::visitFullComment(const FullComment *C) {
749e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko  FullCommentParts Parts(C, Traits);
75096b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko
751ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  bool FirstParagraphIsBrief = false;
7522ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  if (Parts.Brief)
7532ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    visit(Parts.Brief);
7542ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  else if (Parts.FirstParagraph) {
7553e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko    Result << "<p class=\"para-brief\">";
7562ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    visitNonStandaloneParagraphComment(Parts.FirstParagraph);
7573e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko    Result << "</p>";
758ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    FirstParagraphIsBrief = true;
759ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  }
760ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
7612ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  for (unsigned i = 0, e = Parts.MiscBlocks.size(); i != e; ++i) {
7622ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    const Comment *C = Parts.MiscBlocks[i];
7632ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    if (FirstParagraphIsBrief && C == Parts.FirstParagraph)
764ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko      continue;
765ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    visit(C);
766ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  }
767ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
7682ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  if (Parts.TParams.size() != 0) {
76996b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    Result << "<dl>";
7702ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    for (unsigned i = 0, e = Parts.TParams.size(); i != e; ++i)
7712ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      visit(Parts.TParams[i]);
77296b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko    Result << "</dl>";
77396b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko  }
77496b098674908eaa59a9128f3305cda6fbbdad563Dmitri Gribenko
7752ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  if (Parts.Params.size() != 0) {
7763e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko    Result << "<dl>";
7772ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    for (unsigned i = 0, e = Parts.Params.size(); i != e; ++i)
7782ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko      visit(Parts.Params[i]);
7793e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko    Result << "</dl>";
780ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  }
781ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
7822ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko  if (Parts.Returns)
7832ff84b514e53f4273c7067a5aade680a155a9045Dmitri Gribenko    visit(Parts.Returns);
7843e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko
7853e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko  Result.flush();
786ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
787ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
788ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkovoid CommentASTToHTMLConverter::visitNonStandaloneParagraphComment(
789ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko                                  const ParagraphComment *C) {
790ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!C)
791ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return;
792ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
793ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
794ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko       I != E; ++I) {
795ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    visit(*I);
796ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  }
797ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
798ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
799ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkovoid CommentASTToHTMLConverter::appendToResultWithHTMLEscaping(StringRef S) {
800ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I) {
801ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    const char C = *I;
802ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    switch (C) {
803ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko      case '&':
8043e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko        Result << "&amp;";
805ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko        break;
806ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko      case '<':
8073e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko        Result << "&lt;";
808ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko        break;
809ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko      case '>':
8103e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko        Result << "&gt;";
811ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko        break;
812ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko      case '"':
8133e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko        Result << "&quot;";
814ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko        break;
815ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko      case '\'':
8163e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko        Result << "&#39;";
817ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko        break;
818ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko      case '/':
8193e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko        Result << "&#47;";
820ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko        break;
821ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko      default:
8223e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko        Result << C;
823ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko        break;
824ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    }
825ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  }
826ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
827ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
828ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenkoextern "C" {
829ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
830ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri GribenkoCXString clang_HTMLTagComment_getAsString(CXComment CXC) {
831ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const HTMLTagComment *HTC = getASTNodeAs<HTMLTagComment>(CXC);
832ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!HTC)
833ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return createCXString((const char *) 0);
834ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
8353e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko  SmallString<128> HTML;
836bf967be66ea8c51b66c61659c23240f762a56dbeFariborz Jahanian  CommentASTToHTMLConverter Converter(0, HTML, getCommandTraits(CXC));
837ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  Converter.visit(HTC);
8383e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko  return createCXString(HTML.str(), /* DupString = */ true);
839ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
840ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
841ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri GribenkoCXString clang_FullComment_getAsHTML(CXComment CXC) {
842ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  const FullComment *FC = getASTNodeAs<FullComment>(CXC);
843ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  if (!FC)
844ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko    return createCXString((const char *) 0);
845ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
8463e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko  SmallString<1024> HTML;
847bf967be66ea8c51b66c61659c23240f762a56dbeFariborz Jahanian  CommentASTToHTMLConverter Converter(const_cast<FullComment *>(FC),
848bf967be66ea8c51b66c61659c23240f762a56dbeFariborz Jahanian                                      HTML, getCommandTraits(CXC));
849ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko  Converter.visit(FC);
8503e63d332baf0d3b8a5c0b7c2dac2ae85615b1d47Dmitri Gribenko  return createCXString(HTML.str(), /* DupString = */ true);
851ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko}
852ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
853ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko} // end extern "C"
854ae99b75fbbac1deaccdcc1b326b8fb6b07a1e72dDmitri Gribenko
855f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenkonamespace {
856f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenkoclass CommentASTToXMLConverter :
857f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    public ConstCommentVisitor<CommentASTToXMLConverter> {
858f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenkopublic:
859f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  /// \param Str accumulator for XML.
860bf967be66ea8c51b66c61659c23240f762a56dbeFariborz Jahanian  CommentASTToXMLConverter(FullComment *FC,
861bf967be66ea8c51b66c61659c23240f762a56dbeFariborz Jahanian                           SmallVectorImpl<char> &Str,
862e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko                           const CommandTraits &Traits,
863e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko                           const SourceManager &SM) :
864bf967be66ea8c51b66c61659c23240f762a56dbeFariborz Jahanian      FC(FC), Result(Str), Traits(Traits), SM(SM) { }
865f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
866f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  // Inline content.
867f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  void visitTextComment(const TextComment *C);
868f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  void visitInlineCommandComment(const InlineCommandComment *C);
869f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  void visitHTMLStartTagComment(const HTMLStartTagComment *C);
870f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  void visitHTMLEndTagComment(const HTMLEndTagComment *C);
871f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
872f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  // Block content.
873f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  void visitParagraphComment(const ParagraphComment *C);
874f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  void visitBlockCommandComment(const BlockCommandComment *C);
875f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  void visitParamCommandComment(const ParamCommandComment *C);
876f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  void visitTParamCommandComment(const TParamCommandComment *C);
877f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  void visitVerbatimBlockComment(const VerbatimBlockComment *C);
878f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C);
879f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  void visitVerbatimLineComment(const VerbatimLineComment *C);
880f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
881f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  void visitFullComment(const FullComment *C);
882f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
883f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  // Helpers.
884f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  void appendToResultWithXMLEscaping(StringRef S);
885f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
886f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenkoprivate:
887bf967be66ea8c51b66c61659c23240f762a56dbeFariborz Jahanian  FullComment *FC;
888bf967be66ea8c51b66c61659c23240f762a56dbeFariborz Jahanian
889f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  /// Output stream for XML.
890f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  llvm::raw_svector_ostream Result;
891e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko
892e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko  const CommandTraits &Traits;
893e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko  const SourceManager &SM;
894f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko};
895f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko} // end unnamed namespace
896f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
897f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenkovoid CommentASTToXMLConverter::visitTextComment(const TextComment *C) {
898f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  appendToResultWithXMLEscaping(C->getText());
899f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko}
900f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
901f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenkovoid CommentASTToXMLConverter::visitInlineCommandComment(const InlineCommandComment *C) {
902f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  // Nothing to render if no arguments supplied.
903f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  if (C->getNumArgs() == 0)
904f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    return;
905f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
906f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  // Nothing to render if argument is empty.
907f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  StringRef Arg0 = C->getArgText(0);
908f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  if (Arg0.empty())
909f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    return;
910f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
911f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  switch (C->getRenderKind()) {
912f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  case InlineCommandComment::RenderNormal:
913f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) {
914f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      appendToResultWithXMLEscaping(C->getArgText(i));
915f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      Result << " ";
916f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    }
917f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    return;
918f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  case InlineCommandComment::RenderBold:
919f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    assert(C->getNumArgs() == 1);
920f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "<bold>";
921f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    appendToResultWithXMLEscaping(Arg0);
922f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "</bold>";
923f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    return;
924f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  case InlineCommandComment::RenderMonospaced:
925f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    assert(C->getNumArgs() == 1);
926f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "<monospaced>";
927f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    appendToResultWithXMLEscaping(Arg0);
928f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "</monospaced>";
929f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    return;
930f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  case InlineCommandComment::RenderEmphasized:
931f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    assert(C->getNumArgs() == 1);
932f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "<emphasized>";
933f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    appendToResultWithXMLEscaping(Arg0);
934f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "</emphasized>";
935f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    return;
936f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  }
937f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko}
938f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
939f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenkovoid CommentASTToXMLConverter::visitHTMLStartTagComment(const HTMLStartTagComment *C) {
940f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  Result << "<rawHTML><![CDATA[";
941f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  PrintHTMLStartTagComment(C, Result);
942f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  Result << "]]></rawHTML>";
943f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko}
944f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
945f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenkovoid CommentASTToXMLConverter::visitHTMLEndTagComment(const HTMLEndTagComment *C) {
946f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  Result << "<rawHTML>&lt;/" << C->getTagName() << "&gt;</rawHTML>";
947f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko}
948f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
949f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenkovoid CommentASTToXMLConverter::visitParagraphComment(const ParagraphComment *C) {
950f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  if (C->isWhitespace())
951f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    return;
952f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
953f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  Result << "<Para>";
954f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
955f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko       I != E; ++I) {
956f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    visit(*I);
957f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  }
958f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  Result << "</Para>";
959f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko}
960f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
961f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenkovoid CommentASTToXMLConverter::visitBlockCommandComment(const BlockCommandComment *C) {
962f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  visit(C->getParagraph());
963f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko}
964f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
965f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenkovoid CommentASTToXMLConverter::visitParamCommandComment(const ParamCommandComment *C) {
966f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  Result << "<Parameter><Name>";
967262e60c1ccb5197e8e2ea49ada1196ed65183734Fariborz Jahanian  appendToResultWithXMLEscaping(C->isParamIndexValid() ? C->getParamName(FC)
968262e60c1ccb5197e8e2ea49ada1196ed65183734Fariborz Jahanian                                                       : C->getParamNameAsWritten());
969f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  Result << "</Name>";
970f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
971f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  if (C->isParamIndexValid())
972f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "<Index>" << C->getParamIndex() << "</Index>";
973f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
974f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  Result << "<Direction isExplicit=\"" << C->isDirectionExplicit() << "\">";
975f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  switch (C->getDirection()) {
976f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  case ParamCommandComment::In:
977f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "in";
978f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    break;
979f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  case ParamCommandComment::Out:
980f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "out";
981f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    break;
982f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  case ParamCommandComment::InOut:
983f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "in,out";
984f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    break;
985f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  }
986f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  Result << "</Direction><Discussion>";
987f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  visit(C->getParagraph());
988f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  Result << "</Discussion></Parameter>";
989f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko}
990f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
991f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenkovoid CommentASTToXMLConverter::visitTParamCommandComment(
992f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko                                  const TParamCommandComment *C) {
993f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  Result << "<Parameter><Name>";
994262e60c1ccb5197e8e2ea49ada1196ed65183734Fariborz Jahanian  appendToResultWithXMLEscaping(C->isPositionValid() ? C->getParamName(FC)
995262e60c1ccb5197e8e2ea49ada1196ed65183734Fariborz Jahanian                                : C->getParamNameAsWritten());
996f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  Result << "</Name>";
997f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
998f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  if (C->isPositionValid() && C->getDepth() == 1) {
999f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "<Index>" << C->getIndex(0) << "</Index>";
1000f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  }
1001f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1002f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  Result << "<Discussion>";
1003f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  visit(C->getParagraph());
1004f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  Result << "</Discussion></Parameter>";
1005f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko}
1006f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1007f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenkovoid CommentASTToXMLConverter::visitVerbatimBlockComment(
1008f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko                                  const VerbatimBlockComment *C) {
1009f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  unsigned NumLines = C->getNumLines();
1010f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  if (NumLines == 0)
1011f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    return;
1012f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1013e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko  Result << llvm::StringSwitch<const char *>(C->getCommandName(Traits))
10146cd4420945489e7331012103048f162288a6c7d8Dmitri Gribenko      .Case("code", "<Verbatim xml:space=\"preserve\" kind=\"code\">")
10156cd4420945489e7331012103048f162288a6c7d8Dmitri Gribenko      .Default("<Verbatim xml:space=\"preserve\" kind=\"verbatim\">");
1016f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  for (unsigned i = 0; i != NumLines; ++i) {
1017f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    appendToResultWithXMLEscaping(C->getText(i));
1018f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    if (i + 1 != NumLines)
1019f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      Result << '\n';
1020f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  }
1021f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  Result << "</Verbatim>";
1022f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko}
1023f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1024f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenkovoid CommentASTToXMLConverter::visitVerbatimBlockLineComment(
1025f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko                                  const VerbatimBlockLineComment *C) {
1026f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  llvm_unreachable("should not see this AST node");
1027f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko}
1028f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1029f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenkovoid CommentASTToXMLConverter::visitVerbatimLineComment(
1030f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko                                  const VerbatimLineComment *C) {
10316cd4420945489e7331012103048f162288a6c7d8Dmitri Gribenko  Result << "<Verbatim xml:space=\"preserve\" kind=\"verbatim\">";
1032f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  appendToResultWithXMLEscaping(C->getText());
1033f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  Result << "</Verbatim>";
1034f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko}
1035f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1036922fbc41e496c6bb843de5d4cbe26d54f1ecdedfNAKAMURA Takumistatic std::string getSourceTextOfDeclaration(const DeclInfo *ThisDecl) {
10371bfb00dabf83d8c8b95b7276b4c0ae3fd64832c8Fariborz Jahanian
10381bfb00dabf83d8c8b95b7276b4c0ae3fd64832c8Fariborz Jahanian  ASTContext &Context = ThisDecl->CurrentDecl->getASTContext();
10391bfb00dabf83d8c8b95b7276b4c0ae3fd64832c8Fariborz Jahanian  const LangOptions &LangOpts = Context.getLangOpts();
10401bfb00dabf83d8c8b95b7276b4c0ae3fd64832c8Fariborz Jahanian  std::string SStr;
10411bfb00dabf83d8c8b95b7276b4c0ae3fd64832c8Fariborz Jahanian  llvm::raw_string_ostream S(SStr);
10421bfb00dabf83d8c8b95b7276b4c0ae3fd64832c8Fariborz Jahanian  PrintingPolicy PPolicy(LangOpts);
10431bfb00dabf83d8c8b95b7276b4c0ae3fd64832c8Fariborz Jahanian  PPolicy.SuppressAttributes = true;
10441bfb00dabf83d8c8b95b7276b4c0ae3fd64832c8Fariborz Jahanian  PPolicy.TerseOutput = true;
10451bfb00dabf83d8c8b95b7276b4c0ae3fd64832c8Fariborz Jahanian  ThisDecl->CurrentDecl->print(S, PPolicy,
10461bfb00dabf83d8c8b95b7276b4c0ae3fd64832c8Fariborz Jahanian                               /*Indentation*/0, /*PrintInstantiation*/true);
10471bfb00dabf83d8c8b95b7276b4c0ae3fd64832c8Fariborz Jahanian  return S.str();
10481bfb00dabf83d8c8b95b7276b4c0ae3fd64832c8Fariborz Jahanian}
10491bfb00dabf83d8c8b95b7276b4c0ae3fd64832c8Fariborz Jahanian
1050f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenkovoid CommentASTToXMLConverter::visitFullComment(const FullComment *C) {
1051e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko  FullCommentParts Parts(C, Traits);
1052f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1053f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  const DeclInfo *DI = C->getDeclInfo();
1054f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  StringRef RootEndTag;
1055f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  if (DI) {
1056f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    switch (DI->getKind()) {
1057f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    case DeclInfo::OtherKind:
1058f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      RootEndTag = "</Other>";
1059f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      Result << "<Other";
1060f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      break;
1061f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    case DeclInfo::FunctionKind:
1062f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      RootEndTag = "</Function>";
1063f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      Result << "<Function";
1064f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      switch (DI->TemplateKind) {
1065f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      case DeclInfo::NotTemplate:
1066f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        break;
1067f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      case DeclInfo::Template:
1068f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        Result << " templateKind=\"template\"";
1069f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        break;
1070f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      case DeclInfo::TemplateSpecialization:
1071f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        Result << " templateKind=\"specialization\"";
1072f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        break;
1073f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      case DeclInfo::TemplatePartialSpecialization:
1074f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        llvm_unreachable("partial specializations of functions "
1075f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko                         "are not allowed in C++");
1076f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      }
1077f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      if (DI->IsInstanceMethod)
1078f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        Result << " isInstanceMethod=\"1\"";
1079f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      if (DI->IsClassMethod)
1080f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        Result << " isClassMethod=\"1\"";
1081f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      break;
1082f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    case DeclInfo::ClassKind:
1083f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      RootEndTag = "</Class>";
1084f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      Result << "<Class";
1085f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      switch (DI->TemplateKind) {
1086f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      case DeclInfo::NotTemplate:
1087f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        break;
1088f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      case DeclInfo::Template:
1089f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        Result << " templateKind=\"template\"";
1090f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        break;
1091f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      case DeclInfo::TemplateSpecialization:
1092f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        Result << " templateKind=\"specialization\"";
1093f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        break;
1094f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      case DeclInfo::TemplatePartialSpecialization:
1095f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        Result << " templateKind=\"partialSpecialization\"";
1096f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        break;
1097f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      }
1098f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      break;
1099f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    case DeclInfo::VariableKind:
1100f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      RootEndTag = "</Variable>";
1101f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      Result << "<Variable";
1102f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      break;
1103f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    case DeclInfo::NamespaceKind:
1104f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      RootEndTag = "</Namespace>";
1105f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      Result << "<Namespace";
1106f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      break;
1107f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    case DeclInfo::TypedefKind:
1108f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      RootEndTag = "</Typedef>";
1109f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      Result << "<Typedef";
1110f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      break;
1111cff339a60a571a606a7510548f661dc6a719368dDmitri Gribenko    case DeclInfo::EnumKind:
1112cff339a60a571a606a7510548f661dc6a719368dDmitri Gribenko      RootEndTag = "</Enum>";
1113cff339a60a571a606a7510548f661dc6a719368dDmitri Gribenko      Result << "<Enum";
1114cff339a60a571a606a7510548f661dc6a719368dDmitri Gribenko      break;
1115f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    }
1116f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1117f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    {
1118f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      // Print line and column number.
11191bfb00dabf83d8c8b95b7276b4c0ae3fd64832c8Fariborz Jahanian      SourceLocation Loc = DI->CurrentDecl->getLocation();
1120f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
1121f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      FileID FID = LocInfo.first;
1122f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      unsigned FileOffset = LocInfo.second;
1123f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1124f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      if (!FID.isInvalid()) {
1125f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        if (const FileEntry *FE = SM.getFileEntryForID(FID)) {
1126f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko          Result << " file=\"";
1127f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko          appendToResultWithXMLEscaping(FE->getName());
1128f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko          Result << "\"";
1129f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        }
1130f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        Result << " line=\"" << SM.getLineNumber(FID, FileOffset)
1131f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko               << "\" column=\"" << SM.getColumnNumber(FID, FileOffset)
1132f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko               << "\"";
1133f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      }
1134f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    }
1135f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1136f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    // Finish the root tag.
1137f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << ">";
1138f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1139f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    bool FoundName = false;
1140bf967be66ea8c51b66c61659c23240f762a56dbeFariborz Jahanian    if (const NamedDecl *ND = dyn_cast<NamedDecl>(DI->CommentDecl)) {
1141f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      if (DeclarationName DeclName = ND->getDeclName()) {
1142f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        Result << "<Name>";
1143f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        std::string Name = DeclName.getAsString();
1144f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        appendToResultWithXMLEscaping(Name);
1145f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        FoundName = true;
1146f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        Result << "</Name>";
1147f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      }
1148f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    }
1149f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    if (!FoundName)
1150f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      Result << "<Name>&lt;anonymous&gt;</Name>";
1151f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1152f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    {
1153f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      // Print USR.
1154f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      SmallString<128> USR;
1155bf967be66ea8c51b66c61659c23240f762a56dbeFariborz Jahanian      cxcursor::getDeclCursorUSR(DI->CommentDecl, USR);
1156f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      if (!USR.empty()) {
1157f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        Result << "<USR>";
1158f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        appendToResultWithXMLEscaping(USR);
1159f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        Result << "</USR>";
1160f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      }
1161f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    }
1162f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  } else {
1163f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    // No DeclInfo -- just emit some root tag and name tag.
1164f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    RootEndTag = "</Other>";
1165f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "<Other><Name>unknown</Name>";
1166f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  }
1167f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1168f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  bool FirstParagraphIsBrief = false;
11691bfb00dabf83d8c8b95b7276b4c0ae3fd64832c8Fariborz Jahanian  Result << "<Declaration>";
11701bfb00dabf83d8c8b95b7276b4c0ae3fd64832c8Fariborz Jahanian  appendToResultWithXMLEscaping(getSourceTextOfDeclaration(DI));
11711bfb00dabf83d8c8b95b7276b4c0ae3fd64832c8Fariborz Jahanian  Result << "</Declaration>";
11721bfb00dabf83d8c8b95b7276b4c0ae3fd64832c8Fariborz Jahanian
1173f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  if (Parts.Brief) {
1174f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "<Abstract>";
1175f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    visit(Parts.Brief);
1176f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "</Abstract>";
1177f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  } else if (Parts.FirstParagraph) {
1178f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "<Abstract>";
1179f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    visit(Parts.FirstParagraph);
1180f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "</Abstract>";
1181f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    FirstParagraphIsBrief = true;
1182f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  }
1183f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1184f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  if (Parts.TParams.size() != 0) {
1185f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "<TemplateParameters>";
1186f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    for (unsigned i = 0, e = Parts.TParams.size(); i != e; ++i)
1187f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      visit(Parts.TParams[i]);
1188f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "</TemplateParameters>";
1189f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  }
1190f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1191f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  if (Parts.Params.size() != 0) {
1192f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "<Parameters>";
1193f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    for (unsigned i = 0, e = Parts.Params.size(); i != e; ++i)
1194f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      visit(Parts.Params[i]);
1195f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "</Parameters>";
1196f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  }
1197f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1198f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  if (Parts.Returns) {
1199f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "<ResultDiscussion>";
1200f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    visit(Parts.Returns);
1201f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    Result << "</ResultDiscussion>";
1202f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  }
1203257e2e836160c7e55cf160b7cae8e5665f988a5eFariborz Jahanian
1204bf967be66ea8c51b66c61659c23240f762a56dbeFariborz Jahanian  if (DI->CommentDecl->hasAttrs()) {
1205bf967be66ea8c51b66c61659c23240f762a56dbeFariborz Jahanian    const AttrVec &Attrs = DI->CommentDecl->getAttrs();
1206faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian    for (unsigned i = 0, e = Attrs.size(); i != e; i++) {
1207faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian      const AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(Attrs[i]);
12082a46533633441176e93b484739a0a27e07150b63Fariborz Jahanian      if (!AA) {
12098da68b8b03d72314b67ea44568e013ef79d93b40Fariborz Jahanian        if (const DeprecatedAttr *DA = dyn_cast<DeprecatedAttr>(Attrs[i])) {
12108da68b8b03d72314b67ea44568e013ef79d93b40Fariborz Jahanian          if (DA->getMessage().empty())
12118da68b8b03d72314b67ea44568e013ef79d93b40Fariborz Jahanian            Result << "<Deprecated/>";
12128da68b8b03d72314b67ea44568e013ef79d93b40Fariborz Jahanian          else {
12137d9c975bf2ea8e607646e23c15da744490e10d5dDmitri Gribenko            Result << "<Deprecated>";
12147d9c975bf2ea8e607646e23c15da744490e10d5dDmitri Gribenko            appendToResultWithXMLEscaping(DA->getMessage());
12157d9c975bf2ea8e607646e23c15da744490e10d5dDmitri Gribenko            Result << "</Deprecated>";
12168da68b8b03d72314b67ea44568e013ef79d93b40Fariborz Jahanian          }
12178da68b8b03d72314b67ea44568e013ef79d93b40Fariborz Jahanian        }
12188da68b8b03d72314b67ea44568e013ef79d93b40Fariborz Jahanian        else if (const UnavailableAttr *UA = dyn_cast<UnavailableAttr>(Attrs[i])) {
12198da68b8b03d72314b67ea44568e013ef79d93b40Fariborz Jahanian          if (UA->getMessage().empty())
12208da68b8b03d72314b67ea44568e013ef79d93b40Fariborz Jahanian            Result << "<Unavailable/>";
12218da68b8b03d72314b67ea44568e013ef79d93b40Fariborz Jahanian          else {
12227d9c975bf2ea8e607646e23c15da744490e10d5dDmitri Gribenko            Result << "<Unavailable>";
12237d9c975bf2ea8e607646e23c15da744490e10d5dDmitri Gribenko            appendToResultWithXMLEscaping(UA->getMessage());
12247d9c975bf2ea8e607646e23c15da744490e10d5dDmitri Gribenko            Result << "</Unavailable>";
12258da68b8b03d72314b67ea44568e013ef79d93b40Fariborz Jahanian          }
12268da68b8b03d72314b67ea44568e013ef79d93b40Fariborz Jahanian        }
1227257e2e836160c7e55cf160b7cae8e5665f988a5eFariborz Jahanian        continue;
12282a46533633441176e93b484739a0a27e07150b63Fariborz Jahanian      }
1229faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian
1230faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian      // 'availability' attribute.
1231257e2e836160c7e55cf160b7cae8e5665f988a5eFariborz Jahanian      Result << "<Availability";
1232faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian      StringRef Distribution;
1233257e2e836160c7e55cf160b7cae8e5665f988a5eFariborz Jahanian      if (AA->getPlatform()) {
1234faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian        Distribution = AvailabilityAttr::getPrettyPlatformName(
1235faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian                                        AA->getPlatform()->getName());
1236faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian        if (Distribution.empty())
1237faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian          Distribution = AA->getPlatform()->getName();
1238257e2e836160c7e55cf160b7cae8e5665f988a5eFariborz Jahanian      }
1239faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian      Result << " distribution=\"" << Distribution << "\">";
1240257e2e836160c7e55cf160b7cae8e5665f988a5eFariborz Jahanian      VersionTuple IntroducedInVersion = AA->getIntroduced();
1241257e2e836160c7e55cf160b7cae8e5665f988a5eFariborz Jahanian      if (!IntroducedInVersion.empty()) {
1242faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian        Result << "<IntroducedInVersion>"
1243faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian               << IntroducedInVersion.getAsString()
1244faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian               << "</IntroducedInVersion>";
1245257e2e836160c7e55cf160b7cae8e5665f988a5eFariborz Jahanian      }
1246257e2e836160c7e55cf160b7cae8e5665f988a5eFariborz Jahanian      VersionTuple DeprecatedInVersion = AA->getDeprecated();
1247257e2e836160c7e55cf160b7cae8e5665f988a5eFariborz Jahanian      if (!DeprecatedInVersion.empty()) {
1248faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian        Result << "<DeprecatedInVersion>"
1249faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian               << DeprecatedInVersion.getAsString()
1250faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian               << "</DeprecatedInVersion>";
1251257e2e836160c7e55cf160b7cae8e5665f988a5eFariborz Jahanian      }
1252257e2e836160c7e55cf160b7cae8e5665f988a5eFariborz Jahanian      VersionTuple RemovedAfterVersion = AA->getObsoleted();
1253257e2e836160c7e55cf160b7cae8e5665f988a5eFariborz Jahanian      if (!RemovedAfterVersion.empty()) {
1254faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian        Result << "<RemovedAfterVersion>"
1255faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian               << RemovedAfterVersion.getAsString()
1256faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian               << "</RemovedAfterVersion>";
1257257e2e836160c7e55cf160b7cae8e5665f988a5eFariborz Jahanian      }
1258257e2e836160c7e55cf160b7cae8e5665f988a5eFariborz Jahanian      StringRef DeprecationSummary = AA->getMessage();
1259257e2e836160c7e55cf160b7cae8e5665f988a5eFariborz Jahanian      if (!DeprecationSummary.empty()) {
12607d9c975bf2ea8e607646e23c15da744490e10d5dDmitri Gribenko        Result << "<DeprecationSummary>";
12617d9c975bf2ea8e607646e23c15da744490e10d5dDmitri Gribenko        appendToResultWithXMLEscaping(DeprecationSummary);
12627d9c975bf2ea8e607646e23c15da744490e10d5dDmitri Gribenko        Result << "</DeprecationSummary>";
1263257e2e836160c7e55cf160b7cae8e5665f988a5eFariborz Jahanian      }
1264257e2e836160c7e55cf160b7cae8e5665f988a5eFariborz Jahanian      if (AA->getUnavailable())
12658da68b8b03d72314b67ea44568e013ef79d93b40Fariborz Jahanian        Result << "<Unavailable/>";
1266faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian      Result << "</Availability>";
1267257e2e836160c7e55cf160b7cae8e5665f988a5eFariborz Jahanian    }
1268257e2e836160c7e55cf160b7cae8e5665f988a5eFariborz Jahanian  }
1269faab5618b5beed350d7444de97cf513ef1a42ca6Fariborz Jahanian
1270f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  {
1271f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    bool StartTagEmitted = false;
1272f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    for (unsigned i = 0, e = Parts.MiscBlocks.size(); i != e; ++i) {
1273f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      const Comment *C = Parts.MiscBlocks[i];
1274f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      if (FirstParagraphIsBrief && C == Parts.FirstParagraph)
1275f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        continue;
1276f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      if (!StartTagEmitted) {
1277f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        Result << "<Discussion>";
1278f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        StartTagEmitted = true;
1279f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      }
1280f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      visit(C);
1281f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    }
1282f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    if (StartTagEmitted)
1283f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      Result << "</Discussion>";
1284f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  }
1285f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1286f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  Result << RootEndTag;
1287f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1288f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  Result.flush();
1289f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko}
1290f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1291f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenkovoid CommentASTToXMLConverter::appendToResultWithXMLEscaping(StringRef S) {
1292f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I) {
1293f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    const char C = *I;
1294f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    switch (C) {
1295f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      case '&':
1296f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        Result << "&amp;";
1297f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        break;
1298f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      case '<':
1299f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        Result << "&lt;";
1300f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        break;
1301f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      case '>':
1302f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        Result << "&gt;";
1303f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        break;
1304f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      case '"':
1305f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        Result << "&quot;";
1306f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        break;
1307f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      case '\'':
1308f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        Result << "&apos;";
1309f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        break;
1310f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko      default:
1311f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        Result << C;
1312f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko        break;
1313f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    }
1314f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  }
1315f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko}
1316f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1317f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenkoextern "C" {
1318f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1319e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri GribenkoCXString clang_FullComment_getAsXML(CXComment CXC) {
1320f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  const FullComment *FC = getASTNodeAs<FullComment>(CXC);
1321f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  if (!FC)
1322f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko    return createCXString((const char *) 0);
1323f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1324e4330a302ac20b41b9800267ebd4b5b01f8553f8Dmitri Gribenko  CXTranslationUnit TU = CXC.TranslationUnit;
1325f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  SourceManager &SM = static_cast<ASTUnit *>(TU->TUData)->getSourceManager();
1326f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1327f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  SmallString<1024> XML;
1328bf967be66ea8c51b66c61659c23240f762a56dbeFariborz Jahanian  CommentASTToXMLConverter Converter(const_cast<FullComment *>(FC), XML,
1329bf967be66ea8c51b66c61659c23240f762a56dbeFariborz Jahanian                                     getCommandTraits(CXC), SM);
1330f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  Converter.visit(FC);
1331f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko  return createCXString(XML.str(), /* DupString = */ true);
1332f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko}
1333f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1334f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko} // end extern "C"
1335f303d4cb10648ac9c2080ae7c9dd507ba615e3a7Dmitri Gribenko
1336