/* * Copyright (c) 2012, the Dart project authors. * * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package com.google.dart.engine.ast.visitor; import com.google.dart.engine.ast.*; import com.google.dart.engine.scanner.Token; import com.google.dart.engine.utilities.dart.ParameterKind; import java.io.PrintWriter; /** * Instances of the class {@code ToSourceVisitor} write a source representation of a visited AST * node (and all of it's children) to a writer. * * @coverage dart.engine.ast */ public class ToSourceVisitor implements AstVisitor<Void> { /** * The writer to which the source is to be written. */ private PrintWriter writer; /** * Initialize a newly created visitor to write source code representing the visited nodes to the * given writer. * * @param writer the writer to which the source is to be written */ public ToSourceVisitor(PrintWriter writer) { this.writer = writer; } @Override public Void visitAdjacentStrings(AdjacentStrings node) { visitNodeListWithSeparator(node.getStrings(), " "); return null; } @Override public Void visitAnnotation(Annotation node) { writer.print('@'); visitNode(node.getName()); visitNodeWithPrefix(".", node.getConstructorName()); visitNode(node.getArguments()); return null; } @Override public Void visitArgumentList(ArgumentList node) { writer.print('('); visitNodeListWithSeparator(node.getArguments(), ", "); writer.print(')'); return null; } @Override public Void visitAsExpression(AsExpression node) { visitNode(node.getExpression()); writer.print(" as "); visitNode(node.getType()); return null; } @Override public Void visitAssertStatement(AssertStatement node) { writer.print("assert ("); visitNode(node.getCondition()); writer.print(");"); return null; } @Override public Void visitAssignmentExpression(AssignmentExpression node) { visitNode(node.getLeftHandSide()); writer.print(' '); writer.print(node.getOperator().getLexeme()); writer.print(' '); visitNode(node.getRightHandSide()); return null; } @Override public Void visitAwaitExpression(AwaitExpression node) { writer.print("await "); visitNode(node.getExpression()); writer.print(";"); // TODO (brianwilkerson) This line probably needs to be removed. return null; } @Override public Void visitBinaryExpression(BinaryExpression node) { visitNode(node.getLeftOperand()); writer.print(' '); writer.print(node.getOperator().getLexeme()); writer.print(' '); visitNode(node.getRightOperand()); return null; } @Override public Void visitBlock(Block node) { writer.print('{'); visitNodeListWithSeparator(node.getStatements(), " "); writer.print('}'); return null; } @Override public Void visitBlockFunctionBody(BlockFunctionBody node) { Token keyword = node.getKeyword(); if (keyword != null) { writer.print(keyword.getLexeme()); if (node.getStar() != null) { writer.print('*'); } writer.print(' '); } visitNode(node.getBlock()); return null; } @Override public Void visitBooleanLiteral(BooleanLiteral node) { writer.print(node.getLiteral().getLexeme()); return null; } @Override public Void visitBreakStatement(BreakStatement node) { writer.print("break"); visitNodeWithPrefix(" ", node.getLabel()); writer.print(";"); return null; } @Override public Void visitCascadeExpression(CascadeExpression node) { visitNode(node.getTarget()); visitNodeList(node.getCascadeSections()); return null; } @Override public Void visitCatchClause(CatchClause node) { visitNodeWithPrefix("on ", node.getExceptionType()); if (node.getCatchKeyword() != null) { if (node.getExceptionType() != null) { writer.print(' '); } writer.print("catch ("); visitNode(node.getExceptionParameter()); visitNodeWithPrefix(", ", node.getStackTraceParameter()); writer.print(") "); } else { writer.print(" "); } visitNode(node.getBody()); return null; } @Override public Void visitClassDeclaration(ClassDeclaration node) { visitNodeListWithSeparatorAndSuffix(node.getMetadata(), " ", " "); visitTokenWithSuffix(node.getAbstractKeyword(), " "); writer.print("class "); visitNode(node.getName()); visitNode(node.getTypeParameters()); visitNodeWithPrefix(" ", node.getExtendsClause()); visitNodeWithPrefix(" ", node.getWithClause()); visitNodeWithPrefix(" ", node.getImplementsClause()); writer.print(" {"); visitNodeListWithSeparator(node.getMembers(), " "); writer.print("}"); return null; } @Override public Void visitClassTypeAlias(ClassTypeAlias node) { visitNodeListWithSeparatorAndSuffix(node.getMetadata(), " ", " "); if (node.getAbstractKeyword() != null) { writer.print("abstract "); } writer.print("class "); visitNode(node.getName()); visitNode(node.getTypeParameters()); writer.print(" = "); visitNode(node.getSuperclass()); visitNodeWithPrefix(" ", node.getWithClause()); visitNodeWithPrefix(" ", node.getImplementsClause()); writer.print(";"); return null; } @Override public Void visitComment(Comment node) { // We don't print comments. return null; } @Override public Void visitCommentReference(CommentReference node) { // We don't print comment references. return null; } @Override public Void visitCompilationUnit(CompilationUnit node) { ScriptTag scriptTag = node.getScriptTag(); NodeList<Directive> directives = node.getDirectives(); visitNode(scriptTag); String prefix = scriptTag == null ? "" : " "; visitNodeListWithSeparatorAndPrefix(prefix, directives, " "); prefix = scriptTag == null && directives.isEmpty() ? "" : " "; visitNodeListWithSeparatorAndPrefix(prefix, node.getDeclarations(), " "); return null; } @Override public Void visitConditionalExpression(ConditionalExpression node) { visitNode(node.getCondition()); writer.print(" ? "); visitNode(node.getThenExpression()); writer.print(" : "); visitNode(node.getElseExpression()); return null; } @Override public Void visitConstructorDeclaration(ConstructorDeclaration node) { visitNodeListWithSeparatorAndSuffix(node.getMetadata(), " ", " "); visitTokenWithSuffix(node.getExternalKeyword(), " "); visitTokenWithSuffix(node.getConstKeyword(), " "); visitTokenWithSuffix(node.getFactoryKeyword(), " "); visitNode(node.getReturnType()); visitNodeWithPrefix(".", node.getName()); visitNode(node.getParameters()); visitNodeListWithSeparatorAndPrefix(" : ", node.getInitializers(), ", "); visitNodeWithPrefix(" = ", node.getRedirectedConstructor()); visitFunctionWithPrefix(" ", node.getBody()); return null; } @Override public Void visitConstructorFieldInitializer(ConstructorFieldInitializer node) { visitTokenWithSuffix(node.getKeyword(), "."); visitNode(node.getFieldName()); writer.print(" = "); visitNode(node.getExpression()); return null; } @Override public Void visitConstructorName(ConstructorName node) { visitNode(node.getType()); visitNodeWithPrefix(".", node.getName()); return null; } @Override public Void visitContinueStatement(ContinueStatement node) { writer.print("continue"); visitNodeWithPrefix(" ", node.getLabel()); writer.print(";"); return null; } @Override public Void visitDeclaredIdentifier(DeclaredIdentifier node) { visitNodeListWithSeparatorAndSuffix(node.getMetadata(), " ", " "); visitTokenWithSuffix(node.getKeyword(), " "); visitNodeWithSuffix(node.getType(), " "); visitNode(node.getIdentifier()); return null; } @Override public Void visitDefaultFormalParameter(DefaultFormalParameter node) { visitNode(node.getParameter()); if (node.getSeparator() != null) { writer.print(" "); writer.print(node.getSeparator().getLexeme()); visitNodeWithPrefix(" ", node.getDefaultValue()); } return null; } @Override public Void visitDoStatement(DoStatement node) { writer.print("do "); visitNode(node.getBody()); writer.print(" while ("); visitNode(node.getCondition()); writer.print(");"); return null; } @Override public Void visitDoubleLiteral(DoubleLiteral node) { writer.print(node.getLiteral().getLexeme()); return null; } @Override public Void visitEmptyFunctionBody(EmptyFunctionBody node) { writer.print(';'); return null; } @Override public Void visitEmptyStatement(EmptyStatement node) { writer.print(';'); return null; } @Override public Void visitEnumConstantDeclaration(EnumConstantDeclaration node) { visitNodeListWithSeparatorAndSuffix(node.getMetadata(), " ", " "); visitNode(node.getName()); return null; } @Override public Void visitEnumDeclaration(EnumDeclaration node) { visitNodeListWithSeparatorAndSuffix(node.getMetadata(), " ", " "); writer.print("enum "); visitNode(node.getName()); writer.print(" {"); visitNodeListWithSeparator(node.getConstants(), ", "); writer.print("}"); return null; } @Override public Void visitExportDirective(ExportDirective node) { visitNodeListWithSeparatorAndSuffix(node.getMetadata(), " ", " "); writer.print("export "); visitNode(node.getUri()); visitNodeListWithSeparatorAndPrefix(" ", node.getCombinators(), " "); writer.print(';'); return null; } @Override public Void visitExpressionFunctionBody(ExpressionFunctionBody node) { Token keyword = node.getKeyword(); if (keyword != null) { writer.print(keyword.getLexeme()); writer.print(' '); } writer.print("=> "); visitNode(node.getExpression()); if (node.getSemicolon() != null) { writer.print(';'); } return null; } @Override public Void visitExpressionStatement(ExpressionStatement node) { visitNode(node.getExpression()); writer.print(';'); return null; } @Override public Void visitExtendsClause(ExtendsClause node) { writer.print("extends "); visitNode(node.getSuperclass()); return null; } @Override public Void visitFieldDeclaration(FieldDeclaration node) { visitNodeListWithSeparatorAndSuffix(node.getMetadata(), " ", " "); visitTokenWithSuffix(node.getStaticKeyword(), " "); visitNode(node.getFields()); writer.print(";"); return null; } @Override public Void visitFieldFormalParameter(FieldFormalParameter node) { visitTokenWithSuffix(node.getKeyword(), " "); visitNodeWithSuffix(node.getType(), " "); writer.print("this."); visitNode(node.getIdentifier()); visitNode(node.getParameters()); return null; } @Override public Void visitForEachStatement(ForEachStatement node) { DeclaredIdentifier loopVariable = node.getLoopVariable(); if (node.getAwaitKeyword() != null) { writer.print("await "); } writer.print("for ("); if (loopVariable == null) { visitNode(node.getIdentifier()); } else { visitNode(loopVariable); } writer.print(" in "); visitNode(node.getIterator()); writer.print(") "); visitNode(node.getBody()); return null; } @Override public Void visitFormalParameterList(FormalParameterList node) { String groupEnd = null; writer.print('('); NodeList<FormalParameter> parameters = node.getParameters(); int size = parameters.size(); for (int i = 0; i < size; i++) { FormalParameter parameter = parameters.get(i); if (i > 0) { writer.print(", "); } if (groupEnd == null && parameter instanceof DefaultFormalParameter) { if (parameter.getKind() == ParameterKind.NAMED) { groupEnd = "}"; writer.print('{'); } else { groupEnd = "]"; writer.print('['); } } parameter.accept(this); } if (groupEnd != null) { writer.print(groupEnd); } writer.print(')'); return null; } @Override public Void visitForStatement(ForStatement node) { Expression initialization = node.getInitialization(); writer.print("for ("); if (initialization != null) { visitNode(initialization); } else { visitNode(node.getVariables()); } writer.print(";"); visitNodeWithPrefix(" ", node.getCondition()); writer.print(";"); visitNodeListWithSeparatorAndPrefix(" ", node.getUpdaters(), ", "); writer.print(") "); visitNode(node.getBody()); return null; } @Override public Void visitFunctionDeclaration(FunctionDeclaration node) { visitNodeListWithSeparatorAndSuffix(node.getMetadata(), " ", " "); visitNodeWithSuffix(node.getReturnType(), " "); visitTokenWithSuffix(node.getPropertyKeyword(), " "); visitNode(node.getName()); visitNode(node.getFunctionExpression()); return null; } @Override public Void visitFunctionDeclarationStatement(FunctionDeclarationStatement node) { visitNode(node.getFunctionDeclaration()); return null; } @Override public Void visitFunctionExpression(FunctionExpression node) { visitNode(node.getParameters()); writer.print(' '); visitNode(node.getBody()); return null; } @Override public Void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { visitNode(node.getFunction()); visitNode(node.getArgumentList()); return null; } @Override public Void visitFunctionTypeAlias(FunctionTypeAlias node) { visitNodeListWithSeparatorAndSuffix(node.getMetadata(), " ", " "); writer.print("typedef "); visitNodeWithSuffix(node.getReturnType(), " "); visitNode(node.getName()); visitNode(node.getTypeParameters()); visitNode(node.getParameters()); writer.print(";"); return null; } @Override public Void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) { visitNodeWithSuffix(node.getReturnType(), " "); visitNode(node.getIdentifier()); visitNode(node.getParameters()); return null; } @Override public Void visitHideCombinator(HideCombinator node) { writer.print("hide "); visitNodeListWithSeparator(node.getHiddenNames(), ", "); return null; } @Override public Void visitIfStatement(IfStatement node) { writer.print("if ("); visitNode(node.getCondition()); writer.print(") "); visitNode(node.getThenStatement()); visitNodeWithPrefix(" else ", node.getElseStatement()); return null; } @Override public Void visitImplementsClause(ImplementsClause node) { writer.print("implements "); visitNodeListWithSeparator(node.getInterfaces(), ", "); return null; } @Override public Void visitImportDirective(ImportDirective node) { visitNodeListWithSeparatorAndSuffix(node.getMetadata(), " ", " "); writer.print("import "); visitNode(node.getUri()); if (node.getDeferredToken() != null) { writer.print(" deferred"); } visitNodeWithPrefix(" as ", node.getPrefix()); visitNodeListWithSeparatorAndPrefix(" ", node.getCombinators(), " "); writer.print(';'); return null; } @Override public Void visitIndexExpression(IndexExpression node) { if (node.isCascaded()) { writer.print(".."); } else { visitNode(node.getTarget()); } writer.print('['); visitNode(node.getIndex()); writer.print(']'); return null; } @Override public Void visitInstanceCreationExpression(InstanceCreationExpression node) { visitTokenWithSuffix(node.getKeyword(), " "); visitNode(node.getConstructorName()); visitNode(node.getArgumentList()); return null; } @Override public Void visitIntegerLiteral(IntegerLiteral node) { writer.print(node.getLiteral().getLexeme()); return null; } @Override public Void visitInterpolationExpression(InterpolationExpression node) { if (node.getRightBracket() != null) { writer.print("${"); visitNode(node.getExpression()); writer.print("}"); } else { writer.print("$"); visitNode(node.getExpression()); } return null; } @Override public Void visitInterpolationString(InterpolationString node) { writer.print(node.getContents().getLexeme()); return null; } @Override public Void visitIsExpression(IsExpression node) { visitNode(node.getExpression()); if (node.getNotOperator() == null) { writer.print(" is "); } else { writer.print(" is! "); } visitNode(node.getType()); return null; } @Override public Void visitLabel(Label node) { visitNode(node.getLabel()); writer.print(":"); return null; } @Override public Void visitLabeledStatement(LabeledStatement node) { visitNodeListWithSeparatorAndSuffix(node.getLabels(), " ", " "); visitNode(node.getStatement()); return null; } @Override public Void visitLibraryDirective(LibraryDirective node) { visitNodeListWithSeparatorAndSuffix(node.getMetadata(), " ", " "); writer.print("library "); visitNode(node.getName()); writer.print(';'); return null; } @Override public Void visitLibraryIdentifier(LibraryIdentifier node) { writer.print(node.getName()); return null; } @Override public Void visitListLiteral(ListLiteral node) { if (node.getConstKeyword() != null) { writer.print(node.getConstKeyword().getLexeme()); writer.print(' '); } visitNodeWithSuffix(node.getTypeArguments(), " "); writer.print("["); visitNodeListWithSeparator(node.getElements(), ", "); writer.print("]"); return null; } @Override public Void visitMapLiteral(MapLiteral node) { if (node.getConstKeyword() != null) { writer.print(node.getConstKeyword().getLexeme()); writer.print(' '); } visitNodeWithSuffix(node.getTypeArguments(), " "); writer.print("{"); visitNodeListWithSeparator(node.getEntries(), ", "); writer.print("}"); return null; } @Override public Void visitMapLiteralEntry(MapLiteralEntry node) { visitNode(node.getKey()); writer.print(" : "); visitNode(node.getValue()); return null; } @Override public Void visitMethodDeclaration(MethodDeclaration node) { visitNodeListWithSeparatorAndSuffix(node.getMetadata(), " ", " "); visitTokenWithSuffix(node.getExternalKeyword(), " "); visitTokenWithSuffix(node.getModifierKeyword(), " "); visitNodeWithSuffix(node.getReturnType(), " "); visitTokenWithSuffix(node.getPropertyKeyword(), " "); visitTokenWithSuffix(node.getOperatorKeyword(), " "); visitNode(node.getName()); if (!node.isGetter()) { visitNode(node.getParameters()); } visitFunctionWithPrefix(" ", node.getBody()); return null; } @Override public Void visitMethodInvocation(MethodInvocation node) { if (node.isCascaded()) { writer.print(".."); } else { visitNodeWithSuffix(node.getTarget(), "."); } visitNode(node.getMethodName()); visitNode(node.getArgumentList()); return null; } @Override public Void visitNamedExpression(NamedExpression node) { visitNode(node.getName()); visitNodeWithPrefix(" ", node.getExpression()); return null; } @Override public Void visitNativeClause(NativeClause node) { writer.print("native "); visitNode(node.getName()); return null; } @Override public Void visitNativeFunctionBody(NativeFunctionBody node) { writer.print("native "); visitNode(node.getStringLiteral()); writer.print(';'); return null; } @Override public Void visitNullLiteral(NullLiteral node) { writer.print("null"); return null; } @Override public Void visitParenthesizedExpression(ParenthesizedExpression node) { writer.print('('); visitNode(node.getExpression()); writer.print(')'); return null; } @Override public Void visitPartDirective(PartDirective node) { visitNodeListWithSeparatorAndSuffix(node.getMetadata(), " ", " "); writer.print("part "); visitNode(node.getUri()); writer.print(';'); return null; } @Override public Void visitPartOfDirective(PartOfDirective node) { visitNodeListWithSeparatorAndSuffix(node.getMetadata(), " ", " "); writer.print("part of "); visitNode(node.getLibraryName()); writer.print(';'); return null; } @Override public Void visitPostfixExpression(PostfixExpression node) { visitNode(node.getOperand()); writer.print(node.getOperator().getLexeme()); return null; } @Override public Void visitPrefixedIdentifier(PrefixedIdentifier node) { visitNode(node.getPrefix()); writer.print('.'); visitNode(node.getIdentifier()); return null; } @Override public Void visitPrefixExpression(PrefixExpression node) { writer.print(node.getOperator().getLexeme()); visitNode(node.getOperand()); return null; } @Override public Void visitPropertyAccess(PropertyAccess node) { if (node.isCascaded()) { writer.print(".."); } else { visitNode(node.getTarget()); writer.print('.'); } visitNode(node.getPropertyName()); return null; } @Override public Void visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) { writer.print("this"); visitNodeWithPrefix(".", node.getConstructorName()); visitNode(node.getArgumentList()); return null; } @Override public Void visitRethrowExpression(RethrowExpression node) { writer.print("rethrow"); return null; } @Override public Void visitReturnStatement(ReturnStatement node) { Expression expression = node.getExpression(); if (expression == null) { writer.print("return;"); } else { writer.print("return "); expression.accept(this); writer.print(";"); } return null; } @Override public Void visitScriptTag(ScriptTag node) { writer.print(node.getScriptTag().getLexeme()); return null; } @Override public Void visitShowCombinator(ShowCombinator node) { writer.print("show "); visitNodeListWithSeparator(node.getShownNames(), ", "); return null; } @Override public Void visitSimpleFormalParameter(SimpleFormalParameter node) { visitTokenWithSuffix(node.getKeyword(), " "); visitNodeWithSuffix(node.getType(), " "); visitNode(node.getIdentifier()); return null; } @Override public Void visitSimpleIdentifier(SimpleIdentifier node) { writer.print(node.getToken().getLexeme()); return null; } @Override public Void visitSimpleStringLiteral(SimpleStringLiteral node) { writer.print(node.getLiteral().getLexeme()); return null; } @Override public Void visitStringInterpolation(StringInterpolation node) { visitNodeList(node.getElements()); return null; } @Override public Void visitSuperConstructorInvocation(SuperConstructorInvocation node) { writer.print("super"); visitNodeWithPrefix(".", node.getConstructorName()); visitNode(node.getArgumentList()); return null; } @Override public Void visitSuperExpression(SuperExpression node) { writer.print("super"); return null; } @Override public Void visitSwitchCase(SwitchCase node) { visitNodeListWithSeparatorAndSuffix(node.getLabels(), " ", " "); writer.print("case "); visitNode(node.getExpression()); writer.print(": "); visitNodeListWithSeparator(node.getStatements(), " "); return null; } @Override public Void visitSwitchDefault(SwitchDefault node) { visitNodeListWithSeparatorAndSuffix(node.getLabels(), " ", " "); writer.print("default: "); visitNodeListWithSeparator(node.getStatements(), " "); return null; } @Override public Void visitSwitchStatement(SwitchStatement node) { writer.print("switch ("); visitNode(node.getExpression()); writer.print(") {"); visitNodeListWithSeparator(node.getMembers(), " "); writer.print("}"); return null; } @Override public Void visitSymbolLiteral(SymbolLiteral node) { writer.print("#"); Token[] components = node.getComponents(); for (int i = 0; i < components.length; i++) { if (i > 0) { writer.print("."); } writer.print(components[i].getLexeme()); } return null; } @Override public Void visitThisExpression(ThisExpression node) { writer.print("this"); return null; } @Override public Void visitThrowExpression(ThrowExpression node) { writer.print("throw "); visitNode(node.getExpression()); return null; } @Override public Void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { visitNodeWithSuffix(node.getVariables(), ";"); return null; } @Override public Void visitTryStatement(TryStatement node) { writer.print("try "); visitNode(node.getBody()); visitNodeListWithSeparatorAndPrefix(" ", node.getCatchClauses(), " "); visitNodeWithPrefix(" finally ", node.getFinallyBlock()); return null; } @Override public Void visitTypeArgumentList(TypeArgumentList node) { writer.print('<'); visitNodeListWithSeparator(node.getArguments(), ", "); writer.print('>'); return null; } @Override public Void visitTypeName(TypeName node) { visitNode(node.getName()); visitNode(node.getTypeArguments()); return null; } @Override public Void visitTypeParameter(TypeParameter node) { visitNodeListWithSeparatorAndSuffix(node.getMetadata(), " ", " "); visitNode(node.getName()); visitNodeWithPrefix(" extends ", node.getBound()); return null; } @Override public Void visitTypeParameterList(TypeParameterList node) { writer.print('<'); visitNodeListWithSeparator(node.getTypeParameters(), ", "); writer.print('>'); return null; } @Override public Void visitVariableDeclaration(VariableDeclaration node) { visitNodeListWithSeparatorAndSuffix(node.getMetadata(), " ", " "); visitNode(node.getName()); visitNodeWithPrefix(" = ", node.getInitializer()); return null; } @Override public Void visitVariableDeclarationList(VariableDeclarationList node) { visitNodeListWithSeparatorAndSuffix(node.getMetadata(), " ", " "); visitTokenWithSuffix(node.getKeyword(), " "); visitNodeWithSuffix(node.getType(), " "); visitNodeListWithSeparator(node.getVariables(), ", "); return null; } @Override public Void visitVariableDeclarationStatement(VariableDeclarationStatement node) { visitNode(node.getVariables()); writer.print(";"); return null; } @Override public Void visitWhileStatement(WhileStatement node) { writer.print("while ("); visitNode(node.getCondition()); writer.print(") "); visitNode(node.getBody()); return null; } @Override public Void visitWithClause(WithClause node) { writer.print("with "); visitNodeListWithSeparator(node.getMixinTypes(), ", "); return null; } @Override public Void visitYieldStatement(YieldStatement node) { if (node.getStar() != null) { writer.print("yield* "); } else { writer.print("yield "); } visitNode(node.getExpression()); writer.print(";"); return null; } /** * Visit the given function body, printing the prefix before if given body is not empty. * * @param prefix the prefix to be printed if there is a node to visit * @param body the function body to be visited */ private void visitFunctionWithPrefix(String prefix, FunctionBody body) { if (!(body instanceof EmptyFunctionBody)) { writer.print(prefix); } visitNode(body); } /** * Safely visit the given node. * * @param node the node to be visited */ private void visitNode(AstNode node) { if (node != null) { node.accept(this); } } /** * Print a list of nodes without any separation. * * @param nodes the nodes to be printed * @param separator the separator to be printed between adjacent nodes */ private void visitNodeList(NodeList<? extends AstNode> nodes) { visitNodeListWithSeparator(nodes, ""); } /** * Print a list of nodes, separated by the given separator. * * @param nodes the nodes to be printed * @param separator the separator to be printed between adjacent nodes */ private void visitNodeListWithSeparator(NodeList<? extends AstNode> nodes, String separator) { if (nodes != null) { int size = nodes.size(); for (int i = 0; i < size; i++) { if (i > 0) { writer.print(separator); } nodes.get(i).accept(this); } } } /** * Print a list of nodes, separated by the given separator. * * @param prefix the prefix to be printed if the list is not empty * @param nodes the nodes to be printed * @param separator the separator to be printed between adjacent nodes */ private void visitNodeListWithSeparatorAndPrefix(String prefix, NodeList<? extends AstNode> nodes, String separator) { if (nodes != null) { int size = nodes.size(); if (size > 0) { writer.print(prefix); for (int i = 0; i < size; i++) { if (i > 0) { writer.print(separator); } nodes.get(i).accept(this); } } } } /** * Print a list of nodes, separated by the given separator. * * @param nodes the nodes to be printed * @param separator the separator to be printed between adjacent nodes * @param suffix the suffix to be printed if the list is not empty */ private void visitNodeListWithSeparatorAndSuffix(NodeList<? extends AstNode> nodes, String separator, String suffix) { if (nodes != null) { int size = nodes.size(); if (size > 0) { for (int i = 0; i < size; i++) { if (i > 0) { writer.print(separator); } nodes.get(i).accept(this); } writer.print(suffix); } } } /** * Safely visit the given node, printing the prefix before the node if it is non-{@code null}. * * @param prefix the prefix to be printed if there is a node to visit * @param node the node to be visited */ private void visitNodeWithPrefix(String prefix, AstNode node) { if (node != null) { writer.print(prefix); node.accept(this); } } /** * Safely visit the given node, printing the suffix after the node if it is non-{@code null}. * * @param suffix the suffix to be printed if there is a node to visit * @param node the node to be visited */ private void visitNodeWithSuffix(AstNode node, String suffix) { if (node != null) { node.accept(this); writer.print(suffix); } } /** * Safely visit the given node, printing the suffix after the node if it is non-{@code null}. * * @param suffix the suffix to be printed if there is a node to visit * @param node the node to be visited */ private void visitTokenWithSuffix(Token token, String suffix) { if (token != null) { writer.print(token.getLexeme()); writer.print(suffix); } } }