| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 part of tree; | |
| 6 | |
| 7 /** | |
| 8 * Pretty-prints Node tree in XML-like format. | |
| 9 * | |
| 10 * TODO(smok): Add main() to run from command-line to print out tree for given | |
| 11 * .dart file. | |
| 12 */ | |
| 13 class PrettyPrinter extends Indentation implements Visitor { | |
| 14 | |
| 15 StringBuffer sb; | |
| 16 Link<String> tagStack; | |
| 17 | |
| 18 PrettyPrinter() : | |
| 19 sb = new StringBuffer(), | |
| 20 tagStack = const Link<String>(); | |
| 21 | |
| 22 void pushTag(String tag) { | |
| 23 tagStack = tagStack.prepend(tag); | |
| 24 indentMore(); | |
| 25 } | |
| 26 | |
| 27 String popTag() { | |
| 28 assert(!tagStack.isEmpty); | |
| 29 String tag = tagStack.head; | |
| 30 tagStack = tagStack.tail; | |
| 31 indentLess(); | |
| 32 return tag; | |
| 33 } | |
| 34 | |
| 35 /** | |
| 36 * Adds given string to result string. | |
| 37 */ | |
| 38 void add(String string) { | |
| 39 sb.write(string); | |
| 40 } | |
| 41 | |
| 42 void addBeginAndEndTokensToParams(Node node, Map params) { | |
| 43 params['getBeginToken'] = tokenToStringOrNull(node.getBeginToken()); | |
| 44 params['getEndToken'] = tokenToStringOrNull(node.getEndToken()); | |
| 45 } | |
| 46 | |
| 47 /** | |
| 48 * Adds given node type to result string. | |
| 49 * The method "opens" the node, meaning that all output after calling | |
| 50 * this method and before calling closeNode() will represent contents | |
| 51 * of given node. | |
| 52 */ | |
| 53 void openNode(Node node, String type, [Map params]) { | |
| 54 if (params == null) params = new Map(); | |
| 55 addCurrentIndent(); | |
| 56 sb.write("<"); | |
| 57 addBeginAndEndTokensToParams(node, params); | |
| 58 addTypeWithParams(type, params); | |
| 59 sb.write(">\n"); | |
| 60 pushTag(type); | |
| 61 } | |
| 62 | |
| 63 /** | |
| 64 * Adds given node to result string. | |
| 65 */ | |
| 66 void openAndCloseNode(Node node, String type, [Map params]) { | |
| 67 if (params == null) params = new Map(); | |
| 68 addCurrentIndent(); | |
| 69 sb.write("<"); | |
| 70 addBeginAndEndTokensToParams(node, params); | |
| 71 addTypeWithParams(type, params); | |
| 72 sb.write("/>\n"); | |
| 73 } | |
| 74 | |
| 75 /** | |
| 76 * Closes current node type. | |
| 77 */ | |
| 78 void closeNode() { | |
| 79 String tag = popTag(); | |
| 80 addCurrentIndent(); | |
| 81 sb.write("</"); | |
| 82 addTypeWithParams(tag); | |
| 83 sb.write(">\n"); | |
| 84 } | |
| 85 | |
| 86 void addTypeWithParams(String type, [Map params]) { | |
| 87 if (params == null) params = new Map(); | |
| 88 sb.write("${type}"); | |
| 89 params.forEach((k, v) { | |
| 90 String value; | |
| 91 if (v != null) { | |
| 92 var str = v; | |
| 93 if (v is Token) str = v.value; | |
| 94 value = str | |
| 95 .replaceAll("<", "<") | |
| 96 .replaceAll(">", ">") | |
| 97 .replaceAll('"', "'"); | |
| 98 } else { | |
| 99 value = "[null]"; | |
| 100 } | |
| 101 sb.write(' $k="$value"'); | |
| 102 }); | |
| 103 } | |
| 104 | |
| 105 void addCurrentIndent() { | |
| 106 sb.write(indentation); | |
| 107 } | |
| 108 | |
| 109 /** | |
| 110 * Pretty-prints given node tree into string. | |
| 111 */ | |
| 112 static String prettyPrint(Node node) { | |
| 113 var p = new PrettyPrinter(); | |
| 114 node.accept(p); | |
| 115 return p.sb.toString(); | |
| 116 } | |
| 117 | |
| 118 visitNodeWithChildren(Node node, String type) { | |
| 119 openNode(node, type); | |
| 120 node.visitChildren(this); | |
| 121 closeNode(); | |
| 122 } | |
| 123 | |
| 124 visitBlock(Block node) { | |
| 125 visitNodeWithChildren(node, "Block"); | |
| 126 } | |
| 127 | |
| 128 visitBreakStatement(BreakStatement node) { | |
| 129 visitNodeWithChildren(node, "BreakStatement"); | |
| 130 } | |
| 131 | |
| 132 visitCascade(Cascade node) { | |
| 133 visitNodeWithChildren(node, "Cascade"); | |
| 134 } | |
| 135 | |
| 136 visitCascadeReceiver(CascadeReceiver node) { | |
| 137 visitNodeWithChildren(node, "CascadeReceiver"); | |
| 138 } | |
| 139 | |
| 140 visitCaseMatch(CaseMatch node) { | |
| 141 visitNodeWithChildren(node, "CaseMatch"); | |
| 142 } | |
| 143 | |
| 144 visitCatchBlock(CatchBlock node) { | |
| 145 visitNodeWithChildren(node, "CatchBlock"); | |
| 146 } | |
| 147 | |
| 148 visitClassNode(ClassNode node) { | |
| 149 openNode(node, "ClassNode", { | |
| 150 "extendsKeyword" : tokenToStringOrNull(node.extendsKeyword) | |
| 151 }); | |
| 152 visitChildNode(node.name, "name"); | |
| 153 visitChildNode(node.superclass, "superclass"); | |
| 154 visitChildNode(node.interfaces, "interfaces"); | |
| 155 visitChildNode(node.typeParameters, "typeParameters"); | |
| 156 closeNode(); | |
| 157 } | |
| 158 | |
| 159 visitConditional(Conditional node) { | |
| 160 visitNodeWithChildren(node, "Conditional"); | |
| 161 } | |
| 162 | |
| 163 visitContinueStatement(ContinueStatement node) { | |
| 164 visitNodeWithChildren(node, "ContinueStatement"); | |
| 165 } | |
| 166 | |
| 167 visitDoWhile(DoWhile node) { | |
| 168 visitNodeWithChildren(node, "DoWhile"); | |
| 169 } | |
| 170 | |
| 171 visitEmptyStatement(EmptyStatement node) { | |
| 172 visitNodeWithChildren(node, "EmptyStatement"); | |
| 173 } | |
| 174 | |
| 175 visitExpressionStatement(ExpressionStatement node) { | |
| 176 visitNodeWithChildren(node, "ExpressionStatement"); | |
| 177 } | |
| 178 | |
| 179 visitFor(For node) { | |
| 180 visitNodeWithChildren(node, "For"); | |
| 181 } | |
| 182 | |
| 183 visitForIn(ForIn node) { | |
| 184 visitNodeWithChildren(node, "ForIn"); | |
| 185 } | |
| 186 | |
| 187 visitFunctionDeclaration(FunctionDeclaration node) { | |
| 188 visitNodeWithChildren(node, "FunctionDeclaration"); | |
| 189 } | |
| 190 | |
| 191 visitFunctionExpression(FunctionExpression node) { | |
| 192 openNode(node, "FunctionExpression", { | |
| 193 "getOrSet" : tokenToStringOrNull(node.getOrSet) | |
| 194 }); | |
| 195 visitChildNode(node.modifiers, "modifiers"); | |
| 196 visitChildNode(node.returnType, "returnType"); | |
| 197 visitChildNode(node.name, "name"); | |
| 198 visitChildNode(node.parameters, "parameters"); | |
| 199 visitChildNode(node.initializers, "initializers"); | |
| 200 visitChildNode(node.body, "body"); | |
| 201 closeNode(); | |
| 202 } | |
| 203 | |
| 204 visitIdentifier(Identifier node) { | |
| 205 openAndCloseNode(node, "Identifier", {"token" : node.token}); | |
| 206 } | |
| 207 | |
| 208 visitIf(If node) { | |
| 209 visitNodeWithChildren(node, "If"); | |
| 210 } | |
| 211 | |
| 212 visitLabel(Label node) { | |
| 213 visitNodeWithChildren(node, "Label"); | |
| 214 } | |
| 215 | |
| 216 visitLabeledStatement(LabeledStatement node) { | |
| 217 visitNodeWithChildren(node, "LabeledStatement"); | |
| 218 } | |
| 219 | |
| 220 // Custom. | |
| 221 printLiteral(Literal node, String type) { | |
| 222 openAndCloseNode(node, type, {"value" : node.value.toString()}); | |
| 223 } | |
| 224 | |
| 225 visitLiteralBool(LiteralBool node) { | |
| 226 printLiteral(node, "LiteralBool"); | |
| 227 } | |
| 228 | |
| 229 visitLiteralDouble(LiteralDouble node) { | |
| 230 printLiteral(node, "LiteralDouble"); | |
| 231 } | |
| 232 | |
| 233 visitLiteralInt(LiteralInt node) { | |
| 234 printLiteral(node, "LiteralInt"); | |
| 235 } | |
| 236 | |
| 237 /** Returns token string value or [:null:] if token is [:null:]. */ | |
| 238 tokenToStringOrNull(Token token) => token == null ? null : token.stringValue; | |
| 239 | |
| 240 visitLiteralList(LiteralList node) { | |
| 241 openNode(node, "LiteralList", { | |
| 242 "constKeyword" : tokenToStringOrNull(node.constKeyword) | |
| 243 }); | |
| 244 visitChildNode(node.typeArguments, "typeArguments"); | |
| 245 visitChildNode(node.elements, "elements"); | |
| 246 closeNode(); | |
| 247 } | |
| 248 | |
| 249 visitLiteralMap(LiteralMap node) { | |
| 250 visitNodeWithChildren(node, "LiteralMap"); | |
| 251 } | |
| 252 | |
| 253 visitLiteralMapEntry(LiteralMapEntry node) { | |
| 254 visitNodeWithChildren(node, "LiteralMapEntry"); | |
| 255 } | |
| 256 | |
| 257 visitLiteralNull(LiteralNull node) { | |
| 258 printLiteral(node, "LiteralNull"); | |
| 259 } | |
| 260 | |
| 261 visitLiteralString(LiteralString node) { | |
| 262 openAndCloseNode(node, "LiteralString", | |
| 263 {"value" : node.token}); | |
| 264 } | |
| 265 | |
| 266 visitMixinApplication(MixinApplication node) { | |
| 267 visitNodeWithChildren(node, "MixinApplication"); | |
| 268 } | |
| 269 | |
| 270 visitModifiers(Modifiers node) { | |
| 271 visitNodeWithChildren(node, "Modifiers"); | |
| 272 } | |
| 273 | |
| 274 visitNamedArgument(NamedArgument node) { | |
| 275 visitNodeWithChildren(node, "NamedArgument"); | |
| 276 } | |
| 277 | |
| 278 visitNamedMixinApplication(NamedMixinApplication node) { | |
| 279 visitNodeWithChildren(node, "NamedMixinApplication"); | |
| 280 } | |
| 281 | |
| 282 visitNewExpression(NewExpression node) { | |
| 283 visitNodeWithChildren(node, "NewExpression"); | |
| 284 } | |
| 285 | |
| 286 visitNodeList(NodeList node) { | |
| 287 var params = { "delimiter" : node.delimiter }; | |
| 288 if (node.isEmpty) { | |
| 289 openAndCloseNode(node, "NodeList", params); | |
| 290 } else { | |
| 291 openNode(node, "NodeList", params); | |
| 292 node.visitChildren(this); | |
| 293 closeNode(); | |
| 294 } | |
| 295 } | |
| 296 | |
| 297 visitOperator(Operator node) { | |
| 298 openAndCloseNode(node, "Operator", {"value" : node.token}); | |
| 299 } | |
| 300 | |
| 301 visitParenthesizedExpression(ParenthesizedExpression node) { | |
| 302 visitNodeWithChildren(node, "ParenthesizedExpression"); | |
| 303 } | |
| 304 | |
| 305 visitRedirectingFactoryBody(RedirectingFactoryBody node) { | |
| 306 openNode(node, "RedirectingFactoryBody"); | |
| 307 visitChildNode(node.constructorReference, "constructorReference"); | |
| 308 closeNode(); | |
| 309 } | |
| 310 | |
| 311 visitRethrow(Rethrow node) { | |
| 312 visitNodeWithChildren(node, "Rethrow"); | |
| 313 } | |
| 314 | |
| 315 visitReturn(Return node) { | |
| 316 openNode(node, "Return"); | |
| 317 visitChildNode(node.expression, "expression"); | |
| 318 closeNode(); | |
| 319 } | |
| 320 | |
| 321 visitChildNode(Node node, String fieldName) { | |
| 322 if (node == null) return; | |
| 323 addCurrentIndent(); | |
| 324 sb.write("<$fieldName>\n"); | |
| 325 pushTag(fieldName); | |
| 326 node.accept(this); | |
| 327 popTag(); | |
| 328 addCurrentIndent(); | |
| 329 sb.write("</$fieldName>\n"); | |
| 330 } | |
| 331 | |
| 332 openSendNodeWithFields(Send node, String type) { | |
| 333 openNode(node, type, { | |
| 334 "isPrefix" : "${node.isPrefix}", | |
| 335 "isPostfix" : "${node.isPostfix}", | |
| 336 "isIndex" : "${node.isIndex}" | |
| 337 }); | |
| 338 visitChildNode(node.receiver, "receiver"); | |
| 339 visitChildNode(node.selector, "selector"); | |
| 340 visitChildNode(node.argumentsNode, "argumentsNode"); | |
| 341 } | |
| 342 | |
| 343 visitSend(Send node) { | |
| 344 openSendNodeWithFields(node, "Send"); | |
| 345 closeNode(); | |
| 346 } | |
| 347 | |
| 348 visitSendSet(SendSet node) { | |
| 349 openSendNodeWithFields(node, "SendSet"); | |
| 350 visitChildNode(node.assignmentOperator, "assignmentOperator"); | |
| 351 closeNode(); | |
| 352 } | |
| 353 | |
| 354 visitStringInterpolation(StringInterpolation node) { | |
| 355 visitNodeWithChildren(node, "StringInterpolation"); | |
| 356 } | |
| 357 | |
| 358 visitStringInterpolationPart(StringInterpolationPart node) { | |
| 359 visitNodeWithChildren(node, "StringInterpolationPart"); | |
| 360 } | |
| 361 | |
| 362 visitStringJuxtaposition(StringJuxtaposition node) { | |
| 363 visitNodeWithChildren(node, "StringJuxtaposition"); | |
| 364 } | |
| 365 | |
| 366 visitSwitchCase(SwitchCase node) { | |
| 367 visitNodeWithChildren(node, "SwitchCase"); | |
| 368 } | |
| 369 | |
| 370 visitSwitchStatement(SwitchStatement node) { | |
| 371 visitNodeWithChildren(node, "SwitchStatement"); | |
| 372 } | |
| 373 | |
| 374 visitLiteralSymbol(LiteralSymbol node) { | |
| 375 openNode(node, "LiteralSymbol"); | |
| 376 visitChildNode(node.identifiers, "identifiers"); | |
| 377 closeNode(); | |
| 378 } | |
| 379 | |
| 380 visitThrow(Throw node) { | |
| 381 visitNodeWithChildren(node, "Throw"); | |
| 382 } | |
| 383 | |
| 384 visitTryStatement(TryStatement node) { | |
| 385 visitNodeWithChildren(node, "TryStatement"); | |
| 386 } | |
| 387 | |
| 388 visitTypeAnnotation(TypeAnnotation node) { | |
| 389 openNode(node, "TypeAnnotation"); | |
| 390 visitChildNode(node.typeName, "typeName"); | |
| 391 visitChildNode(node.typeArguments, "typeArguments"); | |
| 392 closeNode(); | |
| 393 } | |
| 394 | |
| 395 visitTypedef(Typedef node) { | |
| 396 visitNodeWithChildren(node, "Typedef"); | |
| 397 } | |
| 398 | |
| 399 visitTypeVariable(TypeVariable node) { | |
| 400 openNode(node, "TypeVariable"); | |
| 401 visitChildNode(node.name, "name"); | |
| 402 visitChildNode(node.bound, "bound"); | |
| 403 closeNode(); | |
| 404 } | |
| 405 | |
| 406 visitVariableDefinitions(VariableDefinitions node) { | |
| 407 openNode(node, "VariableDefinitions"); | |
| 408 visitChildNode(node.type, "type"); | |
| 409 visitChildNode(node.modifiers, "modifiers"); | |
| 410 visitChildNode(node.definitions, "definitions"); | |
| 411 closeNode(); | |
| 412 } | |
| 413 | |
| 414 visitWhile(While node) { | |
| 415 visitNodeWithChildren(node, "While"); | |
| 416 } | |
| 417 | |
| 418 visitMetadata(Metadata node) { | |
| 419 openNode(node, "Metadata", { | |
| 420 "token": node.token | |
| 421 }); | |
| 422 visitChildNode(node.expression, "expression"); | |
| 423 closeNode(); | |
| 424 } | |
| 425 | |
| 426 visitCombinator(Combinator node) { | |
| 427 openNode(node, "Combinator", {"isShow" : "${node.isShow}", | |
| 428 "isHide" : "${node.isHide}"}); | |
| 429 closeNode(); | |
| 430 } | |
| 431 | |
| 432 visitExport(Export node) { | |
| 433 openNode(node, "Export"); | |
| 434 visitChildNode(node.uri, "uri"); | |
| 435 visitChildNode(node.combinators, "combinators"); | |
| 436 closeNode(); | |
| 437 } | |
| 438 | |
| 439 visitImport(Import node) { | |
| 440 openNode(node, "Import", { | |
| 441 "isDeferred" : "${node.isDeferred}"}); | |
| 442 visitChildNode(node.uri, "uri"); | |
| 443 visitChildNode(node.combinators, "combinators"); | |
| 444 if (node.prefix != null) { | |
| 445 visitChildNode(node.prefix, "prefix"); | |
| 446 } | |
| 447 closeNode(); | |
| 448 } | |
| 449 | |
| 450 visitPart(Part node) { | |
| 451 openNode(node, "Part"); | |
| 452 visitChildNode(node.uri, "uri"); | |
| 453 closeNode(); | |
| 454 } | |
| 455 | |
| 456 visitPartOf(PartOf node) { | |
| 457 openNode(node, "PartOf"); | |
| 458 visitChildNode(node.name, "name"); | |
| 459 closeNode(); | |
| 460 } | |
| 461 | |
| 462 visitLibraryName(LibraryName node) { | |
| 463 openNode(node, "LibraryName"); | |
| 464 visitChildNode(node.name, "name"); | |
| 465 closeNode(); | |
| 466 } | |
| 467 | |
| 468 visitNode(Node node) { | |
| 469 unimplemented('visitNode', node: node); | |
| 470 } | |
| 471 | |
| 472 visitLibraryDependency(Node node) { | |
| 473 unimplemented('visitNode', node: node); | |
| 474 } | |
| 475 | |
| 476 visitLibraryTag(LibraryTag node) { | |
| 477 unimplemented('visitNode', node: node); | |
| 478 } | |
| 479 | |
| 480 visitLiteral(Literal node) { | |
| 481 unimplemented('visitNode', node: node); | |
| 482 } | |
| 483 | |
| 484 visitLoop(Loop node) { | |
| 485 unimplemented('visitNode', node: node); | |
| 486 } | |
| 487 | |
| 488 visitPostfix(Postfix node) { | |
| 489 unimplemented('visitNode', node: node); | |
| 490 } | |
| 491 | |
| 492 visitPrefix(Prefix node) { | |
| 493 unimplemented('visitNode', node: node); | |
| 494 } | |
| 495 | |
| 496 visitStringNode(StringNode node) { | |
| 497 unimplemented('visitNode', node: node); | |
| 498 } | |
| 499 | |
| 500 visitStatement(Statement node) { | |
| 501 unimplemented('visitNode', node: node); | |
| 502 } | |
| 503 | |
| 504 visitExpression(Expression node) { | |
| 505 unimplemented('visitNode', node: node); | |
| 506 } | |
| 507 | |
| 508 visitGotoStatement(GotoStatement node) { | |
| 509 unimplemented('visitNode', node: node); | |
| 510 } | |
| 511 | |
| 512 unimplemented(String message, {Node node}) { | |
| 513 throw message; | |
| 514 } | |
| 515 } | |
| OLD | NEW |