| 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 visitAsyncModifier(AsyncModifier node) { | |
| 125 openAndCloseNode(node, "AsyncModifier", | |
| 126 {'asyncToken': node.asyncToken, | |
| 127 'starToken': node.starToken}); | |
| 128 } | |
| 129 | |
| 130 visitBlock(Block node) { | |
| 131 visitNodeWithChildren(node, "Block"); | |
| 132 } | |
| 133 | |
| 134 visitBreakStatement(BreakStatement node) { | |
| 135 visitNodeWithChildren(node, "BreakStatement"); | |
| 136 } | |
| 137 | |
| 138 visitCascade(Cascade node) { | |
| 139 visitNodeWithChildren(node, "Cascade"); | |
| 140 } | |
| 141 | |
| 142 visitCascadeReceiver(CascadeReceiver node) { | |
| 143 visitNodeWithChildren(node, "CascadeReceiver"); | |
| 144 } | |
| 145 | |
| 146 visitCaseMatch(CaseMatch node) { | |
| 147 visitNodeWithChildren(node, "CaseMatch"); | |
| 148 } | |
| 149 | |
| 150 visitCatchBlock(CatchBlock node) { | |
| 151 visitNodeWithChildren(node, "CatchBlock"); | |
| 152 } | |
| 153 | |
| 154 visitClassNode(ClassNode node) { | |
| 155 openNode(node, "ClassNode", { | |
| 156 "extendsKeyword" : tokenToStringOrNull(node.extendsKeyword) | |
| 157 }); | |
| 158 visitChildNode(node.name, "name"); | |
| 159 visitChildNode(node.superclass, "superclass"); | |
| 160 visitChildNode(node.interfaces, "interfaces"); | |
| 161 visitChildNode(node.typeParameters, "typeParameters"); | |
| 162 closeNode(); | |
| 163 } | |
| 164 | |
| 165 visitConditional(Conditional node) { | |
| 166 visitNodeWithChildren(node, "Conditional"); | |
| 167 } | |
| 168 | |
| 169 visitContinueStatement(ContinueStatement node) { | |
| 170 visitNodeWithChildren(node, "ContinueStatement"); | |
| 171 } | |
| 172 | |
| 173 visitDoWhile(DoWhile node) { | |
| 174 visitNodeWithChildren(node, "DoWhile"); | |
| 175 } | |
| 176 | |
| 177 visitEmptyStatement(EmptyStatement node) { | |
| 178 visitNodeWithChildren(node, "EmptyStatement"); | |
| 179 } | |
| 180 | |
| 181 visitExpressionStatement(ExpressionStatement node) { | |
| 182 visitNodeWithChildren(node, "ExpressionStatement"); | |
| 183 } | |
| 184 | |
| 185 visitFor(For node) { | |
| 186 visitNodeWithChildren(node, "For"); | |
| 187 } | |
| 188 | |
| 189 visitForIn(ForIn node) { | |
| 190 openNode(node, "ForIn", {'await': node.awaitToken}); | |
| 191 node.visitChildren(this); | |
| 192 closeNode(); | |
| 193 } | |
| 194 | |
| 195 visitFunctionDeclaration(FunctionDeclaration node) { | |
| 196 visitNodeWithChildren(node, "FunctionDeclaration"); | |
| 197 } | |
| 198 | |
| 199 visitFunctionExpression(FunctionExpression node) { | |
| 200 openNode(node, "FunctionExpression", { | |
| 201 "getOrSet" : tokenToStringOrNull(node.getOrSet) | |
| 202 }); | |
| 203 visitChildNode(node.modifiers, "modifiers"); | |
| 204 visitChildNode(node.returnType, "returnType"); | |
| 205 visitChildNode(node.name, "name"); | |
| 206 visitChildNode(node.parameters, "parameters"); | |
| 207 visitChildNode(node.initializers, "initializers"); | |
| 208 visitChildNode(node.body, "body"); | |
| 209 closeNode(); | |
| 210 } | |
| 211 | |
| 212 visitIdentifier(Identifier node) { | |
| 213 openAndCloseNode(node, "Identifier", {"token" : node.token}); | |
| 214 } | |
| 215 | |
| 216 visitIf(If node) { | |
| 217 visitNodeWithChildren(node, "If"); | |
| 218 } | |
| 219 | |
| 220 visitLabel(Label node) { | |
| 221 visitNodeWithChildren(node, "Label"); | |
| 222 } | |
| 223 | |
| 224 visitLabeledStatement(LabeledStatement node) { | |
| 225 visitNodeWithChildren(node, "LabeledStatement"); | |
| 226 } | |
| 227 | |
| 228 // Custom. | |
| 229 printLiteral(Literal node, String type) { | |
| 230 openAndCloseNode(node, type, {"value" : node.value.toString()}); | |
| 231 } | |
| 232 | |
| 233 visitLiteralBool(LiteralBool node) { | |
| 234 printLiteral(node, "LiteralBool"); | |
| 235 } | |
| 236 | |
| 237 visitLiteralDouble(LiteralDouble node) { | |
| 238 printLiteral(node, "LiteralDouble"); | |
| 239 } | |
| 240 | |
| 241 visitLiteralInt(LiteralInt node) { | |
| 242 printLiteral(node, "LiteralInt"); | |
| 243 } | |
| 244 | |
| 245 /** Returns token string value or [:null:] if token is [:null:]. */ | |
| 246 tokenToStringOrNull(Token token) => token == null ? null : token.stringValue; | |
| 247 | |
| 248 visitLiteralList(LiteralList node) { | |
| 249 openNode(node, "LiteralList", { | |
| 250 "constKeyword" : tokenToStringOrNull(node.constKeyword) | |
| 251 }); | |
| 252 visitChildNode(node.typeArguments, "typeArguments"); | |
| 253 visitChildNode(node.elements, "elements"); | |
| 254 closeNode(); | |
| 255 } | |
| 256 | |
| 257 visitLiteralMap(LiteralMap node) { | |
| 258 visitNodeWithChildren(node, "LiteralMap"); | |
| 259 } | |
| 260 | |
| 261 visitLiteralMapEntry(LiteralMapEntry node) { | |
| 262 visitNodeWithChildren(node, "LiteralMapEntry"); | |
| 263 } | |
| 264 | |
| 265 visitLiteralNull(LiteralNull node) { | |
| 266 printLiteral(node, "LiteralNull"); | |
| 267 } | |
| 268 | |
| 269 visitLiteralString(LiteralString node) { | |
| 270 openAndCloseNode(node, "LiteralString", | |
| 271 {"value" : node.token}); | |
| 272 } | |
| 273 | |
| 274 visitMixinApplication(MixinApplication node) { | |
| 275 visitNodeWithChildren(node, "MixinApplication"); | |
| 276 } | |
| 277 | |
| 278 visitModifiers(Modifiers node) { | |
| 279 visitNodeWithChildren(node, "Modifiers"); | |
| 280 } | |
| 281 | |
| 282 visitNamedArgument(NamedArgument node) { | |
| 283 visitNodeWithChildren(node, "NamedArgument"); | |
| 284 } | |
| 285 | |
| 286 visitNamedMixinApplication(NamedMixinApplication node) { | |
| 287 visitNodeWithChildren(node, "NamedMixinApplication"); | |
| 288 } | |
| 289 | |
| 290 visitNewExpression(NewExpression node) { | |
| 291 visitNodeWithChildren(node, "NewExpression"); | |
| 292 } | |
| 293 | |
| 294 visitNodeList(NodeList node) { | |
| 295 var params = { "delimiter" : node.delimiter }; | |
| 296 if (node.isEmpty) { | |
| 297 openAndCloseNode(node, "NodeList", params); | |
| 298 } else { | |
| 299 openNode(node, "NodeList", params); | |
| 300 node.visitChildren(this); | |
| 301 closeNode(); | |
| 302 } | |
| 303 } | |
| 304 | |
| 305 visitOperator(Operator node) { | |
| 306 openAndCloseNode(node, "Operator", {"value" : node.token}); | |
| 307 } | |
| 308 | |
| 309 visitParenthesizedExpression(ParenthesizedExpression node) { | |
| 310 visitNodeWithChildren(node, "ParenthesizedExpression"); | |
| 311 } | |
| 312 | |
| 313 visitRedirectingFactoryBody(RedirectingFactoryBody node) { | |
| 314 openNode(node, "RedirectingFactoryBody"); | |
| 315 visitChildNode(node.constructorReference, "constructorReference"); | |
| 316 closeNode(); | |
| 317 } | |
| 318 | |
| 319 visitRethrow(Rethrow node) { | |
| 320 visitNodeWithChildren(node, "Rethrow"); | |
| 321 } | |
| 322 | |
| 323 visitReturn(Return node) { | |
| 324 openNode(node, "Return"); | |
| 325 visitChildNode(node.expression, "expression"); | |
| 326 closeNode(); | |
| 327 } | |
| 328 | |
| 329 visitYield(Yield node) { | |
| 330 openNode(node, "Yield", {'star': node.starToken}); | |
| 331 visitChildNode(node.expression, "expression"); | |
| 332 closeNode(); | |
| 333 } | |
| 334 | |
| 335 visitChildNode(Node node, String fieldName) { | |
| 336 if (node == null) return; | |
| 337 addCurrentIndent(); | |
| 338 sb.write("<$fieldName>\n"); | |
| 339 pushTag(fieldName); | |
| 340 node.accept(this); | |
| 341 popTag(); | |
| 342 addCurrentIndent(); | |
| 343 sb.write("</$fieldName>\n"); | |
| 344 } | |
| 345 | |
| 346 openSendNodeWithFields(Send node, String type) { | |
| 347 openNode(node, type, { | |
| 348 "isPrefix" : "${node.isPrefix}", | |
| 349 "isPostfix" : "${node.isPostfix}", | |
| 350 "isIndex" : "${node.isIndex}" | |
| 351 }); | |
| 352 visitChildNode(node.receiver, "receiver"); | |
| 353 visitChildNode(node.selector, "selector"); | |
| 354 visitChildNode(node.argumentsNode, "argumentsNode"); | |
| 355 } | |
| 356 | |
| 357 visitSend(Send node) { | |
| 358 openSendNodeWithFields(node, "Send"); | |
| 359 closeNode(); | |
| 360 } | |
| 361 | |
| 362 visitSendSet(SendSet node) { | |
| 363 openSendNodeWithFields(node, "SendSet"); | |
| 364 visitChildNode(node.assignmentOperator, "assignmentOperator"); | |
| 365 closeNode(); | |
| 366 } | |
| 367 | |
| 368 visitStringInterpolation(StringInterpolation node) { | |
| 369 visitNodeWithChildren(node, "StringInterpolation"); | |
| 370 } | |
| 371 | |
| 372 visitStringInterpolationPart(StringInterpolationPart node) { | |
| 373 visitNodeWithChildren(node, "StringInterpolationPart"); | |
| 374 } | |
| 375 | |
| 376 visitStringJuxtaposition(StringJuxtaposition node) { | |
| 377 visitNodeWithChildren(node, "StringJuxtaposition"); | |
| 378 } | |
| 379 | |
| 380 visitSwitchCase(SwitchCase node) { | |
| 381 visitNodeWithChildren(node, "SwitchCase"); | |
| 382 } | |
| 383 | |
| 384 visitSwitchStatement(SwitchStatement node) { | |
| 385 visitNodeWithChildren(node, "SwitchStatement"); | |
| 386 } | |
| 387 | |
| 388 visitLiteralSymbol(LiteralSymbol node) { | |
| 389 openNode(node, "LiteralSymbol"); | |
| 390 visitChildNode(node.identifiers, "identifiers"); | |
| 391 closeNode(); | |
| 392 } | |
| 393 | |
| 394 visitThrow(Throw node) { | |
| 395 visitNodeWithChildren(node, "Throw"); | |
| 396 } | |
| 397 | |
| 398 visitAwait(Await node) { | |
| 399 visitNodeWithChildren(node, "Await"); | |
| 400 } | |
| 401 | |
| 402 visitTryStatement(TryStatement node) { | |
| 403 visitNodeWithChildren(node, "TryStatement"); | |
| 404 } | |
| 405 | |
| 406 visitTypeAnnotation(TypeAnnotation node) { | |
| 407 openNode(node, "TypeAnnotation"); | |
| 408 visitChildNode(node.typeName, "typeName"); | |
| 409 visitChildNode(node.typeArguments, "typeArguments"); | |
| 410 closeNode(); | |
| 411 } | |
| 412 | |
| 413 visitTypedef(Typedef node) { | |
| 414 visitNodeWithChildren(node, "Typedef"); | |
| 415 } | |
| 416 | |
| 417 visitTypeVariable(TypeVariable node) { | |
| 418 openNode(node, "TypeVariable"); | |
| 419 visitChildNode(node.name, "name"); | |
| 420 visitChildNode(node.bound, "bound"); | |
| 421 closeNode(); | |
| 422 } | |
| 423 | |
| 424 visitVariableDefinitions(VariableDefinitions node) { | |
| 425 openNode(node, "VariableDefinitions"); | |
| 426 visitChildNode(node.type, "type"); | |
| 427 visitChildNode(node.modifiers, "modifiers"); | |
| 428 visitChildNode(node.definitions, "definitions"); | |
| 429 closeNode(); | |
| 430 } | |
| 431 | |
| 432 visitWhile(While node) { | |
| 433 visitNodeWithChildren(node, "While"); | |
| 434 } | |
| 435 | |
| 436 visitMetadata(Metadata node) { | |
| 437 openNode(node, "Metadata", { | |
| 438 "token": node.token | |
| 439 }); | |
| 440 visitChildNode(node.expression, "expression"); | |
| 441 closeNode(); | |
| 442 } | |
| 443 | |
| 444 visitCombinator(Combinator node) { | |
| 445 openNode(node, "Combinator", {"isShow" : "${node.isShow}", | |
| 446 "isHide" : "${node.isHide}"}); | |
| 447 closeNode(); | |
| 448 } | |
| 449 | |
| 450 visitExport(Export node) { | |
| 451 openNode(node, "Export"); | |
| 452 visitChildNode(node.uri, "uri"); | |
| 453 visitChildNode(node.combinators, "combinators"); | |
| 454 closeNode(); | |
| 455 } | |
| 456 | |
| 457 visitImport(Import node) { | |
| 458 openNode(node, "Import", { | |
| 459 "isDeferred" : "${node.isDeferred}"}); | |
| 460 visitChildNode(node.uri, "uri"); | |
| 461 visitChildNode(node.combinators, "combinators"); | |
| 462 if (node.prefix != null) { | |
| 463 visitChildNode(node.prefix, "prefix"); | |
| 464 } | |
| 465 closeNode(); | |
| 466 } | |
| 467 | |
| 468 visitPart(Part node) { | |
| 469 openNode(node, "Part"); | |
| 470 visitChildNode(node.uri, "uri"); | |
| 471 closeNode(); | |
| 472 } | |
| 473 | |
| 474 visitPartOf(PartOf node) { | |
| 475 openNode(node, "PartOf"); | |
| 476 visitChildNode(node.name, "name"); | |
| 477 closeNode(); | |
| 478 } | |
| 479 | |
| 480 visitLibraryName(LibraryName node) { | |
| 481 openNode(node, "LibraryName"); | |
| 482 visitChildNode(node.name, "name"); | |
| 483 closeNode(); | |
| 484 } | |
| 485 | |
| 486 visitNode(Node node) { | |
| 487 unimplemented('visitNode', node: node); | |
| 488 } | |
| 489 | |
| 490 visitLibraryDependency(Node node) { | |
| 491 unimplemented('visitNode', node: node); | |
| 492 } | |
| 493 | |
| 494 visitLibraryTag(LibraryTag node) { | |
| 495 unimplemented('visitNode', node: node); | |
| 496 } | |
| 497 | |
| 498 visitLiteral(Literal node) { | |
| 499 unimplemented('visitNode', node: node); | |
| 500 } | |
| 501 | |
| 502 visitLoop(Loop node) { | |
| 503 unimplemented('visitNode', node: node); | |
| 504 } | |
| 505 | |
| 506 visitPostfix(Postfix node) { | |
| 507 unimplemented('visitNode', node: node); | |
| 508 } | |
| 509 | |
| 510 visitPrefix(Prefix node) { | |
| 511 unimplemented('visitNode', node: node); | |
| 512 } | |
| 513 | |
| 514 visitStringNode(StringNode node) { | |
| 515 unimplemented('visitNode', node: node); | |
| 516 } | |
| 517 | |
| 518 visitStatement(Statement node) { | |
| 519 unimplemented('visitNode', node: node); | |
| 520 } | |
| 521 | |
| 522 visitExpression(Expression node) { | |
| 523 unimplemented('visitNode', node: node); | |
| 524 } | |
| 525 | |
| 526 visitGotoStatement(GotoStatement node) { | |
| 527 unimplemented('visitNode', node: node); | |
| 528 } | |
| 529 | |
| 530 unimplemented(String message, {Node node}) { | |
| 531 throw message; | |
| 532 } | |
| 533 } | |
| OLD | NEW |