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
13 namespace clang {
14 namespace comments {
15
16 namespace {
17 class CommentDumper: public comments::ConstCommentVisitor<CommentDumper> {
18 raw_ostream &OS;
19 const CommandTraits *Traits;
20 const SourceManager *SM;
21 unsigned IndentLevel;
22
23 public:
CommentDumper(raw_ostream & OS,const CommandTraits * Traits,const SourceManager * SM)24 CommentDumper(raw_ostream &OS,
25 const CommandTraits *Traits,
26 const SourceManager *SM) :
27 OS(OS), Traits(Traits), SM(SM), IndentLevel(0)
28 { }
29
dumpIndent() const30 void dumpIndent() const {
31 for (unsigned i = 1, e = IndentLevel; i < e; ++i)
32 OS << " ";
33 }
34
dumpLocation(SourceLocation Loc)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
getCommandName(unsigned CommandID)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
dumpSourceRange(const Comment * C)73 void 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
dumpComment(const Comment * C)88 void CommentDumper::dumpComment(const Comment *C) {
89 dumpIndent();
90 OS << "(" << C->getCommentKindName()
91 << " " << (const void *) C;
92 dumpSourceRange(C);
93 }
94
dumpSubtree(const Comment * C)95 void 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
visitTextComment(const TextComment * C)113 void CommentDumper::visitTextComment(const TextComment *C) {
114 dumpComment(C);
115
116 OS << " Text=\"" << C->getText() << "\"";
117 }
118
visitInlineCommandComment(const InlineCommandComment * C)119 void 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
visitHTMLStartTagComment(const HTMLStartTagComment * C)142 void 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
visitHTMLEndTagComment(const HTMLEndTagComment * C)157 void CommentDumper::visitHTMLEndTagComment(const HTMLEndTagComment *C) {
158 dumpComment(C);
159
160 OS << " Name=\"" << C->getTagName() << "\"";
161 }
162
visitParagraphComment(const ParagraphComment * C)163 void CommentDumper::visitParagraphComment(const ParagraphComment *C) {
164 dumpComment(C);
165 }
166
visitBlockCommandComment(const BlockCommandComment * C)167 void 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
visitParamCommandComment(const ParamCommandComment * C)175 void 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
visitTParamCommandComment(const TParamCommandComment * C)192 void 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
visitVerbatimBlockComment(const VerbatimBlockComment * C)210 void CommentDumper::visitVerbatimBlockComment(const VerbatimBlockComment *C) {
211 dumpComment(C);
212
213 OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""
214 " CloseName=\"" << C->getCloseName() << "\"";
215 }
216
visitVerbatimBlockLineComment(const VerbatimBlockLineComment * C)217 void CommentDumper::visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C) {
218 dumpComment(C);
219
220 OS << " Text=\"" << C->getText() << "\"";
221 }
222
visitVerbatimLineComment(const VerbatimLineComment * C)223 void CommentDumper::visitVerbatimLineComment(const VerbatimLineComment *C) {
224 dumpComment(C);
225
226 OS << " Text=\"" << C->getText() << "\"";
227 }
228
visitFullComment(const FullComment * C)229 void CommentDumper::visitFullComment(const FullComment *C) {
230 dumpComment(C);
231 }
232
233 } // unnamed namespace
234
dump(llvm::raw_ostream & OS,const CommandTraits * Traits,const SourceManager * SM) const235 void 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