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 : OS(OS), ShowColors(ShowColors), SM(SM), PrintPolicy(PrintPolicy), 23 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 const char *TextNodeDumper::getCommandName(unsigned CommandID) { 165 if (Traits) 166 return Traits->getCommandInfo(CommandID)->Name; 167 const comments::CommandInfo *Info = 168 comments::CommandTraits::getBuiltinCommandInfo(CommandID); 169 if (Info) 170 return Info->Name; 171 return "<not a builtin command>"; 172 } 173 174 void TextNodeDumper::visitTextComment(const comments::TextComment *C, 175 const comments::FullComment *) { 176 OS << " Text=\"" << C->getText() << "\""; 177 } 178 179 void TextNodeDumper::visitInlineCommandComment( 180 const comments::InlineCommandComment *C, const comments::FullComment *) { 181 OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""; 182 switch (C->getRenderKind()) { 183 case comments::InlineCommandComment::RenderNormal: 184 OS << " RenderNormal"; 185 break; 186 case comments::InlineCommandComment::RenderBold: 187 OS << " RenderBold"; 188 break; 189 case comments::InlineCommandComment::RenderMonospaced: 190 OS << " RenderMonospaced"; 191 break; 192 case comments::InlineCommandComment::RenderEmphasized: 193 OS << " RenderEmphasized"; 194 break; 195 } 196 197 for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) 198 OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\""; 199 } 200 201 void TextNodeDumper::visitHTMLStartTagComment( 202 const comments::HTMLStartTagComment *C, const comments::FullComment *) { 203 OS << " Name=\"" << C->getTagName() << "\""; 204 if (C->getNumAttrs() != 0) { 205 OS << " Attrs: "; 206 for (unsigned i = 0, e = C->getNumAttrs(); i != e; ++i) { 207 const comments::HTMLStartTagComment::Attribute &Attr = C->getAttr(i); 208 OS << " \"" << Attr.Name << "=\"" << Attr.Value << "\""; 209 } 210 } 211 if (C->isSelfClosing()) 212 OS << " SelfClosing"; 213 } 214 215 void TextNodeDumper::visitHTMLEndTagComment( 216 const comments::HTMLEndTagComment *C, const comments::FullComment *) { 217 OS << " Name=\"" << C->getTagName() << "\""; 218 } 219 220 void TextNodeDumper::visitBlockCommandComment( 221 const comments::BlockCommandComment *C, const comments::FullComment *) { 222 OS << " Name=\"" << getCommandName(C->getCommandID()) << "\""; 223 for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) 224 OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\""; 225 } 226 227 void TextNodeDumper::visitParamCommandComment( 228 const comments::ParamCommandComment *C, const comments::FullComment *FC) { 229 OS << " " 230 << comments::ParamCommandComment::getDirectionAsString(C->getDirection()); 231 232 if (C->isDirectionExplicit()) 233 OS << " explicitly"; 234 else 235 OS << " implicitly"; 236 237 if (C->hasParamName()) { 238 if (C->isParamIndexValid()) 239 OS << " Param=\"" << C->getParamName(FC) << "\""; 240 else 241 OS << " Param=\"" << C->getParamNameAsWritten() << "\""; 242 } 243 244 if (C->isParamIndexValid() && !C->isVarArgParam()) 245 OS << " ParamIndex=" << C->getParamIndex(); 246 } 247 248 void TextNodeDumper::visitTParamCommandComment( 249 const comments::TParamCommandComment *C, const comments::FullComment *FC) { 250 if (C->hasParamName()) { 251 if (C->isPositionValid()) 252 OS << " Param=\"" << C->getParamName(FC) << "\""; 253 else 254 OS << " Param=\"" << C->getParamNameAsWritten() << "\""; 255 } 256 257 if (C->isPositionValid()) { 258 OS << " Position=<"; 259 for (unsigned i = 0, e = C->getDepth(); i != e; ++i) { 260 OS << C->getIndex(i); 261 if (i != e - 1) 262 OS << ", "; 263 } 264 OS << ">"; 265 } 266 } 267 268 void TextNodeDumper::visitVerbatimBlockComment( 269 const comments::VerbatimBlockComment *C, const comments::FullComment *) { 270 OS << " Name=\"" << getCommandName(C->getCommandID()) 271 << "\"" 272 " CloseName=\"" 273 << C->getCloseName() << "\""; 274 } 275 276 void TextNodeDumper::visitVerbatimBlockLineComment( 277 const comments::VerbatimBlockLineComment *C, 278 const comments::FullComment *) { 279 OS << " Text=\"" << C->getText() << "\""; 280 } 281 282 void TextNodeDumper::visitVerbatimLineComment( 283 const comments::VerbatimLineComment *C, const comments::FullComment *) { 284 OS << " Text=\"" << C->getText() << "\""; 285 } 286