1//===--- CommentDumper.cpp - Dumping implementation for Comment ASTs ------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "clang/AST/CommentVisitor.h"
11#include "llvm/Support/raw_ostream.h"
12
13namespace clang {
14namespace comments {
15
16namespace {
17class CommentDumper: public comments::ConstCommentVisitor<CommentDumper> {
18  raw_ostream &OS;
19  const CommandTraits *Traits;
20  const SourceManager *SM;
21  unsigned IndentLevel;
22
23public:
24  CommentDumper(raw_ostream &OS,
25                const CommandTraits *Traits,
26                const SourceManager *SM) :
27      OS(OS), Traits(Traits), SM(SM), IndentLevel(0)
28  { }
29
30  void dumpIndent() const {
31    for (unsigned i = 1, e = IndentLevel; i < e; ++i)
32      OS << "  ";
33  }
34
35  void dumpLocation(SourceLocation Loc) {
36    if (SM)
37      Loc.print(OS, *SM);
38  }
39
40  void dumpSourceRange(const Comment *C);
41
42  void dumpComment(const Comment *C);
43
44  void dumpSubtree(const Comment *C);
45
46  // Inline content.
47  void visitTextComment(const TextComment *C);
48  void visitInlineCommandComment(const InlineCommandComment *C);
49  void visitHTMLStartTagComment(const HTMLStartTagComment *C);
50  void visitHTMLEndTagComment(const HTMLEndTagComment *C);
51
52  // Block content.
53  void visitParagraphComment(const ParagraphComment *C);
54  void visitBlockCommandComment(const BlockCommandComment *C);
55  void visitParamCommandComment(const ParamCommandComment *C);
56  void visitTParamCommandComment(const TParamCommandComment *C);
57  void visitVerbatimBlockComment(const VerbatimBlockComment *C);
58  void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C);
59  void visitVerbatimLineComment(const VerbatimLineComment *C);
60
61  void visitFullComment(const FullComment *C);
62
63  const char *getCommandName(unsigned CommandID) {
64    if (Traits)
65      return Traits->getCommandInfo(CommandID)->Name;
66    const CommandInfo *Info = CommandTraits::getBuiltinCommandInfo(CommandID);
67    if (Info)
68      return Info->Name;
69    return "<not a builtin command>";
70  }
71};
72
73void CommentDumper::dumpSourceRange(const Comment *C) {
74  if (!SM)
75    return;
76
77  SourceRange SR = C->getSourceRange();
78
79  OS << " <";
80  dumpLocation(SR.getBegin());
81  if (SR.getBegin() != SR.getEnd()) {
82    OS << ", ";
83    dumpLocation(SR.getEnd());
84  }
85  OS << ">";
86}
87
88void CommentDumper::dumpComment(const Comment *C) {
89  dumpIndent();
90  OS << "(" << C->getCommentKindName()
91     << " " << (const void *) C;
92  dumpSourceRange(C);
93}
94
95void CommentDumper::dumpSubtree(const Comment *C) {
96  ++IndentLevel;
97  if (C) {
98    visit(C);
99    for (Comment::child_iterator I = C->child_begin(),
100                                 E = C->child_end();
101         I != E; ++I) {
102      OS << '\n';
103      dumpSubtree(*I);
104    }
105    OS << ')';
106  } else {
107    dumpIndent();
108    OS << "<<<NULL>>>";
109  }
110  --IndentLevel;
111}
112
113void CommentDumper::visitTextComment(const TextComment *C) {
114  dumpComment(C);
115
116  OS << " Text=\"" << C->getText() << "\"";
117}
118
119void CommentDumper::visitInlineCommandComment(const InlineCommandComment *C) {
120  dumpComment(C);
121
122  OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
123  switch (C->getRenderKind()) {
124  case InlineCommandComment::RenderNormal:
125    OS << " RenderNormal";
126    break;
127  case InlineCommandComment::RenderBold:
128    OS << " RenderBold";
129    break;
130  case InlineCommandComment::RenderMonospaced:
131    OS << " RenderMonospaced";
132    break;
133  case InlineCommandComment::RenderEmphasized:
134    OS << " RenderEmphasized";
135    break;
136  }
137
138  for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
139    OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
140}
141
142void CommentDumper::visitHTMLStartTagComment(const HTMLStartTagComment *C) {
143  dumpComment(C);
144
145  OS << " Name=\"" << C->getTagName() << "\"";
146  if (C->getNumAttrs() != 0) {
147    OS << " Attrs: ";
148    for (unsigned i = 0, e = C->getNumAttrs(); i != e; ++i) {
149      const HTMLStartTagComment::Attribute &Attr = C->getAttr(i);
150      OS << " \"" << Attr.Name << "=\"" << Attr.Value << "\"";
151    }
152  }
153  if (C->isSelfClosing())
154    OS << " SelfClosing";
155}
156
157void CommentDumper::visitHTMLEndTagComment(const HTMLEndTagComment *C) {
158  dumpComment(C);
159
160  OS << " Name=\"" << C->getTagName() << "\"";
161}
162
163void CommentDumper::visitParagraphComment(const ParagraphComment *C) {
164  dumpComment(C);
165}
166
167void CommentDumper::visitBlockCommandComment(const BlockCommandComment *C) {
168  dumpComment(C);
169
170  OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
171  for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
172    OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
173}
174
175void CommentDumper::visitParamCommandComment(const ParamCommandComment *C) {
176  dumpComment(C);
177
178  OS << " " << ParamCommandComment::getDirectionAsString(C->getDirection());
179
180  if (C->isDirectionExplicit())
181    OS << " explicitly";
182  else
183    OS << " implicitly";
184
185  if (C->hasParamName())
186    OS << " Param=\"" << C->getParamName() << "\"";
187
188  if (C->isParamIndexValid())
189    OS << " ParamIndex=" << C->getParamIndex();
190}
191
192void CommentDumper::visitTParamCommandComment(const TParamCommandComment *C) {
193  dumpComment(C);
194
195  if (C->hasParamName()) {
196    OS << " Param=\"" << C->getParamName() << "\"";
197  }
198
199  if (C->isPositionValid()) {
200    OS << " Position=<";
201    for (unsigned i = 0, e = C->getDepth(); i != e; ++i) {
202      OS << C->getIndex(i);
203      if (i != e - 1)
204        OS << ", ";
205    }
206    OS << ">";
207  }
208}
209
210void CommentDumper::visitVerbatimBlockComment(const VerbatimBlockComment *C) {
211  dumpComment(C);
212
213  OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""
214        " CloseName=\"" << C->getCloseName() << "\"";
215}
216
217void CommentDumper::visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C) {
218  dumpComment(C);
219
220  OS << " Text=\"" << C->getText() << "\"";
221}
222
223void CommentDumper::visitVerbatimLineComment(const VerbatimLineComment *C) {
224  dumpComment(C);
225
226  OS << " Text=\"" << C->getText() << "\"";
227}
228
229void CommentDumper::visitFullComment(const FullComment *C) {
230  dumpComment(C);
231}
232
233} // unnamed namespace
234
235void Comment::dump(llvm::raw_ostream &OS, const CommandTraits *Traits,
236                   const SourceManager *SM) const {
237  CommentDumper D(llvm::errs(), Traits, SM);
238  D.dumpSubtree(this);
239  llvm::errs() << '\n';
240}
241
242} // end namespace comments
243} // end namespace clang
244
245