| // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| import 'package:front_end/src/fasta/scanner.dart' show Token; |
| import '../util/util.dart'; |
| import 'nodes.dart'; |
| |
| /** |
| * Pretty-prints Node tree in XML-like format. |
| * |
| * TODO(smok): Add main() to run from command-line to print out tree for given |
| * .dart file. |
| */ |
| class PrettyPrinter extends Indentation with Tagging<Node> implements Visitor { |
| @override |
| void addDefaultParameters(Node node, Map params) { |
| params['getBeginToken'] = tokenToStringOrNull(node.getBeginToken()); |
| params['getEndToken'] = tokenToStringOrNull(node.getEndToken()); |
| } |
| |
| String valueToString(var value) { |
| if (value is Token) { |
| return value.lexeme; |
| } |
| return value; |
| } |
| |
| /** |
| * Pretty-prints given node tree into string. |
| */ |
| static String prettyPrint(Node node) { |
| var p = new PrettyPrinter(); |
| node.accept(p); |
| return p.sb.toString(); |
| } |
| |
| visitNodeWithChildren(Node node, String type) { |
| openNode(node, type); |
| node.visitChildren(this); |
| closeNode(); |
| } |
| |
| visitAssert(Assert node) { |
| visitNodeWithChildren(node, "Assert"); |
| } |
| |
| visitAsyncModifier(AsyncModifier node) { |
| openAndCloseNode(node, "AsyncModifier", |
| {'asyncToken': node.asyncToken, 'starToken': node.starToken}); |
| } |
| |
| visitBlock(Block node) { |
| visitNodeWithChildren(node, "Block"); |
| } |
| |
| visitBreakStatement(BreakStatement node) { |
| visitNodeWithChildren(node, "BreakStatement"); |
| } |
| |
| visitCascade(Cascade node) { |
| visitNodeWithChildren(node, "Cascade"); |
| } |
| |
| visitCascadeReceiver(CascadeReceiver node) { |
| visitNodeWithChildren(node, "CascadeReceiver"); |
| } |
| |
| visitCaseMatch(CaseMatch node) { |
| visitNodeWithChildren(node, "CaseMatch"); |
| } |
| |
| visitCatchBlock(CatchBlock node) { |
| visitNodeWithChildren(node, "CatchBlock"); |
| } |
| |
| visitClassNode(ClassNode node) { |
| openNode(node, "ClassNode", |
| {"extendsKeyword": tokenToStringOrNull(node.extendsKeyword)}); |
| visitChildNode(node.name, "name"); |
| visitChildNode(node.superclass, "superclass"); |
| visitChildNode(node.interfaces, "interfaces"); |
| visitChildNode(node.typeParameters, "typeParameters"); |
| closeNode(); |
| } |
| |
| visitConditional(Conditional node) { |
| visitNodeWithChildren(node, "Conditional"); |
| } |
| |
| visitConditionalUri(ConditionalUri node) { |
| visitNodeWithChildren(node, "ConditionalUri"); |
| } |
| |
| visitContinueStatement(ContinueStatement node) { |
| visitNodeWithChildren(node, "ContinueStatement"); |
| } |
| |
| visitDottedName(DottedName node) { |
| openNode(node, "DottedName"); |
| visitChildNode(node.identifiers, "identifiers"); |
| closeNode(); |
| } |
| |
| visitDoWhile(DoWhile node) { |
| visitNodeWithChildren(node, "DoWhile"); |
| } |
| |
| visitEmptyStatement(EmptyStatement node) { |
| visitNodeWithChildren(node, "EmptyStatement"); |
| } |
| |
| visitEnum(Enum node) { |
| visitNodeWithChildren(node, "Enum"); |
| } |
| |
| visitExpressionStatement(ExpressionStatement node) { |
| visitNodeWithChildren(node, "ExpressionStatement"); |
| } |
| |
| visitFor(For node) { |
| visitNodeWithChildren(node, "For"); |
| } |
| |
| visitForIn(ForIn node) { |
| node.visitChildren(this); |
| closeNode(); |
| } |
| |
| visitAsyncForIn(AsyncForIn node) { |
| openNode(node, "AsyncForIn"); |
| visitForIn(node); |
| } |
| |
| visitSyncForIn(SyncForIn node) { |
| openNode(node, "SyncForIn"); |
| visitForIn(node); |
| } |
| |
| visitFunctionDeclaration(FunctionDeclaration node) { |
| visitNodeWithChildren(node, "FunctionDeclaration"); |
| } |
| |
| visitFunctionExpression(FunctionExpression node) { |
| openNode(node, "FunctionExpression", |
| {"getOrSet": tokenToStringOrNull(node.getOrSet)}); |
| visitChildNode(node.modifiers, "modifiers"); |
| visitChildNode(node.returnType, "returnType"); |
| visitChildNode(node.name, "name"); |
| visitChildNode(node.parameters, "parameters"); |
| visitChildNode(node.initializers, "initializers"); |
| visitChildNode(node.body, "body"); |
| closeNode(); |
| } |
| |
| visitFunctionTypeAnnotation(FunctionTypeAnnotation node) { |
| openNode(node, "FunctionTypeAnnotation"); |
| visitChildNode(node.returnType, "returnType"); |
| visitChildNode(node.typeParameters, "typeParameters"); |
| visitChildNode(node.formals, "formals"); |
| closeNode(); |
| } |
| |
| visitIdentifier(Identifier node) { |
| openAndCloseNode(node, "Identifier", {"token": node.token}); |
| } |
| |
| visitIf(If node) { |
| visitNodeWithChildren(node, "If"); |
| } |
| |
| visitLabel(Label node) { |
| visitNodeWithChildren(node, "Label"); |
| } |
| |
| visitLabeledStatement(LabeledStatement node) { |
| visitNodeWithChildren(node, "LabeledStatement"); |
| } |
| |
| // Custom. |
| printLiteral(Literal node, String type) { |
| openAndCloseNode(node, type, {"value": node.value.toString()}); |
| } |
| |
| visitLiteralBool(LiteralBool node) { |
| printLiteral(node, "LiteralBool"); |
| } |
| |
| visitLiteralDouble(LiteralDouble node) { |
| printLiteral(node, "LiteralDouble"); |
| } |
| |
| visitLiteralInt(LiteralInt node) { |
| printLiteral(node, "LiteralInt"); |
| } |
| |
| /** Returns token string value or [:null:] if token is [:null:]. */ |
| tokenToStringOrNull(Token token) => token == null ? null : token.stringValue; |
| |
| visitLiteralList(LiteralList node) { |
| openNode(node, "LiteralList", |
| {"constKeyword": tokenToStringOrNull(node.constKeyword)}); |
| visitChildNode(node.typeArguments, "typeArguments"); |
| visitChildNode(node.elements, "elements"); |
| closeNode(); |
| } |
| |
| visitLiteralMap(LiteralMap node) { |
| visitNodeWithChildren(node, "LiteralMap"); |
| } |
| |
| visitLiteralMapEntry(LiteralMapEntry node) { |
| visitNodeWithChildren(node, "LiteralMapEntry"); |
| } |
| |
| visitLiteralNull(LiteralNull node) { |
| printLiteral(node, "LiteralNull"); |
| } |
| |
| visitLiteralString(LiteralString node) { |
| openAndCloseNode(node, "LiteralString", {"value": node.token}); |
| } |
| |
| visitMixinApplication(MixinApplication node) { |
| visitNodeWithChildren(node, "MixinApplication"); |
| } |
| |
| visitModifiers(Modifiers node) { |
| visitNodeWithChildren(node, "Modifiers"); |
| } |
| |
| visitNamedArgument(NamedArgument node) { |
| visitNodeWithChildren(node, "NamedArgument"); |
| } |
| |
| visitNamedMixinApplication(NamedMixinApplication node) { |
| visitNodeWithChildren(node, "NamedMixinApplication"); |
| } |
| |
| visitNewExpression(NewExpression node) { |
| visitNodeWithChildren(node, "NewExpression"); |
| } |
| |
| visitNodeList(NodeList node) { |
| var params = {"delimiter": node.delimiter}; |
| if (node.isEmpty) { |
| openAndCloseNode(node, "NodeList", params); |
| } else { |
| openNode(node, "NodeList", params); |
| node.visitChildren(this); |
| closeNode(); |
| } |
| } |
| |
| visitNominalTypeAnnotation(NominalTypeAnnotation node) { |
| openNode(node, "NominalTypeAnnotation"); |
| visitChildNode(node.typeName, "typeName"); |
| visitChildNode(node.typeArguments, "typeArguments"); |
| closeNode(); |
| } |
| |
| visitOperator(Operator node) { |
| openAndCloseNode(node, "Operator", {"value": node.token}); |
| } |
| |
| visitParenthesizedExpression(ParenthesizedExpression node) { |
| visitNodeWithChildren(node, "ParenthesizedExpression"); |
| } |
| |
| visitRedirectingFactoryBody(RedirectingFactoryBody node) { |
| openNode(node, "RedirectingFactoryBody"); |
| visitChildNode(node.constructorReference, "constructorReference"); |
| closeNode(); |
| } |
| |
| visitRethrow(Rethrow node) { |
| visitNodeWithChildren(node, "Rethrow"); |
| } |
| |
| visitReturn(Return node) { |
| openNode(node, "Return"); |
| visitChildNode(node.expression, "expression"); |
| closeNode(); |
| } |
| |
| visitYield(Yield node) { |
| openNode(node, "Yield", {'star': node.starToken}); |
| visitChildNode(node.expression, "expression"); |
| closeNode(); |
| } |
| |
| visitChildNode(Node node, String fieldName) { |
| if (node == null) return; |
| addCurrentIndent(); |
| sb.write("<$fieldName>\n"); |
| pushTag(fieldName); |
| node.accept(this); |
| popTag(); |
| addCurrentIndent(); |
| sb.write("</$fieldName>\n"); |
| } |
| |
| openSendNodeWithFields(Send node, String type) { |
| openNode(node, type, { |
| "isPrefix": "${node.isPrefix}", |
| "isPostfix": "${node.isPostfix}", |
| "isIndex": "${node.isIndex}" |
| }); |
| visitChildNode(node.receiver, "receiver"); |
| visitChildNode(node.selector, "selector"); |
| visitChildNode(node.argumentsNode, "argumentsNode"); |
| } |
| |
| visitSend(Send node) { |
| openSendNodeWithFields(node, "Send"); |
| closeNode(); |
| } |
| |
| visitSendSet(SendSet node) { |
| openSendNodeWithFields(node, "SendSet"); |
| visitChildNode(node.assignmentOperator, "assignmentOperator"); |
| closeNode(); |
| } |
| |
| visitStringInterpolation(StringInterpolation node) { |
| visitNodeWithChildren(node, "StringInterpolation"); |
| } |
| |
| visitStringInterpolationPart(StringInterpolationPart node) { |
| visitNodeWithChildren(node, "StringInterpolationPart"); |
| } |
| |
| visitStringJuxtaposition(StringJuxtaposition node) { |
| visitNodeWithChildren(node, "StringJuxtaposition"); |
| } |
| |
| visitSwitchCase(SwitchCase node) { |
| visitNodeWithChildren(node, "SwitchCase"); |
| } |
| |
| visitSwitchStatement(SwitchStatement node) { |
| visitNodeWithChildren(node, "SwitchStatement"); |
| } |
| |
| visitLiteralSymbol(LiteralSymbol node) { |
| openNode(node, "LiteralSymbol"); |
| visitChildNode(node.identifiers, "identifiers"); |
| closeNode(); |
| } |
| |
| visitThrow(Throw node) { |
| visitNodeWithChildren(node, "Throw"); |
| } |
| |
| visitAwait(Await node) { |
| visitNodeWithChildren(node, "Await"); |
| } |
| |
| visitTryStatement(TryStatement node) { |
| visitNodeWithChildren(node, "TryStatement"); |
| } |
| |
| visitTypedef(Typedef node) { |
| visitNodeWithChildren(node, "Typedef"); |
| } |
| |
| visitTypeVariable(TypeVariable node) { |
| openNode(node, "TypeVariable"); |
| visitChildNode(node.name, "name"); |
| visitChildNode(node.bound, "bound"); |
| closeNode(); |
| } |
| |
| visitVariableDefinitions(VariableDefinitions node) { |
| openNode(node, "VariableDefinitions"); |
| visitChildNode(node.type, "type"); |
| visitChildNode(node.modifiers, "modifiers"); |
| visitChildNode(node.definitions, "definitions"); |
| closeNode(); |
| } |
| |
| visitWhile(While node) { |
| visitNodeWithChildren(node, "While"); |
| } |
| |
| visitMetadata(Metadata node) { |
| openNode(node, "Metadata", {"token": node.token}); |
| visitChildNode(node.expression, "expression"); |
| closeNode(); |
| } |
| |
| visitCombinator(Combinator node) { |
| openNode(node, "Combinator", |
| {"isShow": "${node.isShow}", "isHide": "${node.isHide}"}); |
| closeNode(); |
| } |
| |
| visitExport(Export node) { |
| openNode(node, "Export"); |
| visitChildNode(node.uri, "uri"); |
| if (node.conditionalUris != null) { |
| visitChildNode(node.conditionalUris, "conditionalUris"); |
| } |
| visitChildNode(node.combinators, "combinators"); |
| closeNode(); |
| } |
| |
| visitImport(Import node) { |
| openNode(node, "Import", {"isDeferred": "${node.isDeferred}"}); |
| visitChildNode(node.uri, "uri"); |
| if (node.conditionalUris != null) { |
| visitChildNode(node.conditionalUris, "conditionalUris"); |
| } |
| visitChildNode(node.combinators, "combinators"); |
| if (node.prefix != null) { |
| visitChildNode(node.prefix, "prefix"); |
| } |
| closeNode(); |
| } |
| |
| visitPart(Part node) { |
| openNode(node, "Part"); |
| visitChildNode(node.uri, "uri"); |
| closeNode(); |
| } |
| |
| visitPartOf(PartOf node) { |
| openNode(node, "PartOf"); |
| visitChildNode(node.name, "name"); |
| closeNode(); |
| } |
| |
| visitLibraryName(LibraryName node) { |
| openNode(node, "LibraryName"); |
| visitChildNode(node.name, "name"); |
| closeNode(); |
| } |
| |
| visitNode(Node node) { |
| unimplemented('visitNode', node: node); |
| } |
| |
| visitLibraryDependency(Node node) { |
| unimplemented('visitNode', node: node); |
| } |
| |
| visitLibraryTag(LibraryTag node) { |
| unimplemented('visitNode', node: node); |
| } |
| |
| visitLiteral(Literal node) { |
| unimplemented('visitNode', node: node); |
| } |
| |
| visitLoop(Loop node) { |
| unimplemented('visitNode', node: node); |
| } |
| |
| visitPostfix(Postfix node) { |
| unimplemented('visitNode', node: node); |
| } |
| |
| visitPrefix(Prefix node) { |
| unimplemented('visitNode', node: node); |
| } |
| |
| visitStringNode(StringNode node) { |
| unimplemented('visitNode', node: node); |
| } |
| |
| visitStatement(Statement node) { |
| unimplemented('visitNode', node: node); |
| } |
| |
| visitExpression(Expression node) { |
| unimplemented('visitNode', node: node); |
| } |
| |
| visitGotoStatement(GotoStatement node) { |
| unimplemented('visitNode', node: node); |
| } |
| |
| visitTypeAnnotation(TypeAnnotation node) { |
| unimplemented('visitNode', node: node); |
| } |
| |
| unimplemented(String message, {Node node}) { |
| throw message; |
| } |
| } |