1 //===--- 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 16 using namespace clang; 17 18 TextNodeDumper::TextNodeDumper(raw_ostream &OS, bool ShowColors, 19 const SourceManager *SM, 20 const PrintingPolicy &PrintPolicy, 21 const comments::CommandTraits *Traits) 22 : TextTreeStructure(OS, ShowColors), OS(OS), ShowColors(ShowColors), SM(SM), 23 PrintPolicy(PrintPolicy), Traits(Traits) {} 24 25 void 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 } 43 44 void TextNodeDumper::dumpPointer(const void *Ptr) { 45 ColorScope Color(OS, ShowColors, AddressColor); 46 OS << ' ' << Ptr; 47 } 48 49 void 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 78 void 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 94 void 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 108 void TextNodeDumper::dumpType(QualType T) { 109 OS << ' '; 110 dumpBareType(T); 111 } 112 113 void 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 135 void TextNodeDumper::dumpName(const NamedDecl *ND) { 136 if (ND->getDeclName()) { 137 ColorScope Color(OS, ShowColors, DeclNameColor); 138 OS << ' ' << ND->getNameAsString(); 139 } 140 } 141 142 void 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 158 void TextNodeDumper::dumpCXXTemporary(const CXXTemporary *Temporary) { 159 OS << "(CXXTemporary"; 160 dumpPointer(Temporary); 161 OS << ")"; 162 } 163 164 void 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 175 const 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 185 void TextNodeDumper::visitTextComment(const comments::TextComment *C, 186 const comments::FullComment *) { 187 OS << " Text=\"" << C->getText() << "\""; 188 } 189 190 void 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 212 void 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 226 void TextNodeDumper::visitHTMLEndTagComment( 227 const comments::HTMLEndTagComment *C, const comments::FullComment *) { 228 OS << " Name=\"" << C->getTagName() << "\""; 229 } 230 231 void 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 238 void 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 259 void 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 279 void TextNodeDumper::visitVerbatimBlockComment( 280 const comments::VerbatimBlockComment *C, const comments::FullComment *) { 281 OS << " Name=\"" << getCommandName(C->getCommandID()) 282 << "\"" 283 " CloseName=\"" 284 << C->getCloseName() << "\""; 285 } 286 287 void TextNodeDumper::visitVerbatimBlockLineComment( 288 const comments::VerbatimBlockLineComment *C, 289 const comments::FullComment *) { 290 OS << " Text=\"" << C->getText() << "\""; 291 } 292 293 void TextNodeDumper::visitVerbatimLineComment( 294 const comments::VerbatimLineComment *C, const comments::FullComment *) { 295 OS << " Text=\"" << C->getText() << "\""; 296 } 297