blob: b04a3cfdc844be08635b5696c742d135e650bb48 [file] [log] [blame]
Stephen Kellyd8744a72018-12-05 21:12:39 +00001//===--- TextNodeDumper.cpp - Printing of AST nodes -----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements AST dumping of components of individual AST nodes.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/TextNodeDumper.h"
15
16using namespace clang;
17
18TextNodeDumper::TextNodeDumper(raw_ostream &OS, bool ShowColors,
19 const SourceManager *SM,
Stephen Kellye26a88a2018-12-09 13:30:17 +000020 const PrintingPolicy &PrintPolicy,
21 const comments::CommandTraits *Traits)
Stephen Kellyb6d674f2019-01-08 22:32:48 +000022 : TextTreeStructure(OS, ShowColors), OS(OS), ShowColors(ShowColors), SM(SM),
23 PrintPolicy(PrintPolicy), Traits(Traits) {}
Stephen Kellye26a88a2018-12-09 13:30:17 +000024
25void TextNodeDumper::Visit(const comments::Comment *C,
26 const comments::FullComment *FC) {
27 if (!C) {
28 ColorScope Color(OS, ShowColors, NullColor);
29 OS << "<<<NULL>>>";
30 return;
31 }
32
33 {
34 ColorScope Color(OS, ShowColors, CommentColor);
35 OS << C->getCommentKindName();
36 }
37 dumpPointer(C);
38 dumpSourceRange(C->getSourceRange());
39
40 ConstCommentVisitor<TextNodeDumper, void,
41 const comments::FullComment *>::visit(C, FC);
42}
Stephen Kellyd8744a72018-12-05 21:12:39 +000043
44void TextNodeDumper::dumpPointer(const void *Ptr) {
45 ColorScope Color(OS, ShowColors, AddressColor);
46 OS << ' ' << Ptr;
47}
48
49void TextNodeDumper::dumpLocation(SourceLocation Loc) {
50 if (!SM)
51 return;
52
53 ColorScope Color(OS, ShowColors, LocationColor);
54 SourceLocation SpellingLoc = SM->getSpellingLoc(Loc);
55
56 // The general format we print out is filename:line:col, but we drop pieces
57 // that haven't changed since the last loc printed.
58 PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc);
59
60 if (PLoc.isInvalid()) {
61 OS << "<invalid sloc>";
62 return;
63 }
64
65 if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) {
66 OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':'
67 << PLoc.getColumn();
68 LastLocFilename = PLoc.getFilename();
69 LastLocLine = PLoc.getLine();
70 } else if (PLoc.getLine() != LastLocLine) {
71 OS << "line" << ':' << PLoc.getLine() << ':' << PLoc.getColumn();
72 LastLocLine = PLoc.getLine();
73 } else {
74 OS << "col" << ':' << PLoc.getColumn();
75 }
76}
77
78void TextNodeDumper::dumpSourceRange(SourceRange R) {
79 // Can't translate locations if a SourceManager isn't available.
80 if (!SM)
81 return;
82
83 OS << " <";
84 dumpLocation(R.getBegin());
85 if (R.getBegin() != R.getEnd()) {
86 OS << ", ";
87 dumpLocation(R.getEnd());
88 }
89 OS << ">";
90
91 // <t2.c:123:421[blah], t2.c:412:321>
92}
93
94void TextNodeDumper::dumpBareType(QualType T, bool Desugar) {
95 ColorScope Color(OS, ShowColors, TypeColor);
96
97 SplitQualType T_split = T.split();
98 OS << "'" << QualType::getAsString(T_split, PrintPolicy) << "'";
99
100 if (Desugar && !T.isNull()) {
101 // If the type is sugared, also dump a (shallow) desugared type.
102 SplitQualType D_split = T.getSplitDesugaredType();
103 if (T_split != D_split)
104 OS << ":'" << QualType::getAsString(D_split, PrintPolicy) << "'";
105 }
106}
107
108void TextNodeDumper::dumpType(QualType T) {
109 OS << ' ';
110 dumpBareType(T);
111}
112
113void TextNodeDumper::dumpBareDeclRef(const Decl *D) {
114 if (!D) {
115 ColorScope Color(OS, ShowColors, NullColor);
116 OS << "<<<NULL>>>";
117 return;
118 }
119
120 {
121 ColorScope Color(OS, ShowColors, DeclKindNameColor);
122 OS << D->getDeclKindName();
123 }
124 dumpPointer(D);
125
126 if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
127 ColorScope Color(OS, ShowColors, DeclNameColor);
128 OS << " '" << ND->getDeclName() << '\'';
129 }
130
131 if (const ValueDecl *VD = dyn_cast<ValueDecl>(D))
132 dumpType(VD->getType());
133}
134
135void TextNodeDumper::dumpName(const NamedDecl *ND) {
136 if (ND->getDeclName()) {
137 ColorScope Color(OS, ShowColors, DeclNameColor);
138 OS << ' ' << ND->getNameAsString();
139 }
140}
141
142void TextNodeDumper::dumpAccessSpecifier(AccessSpecifier AS) {
143 switch (AS) {
144 case AS_none:
145 break;
146 case AS_public:
147 OS << "public";
148 break;
149 case AS_protected:
150 OS << "protected";
151 break;
152 case AS_private:
153 OS << "private";
154 break;
155 }
156}
157
158void TextNodeDumper::dumpCXXTemporary(const CXXTemporary *Temporary) {
159 OS << "(CXXTemporary";
160 dumpPointer(Temporary);
161 OS << ")";
162}
Stephen Kellye26a88a2018-12-09 13:30:17 +0000163
Stephen Kellyd186dbc2019-01-08 23:11:24 +0000164void TextNodeDumper::dumpDeclRef(const Decl *D, const char *Label) {
165 if (!D)
166 return;
167
168 addChild([=] {
169 if (Label)
170 OS << Label << ' ';
171 dumpBareDeclRef(D);
172 });
173}
174
Stephen Kellye26a88a2018-12-09 13:30:17 +0000175const char *TextNodeDumper::getCommandName(unsigned CommandID) {
176 if (Traits)
177 return Traits->getCommandInfo(CommandID)->Name;
178 const comments::CommandInfo *Info =
179 comments::CommandTraits::getBuiltinCommandInfo(CommandID);
180 if (Info)
181 return Info->Name;
182 return "<not a builtin command>";
183}
184
185void TextNodeDumper::visitTextComment(const comments::TextComment *C,
186 const comments::FullComment *) {
187 OS << " Text=\"" << C->getText() << "\"";
188}
189
190void TextNodeDumper::visitInlineCommandComment(
191 const comments::InlineCommandComment *C, const comments::FullComment *) {
192 OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
193 switch (C->getRenderKind()) {
194 case comments::InlineCommandComment::RenderNormal:
195 OS << " RenderNormal";
196 break;
197 case comments::InlineCommandComment::RenderBold:
198 OS << " RenderBold";
199 break;
200 case comments::InlineCommandComment::RenderMonospaced:
201 OS << " RenderMonospaced";
202 break;
203 case comments::InlineCommandComment::RenderEmphasized:
204 OS << " RenderEmphasized";
205 break;
206 }
207
208 for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
209 OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
210}
211
212void TextNodeDumper::visitHTMLStartTagComment(
213 const comments::HTMLStartTagComment *C, const comments::FullComment *) {
214 OS << " Name=\"" << C->getTagName() << "\"";
215 if (C->getNumAttrs() != 0) {
216 OS << " Attrs: ";
217 for (unsigned i = 0, e = C->getNumAttrs(); i != e; ++i) {
218 const comments::HTMLStartTagComment::Attribute &Attr = C->getAttr(i);
219 OS << " \"" << Attr.Name << "=\"" << Attr.Value << "\"";
220 }
221 }
222 if (C->isSelfClosing())
223 OS << " SelfClosing";
224}
225
226void TextNodeDumper::visitHTMLEndTagComment(
227 const comments::HTMLEndTagComment *C, const comments::FullComment *) {
228 OS << " Name=\"" << C->getTagName() << "\"";
229}
230
231void TextNodeDumper::visitBlockCommandComment(
232 const comments::BlockCommandComment *C, const comments::FullComment *) {
233 OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
234 for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
235 OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
236}
237
238void TextNodeDumper::visitParamCommandComment(
239 const comments::ParamCommandComment *C, const comments::FullComment *FC) {
240 OS << " "
241 << comments::ParamCommandComment::getDirectionAsString(C->getDirection());
242
243 if (C->isDirectionExplicit())
244 OS << " explicitly";
245 else
246 OS << " implicitly";
247
248 if (C->hasParamName()) {
249 if (C->isParamIndexValid())
250 OS << " Param=\"" << C->getParamName(FC) << "\"";
251 else
252 OS << " Param=\"" << C->getParamNameAsWritten() << "\"";
253 }
254
255 if (C->isParamIndexValid() && !C->isVarArgParam())
256 OS << " ParamIndex=" << C->getParamIndex();
257}
258
259void TextNodeDumper::visitTParamCommandComment(
260 const comments::TParamCommandComment *C, const comments::FullComment *FC) {
261 if (C->hasParamName()) {
262 if (C->isPositionValid())
263 OS << " Param=\"" << C->getParamName(FC) << "\"";
264 else
265 OS << " Param=\"" << C->getParamNameAsWritten() << "\"";
266 }
267
268 if (C->isPositionValid()) {
269 OS << " Position=<";
270 for (unsigned i = 0, e = C->getDepth(); i != e; ++i) {
271 OS << C->getIndex(i);
272 if (i != e - 1)
273 OS << ", ";
274 }
275 OS << ">";
276 }
277}
278
279void TextNodeDumper::visitVerbatimBlockComment(
280 const comments::VerbatimBlockComment *C, const comments::FullComment *) {
281 OS << " Name=\"" << getCommandName(C->getCommandID())
282 << "\""
283 " CloseName=\""
284 << C->getCloseName() << "\"";
285}
286
287void TextNodeDumper::visitVerbatimBlockLineComment(
288 const comments::VerbatimBlockLineComment *C,
289 const comments::FullComment *) {
290 OS << " Text=\"" << C->getText() << "\"";
291}
292
293void TextNodeDumper::visitVerbatimLineComment(
294 const comments::VerbatimLineComment *C, const comments::FullComment *) {
295 OS << " Text=\"" << C->getText() << "\"";
296}