/* * Copyright (C) 2012-2016 NS Solutions Corporation * * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 * * 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.htmlhifive.tools.rhino; import static com.htmlhifive.tools.rhino.Util.addChild; import static com.htmlhifive.tools.rhino.Util.addChildren; import static com.htmlhifive.tools.rhino.Util.addChildrenForVariables; import static com.htmlhifive.tools.rhino.Util.isVSDoc; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import org.apache.commons.lang.StringUtils; import org.mozilla.javascript.Node; import org.mozilla.javascript.Token; import org.mozilla.javascript.ast.ArrayComprehension; import org.mozilla.javascript.ast.ArrayComprehensionLoop; import org.mozilla.javascript.ast.ArrayLiteral; import org.mozilla.javascript.ast.Assignment; import org.mozilla.javascript.ast.AstNode; import org.mozilla.javascript.ast.AstRoot; import org.mozilla.javascript.ast.Block; import org.mozilla.javascript.ast.BreakStatement; import org.mozilla.javascript.ast.CatchClause; import org.mozilla.javascript.ast.Comment; import org.mozilla.javascript.ast.ConditionalExpression; import org.mozilla.javascript.ast.ContinueStatement; import org.mozilla.javascript.ast.DoLoop; import org.mozilla.javascript.ast.ElementGet; import org.mozilla.javascript.ast.EmptyExpression; import org.mozilla.javascript.ast.EmptyStatement; import org.mozilla.javascript.ast.ErrorNode; import org.mozilla.javascript.ast.ExpressionStatement; import org.mozilla.javascript.ast.ForInLoop; import org.mozilla.javascript.ast.ForLoop; import org.mozilla.javascript.ast.FunctionCall; import org.mozilla.javascript.ast.FunctionNode; import org.mozilla.javascript.ast.IfStatement; import org.mozilla.javascript.ast.InfixExpression; import org.mozilla.javascript.ast.Jump; import org.mozilla.javascript.ast.KeywordLiteral; import org.mozilla.javascript.ast.Label; import org.mozilla.javascript.ast.LabeledStatement; import org.mozilla.javascript.ast.LetNode; import org.mozilla.javascript.ast.Loop; import org.mozilla.javascript.ast.Name; import org.mozilla.javascript.ast.NewExpression; import org.mozilla.javascript.ast.NodeVisitor; import org.mozilla.javascript.ast.NumberLiteral; import org.mozilla.javascript.ast.ObjectLiteral; import org.mozilla.javascript.ast.ObjectProperty; import org.mozilla.javascript.ast.ParenthesizedExpression; import org.mozilla.javascript.ast.PropertyGet; import org.mozilla.javascript.ast.RegExpLiteral; import org.mozilla.javascript.ast.ReturnStatement; import org.mozilla.javascript.ast.Scope; import org.mozilla.javascript.ast.ScriptNode; import org.mozilla.javascript.ast.StringLiteral; import org.mozilla.javascript.ast.SwitchCase; import org.mozilla.javascript.ast.SwitchStatement; import org.mozilla.javascript.ast.ThrowStatement; import org.mozilla.javascript.ast.TryStatement; import org.mozilla.javascript.ast.UnaryExpression; import org.mozilla.javascript.ast.VariableDeclaration; import org.mozilla.javascript.ast.VariableInitializer; import org.mozilla.javascript.ast.WhileLoop; import org.mozilla.javascript.ast.WithStatement; import org.mozilla.javascript.ast.Word; import org.mozilla.javascript.ast.XmlDotQuery; import org.mozilla.javascript.ast.XmlElemRef; import org.mozilla.javascript.ast.XmlExpression; import org.mozilla.javascript.ast.XmlFragment; import org.mozilla.javascript.ast.XmlLiteral; import org.mozilla.javascript.ast.XmlMemberGet; import org.mozilla.javascript.ast.XmlPropRef; import org.mozilla.javascript.ast.XmlString; import org.mozilla.javascript.ast.Yield; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * ツリー構造をとる様に、ノードを追加する. */ public class AddNodeInfoVisitor implements NodeVisitor { private static Logger logger = LoggerFactory.getLogger(AddNodeInfoVisitor.class); /** 深さ. */ protected int depth = 0; /** インデント. */ protected int indent = 0; /** コンストラクタ. */ public AddNodeInfoVisitor() { } @Override public boolean visit(AstNode node) { depth = Util.getPropValue(node, Constants.DEPTH); indent = Util.getPropValue(node, Constants.INDENT); // --------------------------------------------------------------------- if (node instanceof ArrayLiteral) { visit((ArrayLiteral) node); } else if (node instanceof Block) { visit((Block) node); } else if (node instanceof CatchClause) { visit((CatchClause) node); } else if (node instanceof Comment) { visit((Comment) node); } else if (node instanceof ConditionalExpression) { visit((ConditionalExpression) node); } else if (node instanceof ElementGet) { visit((ElementGet) node); } else if (node instanceof EmptyStatement){ visit((EmptyStatement) node); } else if (node instanceof EmptyExpression) { visit((EmptyExpression) node); } else if (node instanceof ErrorNode) { visit((ErrorNode) node); } else if (node instanceof ExpressionStatement) { visit((ExpressionStatement) node); } else if (node instanceof NewExpression) { visit((NewExpression) node); } else if (node instanceof FunctionCall) { visit((FunctionCall) node); } else if (node instanceof IfStatement) { visit((IfStatement) node); } // --------------------------------------------------------------------- // else if (node instanceof Assignment) { // InfixExpressionと同様 else if (node instanceof ObjectProperty) { visit((ObjectProperty) node); } else if (node instanceof PropertyGet) { visit((PropertyGet) node); } else if (node instanceof XmlDotQuery) { visit((XmlDotQuery) node); } else if (node instanceof XmlMemberGet) { visit((XmlMemberGet) node); } else if (node instanceof InfixExpression) { visit((InfixExpression) node); } // --------------------------------------------------------------------- else if (node instanceof BreakStatement) { visit((BreakStatement) node); } else if (node instanceof ContinueStatement) { visit((ContinueStatement) node); } else if (node instanceof Label) { visit((Label) node); } else if (node instanceof ArrayComprehension) { visit((ArrayComprehension) node); } else if (node instanceof LetNode) { visit((LetNode) node); } else if (node instanceof DoLoop) { visit((DoLoop) node); } else if (node instanceof ArrayComprehensionLoop) { visit((ArrayComprehensionLoop) node); } else if (node instanceof ForInLoop) { visit((ForInLoop) node); } else if (node instanceof ForLoop) { visit((ForLoop) node); } else if (node instanceof WhileLoop) { visit((WhileLoop) node); } else if (node instanceof AstRoot) { // } else if (node instanceof FunctionNode) { visit((FunctionNode) node); } else if (node instanceof SwitchStatement) { visit((SwitchStatement) node); } else if (node instanceof ScriptNode) { // } else if (node instanceof Scope) { visit((Scope) node); } else if (node instanceof Jump) { // } else if (node instanceof KeywordLiteral) { visit((KeywordLiteral) node); } else if (node instanceof LabeledStatement) { visit((LabeledStatement) node); } else if (node instanceof Name) { visit((Name) node); } else if (node instanceof NumberLiteral) { visit((NumberLiteral) node); } else if (node instanceof ObjectLiteral) { visit((ObjectLiteral) node); } else if (node instanceof ParenthesizedExpression) { visit((ParenthesizedExpression) node); } else if (node instanceof RegExpLiteral) { visit((RegExpLiteral) node); } else if (node instanceof ReturnStatement) { visit((ReturnStatement) node); } else if (node instanceof StringLiteral) { visit((StringLiteral) node); } else if (node instanceof SwitchCase) { visit((SwitchCase) node); } else if (node instanceof ThrowStatement) { visit((ThrowStatement) node); } else if (node instanceof TryStatement) { visit((TryStatement) node); } else if (node instanceof UnaryExpression) { visit((UnaryExpression) node); } else if (node instanceof VariableDeclaration) { visit((VariableDeclaration) node); } else if (node instanceof VariableInitializer) { visit((VariableInitializer) node); } else if (node instanceof WithStatement) { visit((WithStatement) node); } else if (node instanceof XmlExpression) { visit((XmlExpression) node); } else if (node instanceof XmlString) { visit((XmlString) node); } else if (node instanceof XmlLiteral) { visit((XmlLiteral) node); } else if (node instanceof XmlElemRef) { visit((XmlElemRef) node); } else if (node instanceof XmlPropRef) { visit((XmlPropRef) node); } else if (node instanceof Yield) { visit((Yield) node); } else if (node instanceof Word) { // } else { System.out.println(node.toSource()); throw new IllegalArgumentException(); } return true; } // ------------------------------------------------------------------------- protected void visit(ArrayLiteral an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, "["); pos = addChildren(an, pos, an.getElements(), depth); pos = addChild(an, an.getLength() - 1, "]"); } protected void visit(Block an) { List<Node> children = new ArrayList<Node>(); for (Node kid : an) { children.add(kid); } an.removeChildren(); // int pos = addChild(an, 0, Util.makeIndent(indent)); // TODO pos = addChild(an, pos, "{" + Constants.LINE_SEPARATOR); int newDepth = depth + 1; for (Node child : children) { pos = addChild(an, (AstNode) child, newDepth, newDepth); } String indent = Util.makeIndent(depth); if (null != indent) { pos = addChild(an, an.getLength() - 2 - indent.length(), indent); } pos = addChild(an, an.getLength() - 2, "}" + Constants.LINE_SEPARATOR); } protected void visit(CatchClause an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, "catch ("); pos = addChild(an, an.getVarName(), depth); if (null != an.getCatchCondition()) { pos = addChild(an, pos, " if "); pos = addChild(an, an.getCatchCondition(), depth); } pos = addChild(an, an.getBody().getPosition() - 1, ") "); pos = addChild(an, an.getBody(), depth); } protected void visit(Comment an) { logger.debug("Comment Visit Start--------------------------------"); Token.CommentType type = an.getCommentType(); logger.debug("Comment type :" + type.toString()); AstNode parent = an.getParent(); logger.debug("parent node " + parent.shortName()); int parentDepth = Util.getPropValue(parent, Constants.DEPTH); int pos = 0; if (type == Token.CommentType.JSDOC) { // 2012/4/18 修正 if (an.getProp(Constants.VSDOC_FLAG) == null) { pos = addChild(an, pos, Constants.LINE_SEPARATOR); } // pos = addChild(an, pos, Util.makeIndent(parentDepth + 1)); } else if (type == Token.CommentType.LINE) { // TODO かなり制御が煩雑. // prev -> コメントノードのひとつ前のノードの一番最後の子供 AstNode prev = Util.getLast(Util.getPrev(an)); if ((null == prev) || (prev.getLineno() != an.getLineno())) { // 直前ノードと、行コメントが別の行であれば、インデントを1足して出力. // pos = addChild(an, pos, Util.makeIndent(parentDepth + 1)); } else { if (prev instanceof Word) { Word word = (Word) prev; String wordValue = word.getValue(); logger.debug("Word value : " + wordValue); if (wordValue.trim().length() == 0) { if (wordValue.equals(Constants.LINE_SEPARATOR)) { while (true) { if (!(prev instanceof Word) || (Constants.LINE_SEPARATOR.equals(((Word) prev).getValue()))) { break; } prev = Util.getLast(Util.getPrev(prev)); } if ((prev.getLineno() == an.getLineno())) { // 元ファイル中、行コメントと、直前ノードが同じ行であれば、間の改行を取り除く. word.setValue(wordValue.substring(0, wordValue.length() - 1)); } } // pos = addChild(an, pos, Util.makeIndent(1)); } else if (wordValue.endsWith(Constants.LINE_SEPARATOR)) { word.setValue(wordValue.substring(0, wordValue.length() - 1)); } } } } // 2012/4/18 修正 // String document = StringUtils.isEmpty(an.getJsDoc()) ? an.getValue() : an.getJsDoc(); // pos = addChild(an, pos, document); // pos = addChild(an, an.getLength() - 1, "\n"); // JsDoc/VSDoc生成時切り替え機能未リリースのため一旦処理を簡素化 2013/05/31 by pos = addChild(an, 0, an.getValue()); Token.CommentType commentType = an.getCommentType(); if (commentType == Token.CommentType.LINE || commentType == Token.CommentType.JSDOC) { addChild(an, pos, Constants.LINE_SEPARATOR); } /* String document = StringUtils.isEmpty(an.getJsDoc()) ? an.getValue() : an.getJsDoc(); // 一行ずつ取得 StringTokenizer st = new StringTokenizer(document, Constants.LINE_SEPARATOR); boolean first = true; while (st.hasMoreTokens()) { String token = st.nextToken(); logger.debug(token); if (!(parent instanceof AstRoot)) { // 親がAstRootだった場合は深さは0 logger.debug("parentDepth" + parentDepth); pos = addChild(an, pos, Util.makeIndent(parentDepth + 1)); } if (!first && Token.CommentType.JSDOC == an.getCommentType() && !isVSDoc(token)) { // 一行目以外は空白を入れる pos = addChild(an, pos, " "); } first = false; pos = addChild(an, pos, token); pos = addChild(an, pos, Constants.LINE_SEPARATOR); } */ logger.debug("Comment Visit end--------------------------------"); } protected void visit(ConditionalExpression an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, an.getTestExpression(), depth); pos = addChild(an, pos, " ? "); pos = addChild(an, an.getTrueExpression(), depth); pos = addChild(an, pos, " : "); pos = addChild(an, an.getFalseExpression(), depth); } protected void visit(ElementGet an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, an.getTarget(), depth); pos = addChild(an, pos, "["); pos = addChild(an, an.getElement(), depth); pos = addChild(an, an.getLength() - 1, "]"); } protected void visit(EmptyExpression an) { int pos = addChild(an, 0, Util.makeIndent(indent)); } protected void visit(EmptyStatement an) { int pos = addChild(an, 0, Util.makeIndent(indent)); } protected void visit(ErrorNode an) { int pos = addChild(an, 0, an.getMessage()); } protected void visit(ExpressionStatement an) { int pos = addChild(an, an.getExpression(), depth, indent); pos = addChild(an, an.getLength() - 2, ";" + Constants.LINE_SEPARATOR); } protected void visit(NewExpression an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, "new "); pos = addChild(an, an.getTarget(), depth); pos = addChild(an, pos, "("); pos = addChildren(an, pos, an.getArguments(), depth); pos = addChild(an, pos, ")"); if (null != an.getInitializer()) { pos = addChild(an, pos, " "); pos = addChild(an, an.getInitializer(), depth); } } protected void visit(FunctionCall an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, an.getTarget(), depth); pos = addChild(an, pos, "("); pos = addChildren(an, pos, an.getArguments(), depth); pos = addChild(an, an.getLength() - 1, ")"); } protected void visit(IfStatement an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, "if ("); pos = addChild(an, an.getCondition(), depth); pos = addChild(an, pos, ")"); AstNode thenPart = an.getThenPart(); if (!(thenPart instanceof Block)) { pos = addChild(an, pos, " "); } pos = addChild(an, thenPart, depth, 0, true); AstNode elsePart = an.getElsePart(); if (elsePart instanceof IfStatement) { // TODO elseパートの扱い要確認 pos = addChild(an, pos, " else "); pos = addChild(an, elsePart, depth, 0, true); } else if (null != elsePart) { pos = addChild(an, pos, " else "); pos = addChild(an, elsePart, depth, 0, true); } pos = addChild(an, an.getLength() - 1, Constants.LINE_SEPARATOR); } protected void visit(Assignment an) { // InfixExpressionと同様 } protected void visit(ObjectProperty an) { int pos = addChild(an, 0, Util.makeIndent(indent)); if (an.isGetter()) { pos = addChild(an, pos, "get "); } else if (an.isSetter()) { pos = addChild(an, pos, "set "); } pos = addChild(an, an.getLeft(), depth); if (an.getType() == Token.COLON) { pos = addChild(an, pos, ": "); } pos = addChild(an, an.getRight(), depth); } protected void visit(PropertyGet an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, an.getLeft(), depth); pos = addChild(an, pos, "."); pos = addChild(an, an.getRight(), depth); } protected void visit(XmlDotQuery an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, an.getLeft(), depth); pos = addChild(an, pos, ".("); pos = addChild(an, an.getRight(), depth); pos = addChild(an, an.getLength() - 1, ")"); } protected void visit(XmlMemberGet an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, an.getLeft(), depth); pos = addChild(an, pos, AstNode.operatorToString(an.getType())); pos = addChild(an, an.getRight(), depth); } protected void visit(InfixExpression an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, an.getLeft(), depth); pos = addChild(an, pos, " "); pos = addChild(an, pos, AstNode.operatorToString(an.getType())); pos = addChild(an, pos, " "); pos = addChild(an, an.getRight(), depth); } protected void visit(BreakStatement an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, "break"); Name breakLabel = an.getBreakLabel(); if (null != breakLabel) { pos = addChild(an, pos, " "); pos = addChild(an, breakLabel, depth); } pos = addChild(an, an.getLength() - 2, ";" + Constants.LINE_SEPARATOR); } protected void visit(ContinueStatement an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, "continue"); Name label = an.getLabel(); if (null != label) { pos = addChild(an, pos, " "); pos = addChild(an, label, depth); } pos = addChild(an, an.getLength() - 2, ";" + Constants.LINE_SEPARATOR); } protected void visit(Label an) { int pos = addChild(an, 0, Util.makeIndent(depth)); pos = addChild(an, pos, an.getName()); pos = addChild(an, an.getLength() - 2, ":" + Constants.LINE_SEPARATOR); } protected void visit(ArrayComprehension an) { int pos = addChild(an, 0, "["); pos = addChild(an, an.getResult(), depth); for (ArrayComprehensionLoop loop : an.getLoops()) { pos = addChild(an, loop, depth); } if (null != an.getFilter()) { pos = addChild(an, pos, " if ("); pos = addChild(an, an.getFilter(), depth); pos = addChild(an, pos, ")"); } pos = addChild(an, an.getLength() - 1, "]"); } protected void visit(LetNode an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, "let ("); pos = addChild(an, an.getVariables(), depth); pos = addChild(an, pos, ")"); if (null != an.getBody()) { pos = addChild(an, an.getBody(), depth); } } protected void visit(DoLoop an) { int pos = addChild(an, 0, "do "); pos = addChild(an, an.getBody(), depth, 0, true); pos = addChild(an, pos, " while ("); pos = addChild(an, an.getCondition(), depth); pos = addChild(an, an.getLength() - 3, ");" + Constants.LINE_SEPARATOR); } protected void visit(ArrayComprehensionLoop an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, " for ("); pos = addChild(an, an.getIterator(), depth); pos = addChild(an, pos, " in "); pos = addChild(an, an.getIteratedObject(), depth); pos = addChild(an, an.getLength() - 1, ")"); } protected void visit(ForInLoop an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, "for "); if (an.isForEach()) { pos = addChild(an, pos, "each "); } pos = addChild(an, pos, "("); pos = addChild(an, an.getIterator(), depth); pos = addChild(an, pos, " in "); pos = addChild(an, an.getIteratedObject(), depth); pos = addChild(an, pos, ") "); if (an.getBody() instanceof Block) { pos = addChild(an, an.getBody(), depth, 0, true); pos = addChild(an, an.getLength() - 1, Constants.LINE_SEPARATOR); } else { pos = addChild(an, an.getBody(), depth);// TODO 調整中(depth + 1) } } protected void visit(ForLoop an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, "for ("); AstNode initializer = an.getInitializer(); initializer.putProp(Constants.IN_FOR_LOOP, true); pos = addChild(an, initializer, depth); pos = addChild(an, pos, "; "); pos = addChild(an, an.getCondition(), depth); pos = addChild(an, pos, "; "); pos = addChild(an, an.getIncrement(), depth); pos = addChild(an, pos, ") "); if (an.getBody() instanceof Block) { // TODO インデントが1つ多い? pos = addChild(an, an.getBody(), depth, 0, true); pos = addChild(an, an.getLength() - 1, Constants.LINE_SEPARATOR); } else { pos = addChild(an, an.getBody(), depth); // TODO 調整中(depth + 1) } } protected void visit(WhileLoop an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, "while ("); pos = addChild(an, an.getCondition(), depth); pos = addChild(an, pos, ") "); if (an.getBody() instanceof Block) { pos = addChild(an, an.getBody(), depth, 0, true); pos = addChild(an, an.getLength() - 1, Constants.LINE_SEPARATOR); } else { pos = addChild(an, pos, Constants.LINE_SEPARATOR); pos = addChild(an, pos, Util.makeIndent(depth)); pos = addChild(an, an.getBody(), depth + 1); } } protected void visit(AstRoot an) { // } protected void visit(FunctionNode an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, "function"); if (an.getFunctionName() != null) { pos = addChild(an, pos, " "); pos = addChild(an, an.getFunctionName(), depth); } if (an.getParams() == null) { pos = addChild(an, pos, "() "); } else { pos = addChild(an, pos, "("); pos = addChildren(an, pos, an.getParams(), depth); pos = addChild(an, pos, ") "); } if (an.isExpressionClosure()) { pos = addChild(an, pos, " "); pos = addChild(an, an.getBody(), depth); } else { pos = addChild(an, an.getBody(), depth, 0, true);// TODO インデント調整中 } if (an.getFunctionType() == FunctionNode.FUNCTION_STATEMENT) { pos = addChild(an, an.getLength() - 1, Constants.LINE_SEPARATOR); } } protected void visit(SwitchStatement an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, "switch ("); pos = addChild(an, an.getExpression(), depth); pos = addChild(an, pos, ") {" + Constants.LINE_SEPARATOR); int newDepth = depth + 1; for (SwitchCase sc : an.getCases()) { pos = addChild(an, sc, newDepth, newDepth); } String indent = Util.makeIndent(depth); if (null != indent) { pos = addChild(an, an.getLength() - 2 - indent.length(), indent); } pos = addChild(an, an.getLength() - 2, "}" + Constants.LINE_SEPARATOR); } protected void visit(ScriptNode an) { // } protected void visit(Scope an) { List<Node> chidlren = new ArrayList<Node>(); for (Node kid : an) { chidlren.add(kid); } an.removeChildren(); int pos = addChild(an, 0, Util.makeIndent(indent));// TODO pos = addChild(an, pos, "{" + Constants.LINE_SEPARATOR); int newDepth = depth + 1; for (Node child : chidlren) { pos = addChild(an, (AstNode) child, newDepth, newDepth); } String indent = Util.makeIndent(depth); if (null != indent) { pos = addChild(an, an.getLength() - 2 - indent.length(), indent); } pos = addChild(an, an.getLength() - 2, "}" + Constants.LINE_SEPARATOR); } protected void visit(Jump an) { // } protected void visit(KeywordLiteral an) { int pos = addChild(an, 0, Util.makeIndent(indent)); switch (an.getType()) { case Token.THIS: pos = addChild(an, pos, "this"); break; case Token.NULL: pos = addChild(an, pos, "null"); break; case Token.TRUE: pos = addChild(an, pos, "true"); break; case Token.FALSE: pos = addChild(an, pos, "false"); break; case Token.DEBUGGER: pos = addChild(an, pos, "debugger"); break; default: throw new IllegalStateException("Invalid keyword literal type: " + an.getType()); } } protected void visit(LabeledStatement an) { int pos = 0; for (Label label : an.getLabels()) { pos = addChild(an, label, depth); } pos = addChild(an, an.getStatement(), depth + 1); } protected void visit(Name an) { int pos = addChild(an, 0, Util.makeIndent(indent)); if (an.getIdentifier() == null) { pos = addChild(an, pos, "<null>"); } else { pos = addChild(an, pos, an.getIdentifier()); } } protected void visit(NumberLiteral an) { int pos = addChild(an, 0, Util.makeIndent(indent)); if (an.getValue() == null) { pos = addChild(an, pos, "<null>"); } else { pos = addChild(an, pos, an.getValue()); } } protected void visit(ObjectLiteral an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, "{"); if (an.getElements() != null) { pos = addChildren(an, pos, an.getElements(), depth, true); } pos = addChild(an, an.getLength() - 1, "}"); } protected void visit(ParenthesizedExpression an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, "("); pos = addChild(an, an.getExpression(), depth); pos = addChild(an, an.getLength() - 1, ")"); } protected void visit(RegExpLiteral an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, "/"); pos = addChild(an, pos, an.getValue()); pos = addChild(an, pos, "/"); if (an.getFlags() != null) { pos = addChild(an, pos, an.getFlags()); } } protected void visit(ReturnStatement an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, "return"); if (an.getReturnValue() != null) { // pos = addChild(an, pos, " "); pos = addChild(an, 6, " "); pos = addChild(an, an.getReturnValue(), depth); } pos = addChild(an, an.getLength() - 2, ";" + Constants.LINE_SEPARATOR); } protected void visit(StringLiteral an) { int pos = addChild(an, 0, Util.makeIndent(indent)); char quoteCharacter = an.getQuoteCharacter(); pos = addChild(an, pos, String.valueOf(quoteCharacter)); String value = an.getValue(); value = value.replaceAll("\\\\", "\\\\\\\\"); value = value.replaceAll("\\n", "\\\\n"); value = value.replaceAll("\\r", "\\\\r"); // value = value.replaceAll("\\\"", "\\\\\""); // value = value.replaceAll("\\\'", "\\\\\'"); // value = value.replaceAll("\\/", "\\\\/"); if ('\'' == quoteCharacter) { value = value.replaceAll("\\'", "\\\\'"); } else if ('"' == quoteCharacter) { value = value.replaceAll("\\\"", "\\\\\""); } pos = addChild(an, pos, value); pos = addChild(an, an.getLength() - 1, String.valueOf(quoteCharacter)); } protected void visit(SwitchCase an) { int pos = addChild(an, 0, Util.makeIndent(indent)); if (an.getExpression() == null) { pos = addChild(an, pos, "default:" + Constants.LINE_SEPARATOR); } else { pos = addChild(an, pos, "case "); pos = addChild(an, an.getExpression(), depth); pos = addChild(an, pos, ":" + Constants.LINE_SEPARATOR); } if (an.getStatements() != null) { int newDepth = depth + 1; for (AstNode s : an.getStatements()) { pos = addChild(an, s, newDepth, newDepth); } } } protected void visit(ThrowStatement an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, "throw"); pos = addChild(an, pos, " "); pos = addChild(an, an.getExpression(), depth); pos = addChild(an, an.getLength() - 2, ";" + Constants.LINE_SEPARATOR); } protected void visit(TryStatement an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, "try "); pos = addChild(an, an.getTryBlock(), depth, 0); for (CatchClause cc : an.getCatchClauses()) { pos = addChild(an, cc, depth, depth); } if (an.getFinallyBlock() != null) { pos = addChild(an, pos, " finally "); pos = addChild(an, an.getFinallyBlock(), depth); } } protected void visit(UnaryExpression an) { int pos = addChild(an, 0, Util.makeIndent(indent)); int type = an.getType(); String operator = AstNode.operatorToString(type); if (!an.isPostfix()) { pos = addChild(an, pos, operator); if (type == Token.TYPEOF || type == Token.DELPROP) { pos = addChild(an, pos, " "); } } pos = addChild(an, an.getOperand(), depth); if (an.isPostfix()) { pos = addChild(an, pos, operator); } } protected void visit(VariableDeclaration an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, Token.typeToName(an.getType()).toLowerCase()); pos = addChild(an, pos, " "); boolean lnFlag = true; Object flagObj = an.getProp(Constants.IN_FOR_LOOP); if ((null != flagObj) && (Boolean.valueOf(flagObj.toString()))) { lnFlag = false; } pos = addChildrenForVariables(an, pos, an.getVariables(), depth, lnFlag); if (!(an.getParent() instanceof Loop)) { pos = addChild(an, an.getLength() - 2, ";" + Constants.LINE_SEPARATOR); } } protected void visit(VariableInitializer an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, an.getTarget(), depth); if (null != an.getInitializer()) { pos = addChild(an, pos, " = "); pos = addChild(an, an.getInitializer(), depth); } } protected void visit(WithStatement an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, "with ("); pos = addChild(an, an.getExpression(), depth); pos = addChild(an, pos, ") "); pos = addChild(an, an.getStatement(), depth + 1); if (!(an.getStatement() instanceof Block)) { pos = addChild(an, an.getLength() - 2, ";" + Constants.LINE_SEPARATOR); } } protected void visit(XmlExpression an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, "{"); pos = addChild(an, an.getExpression(), depth); pos = addChild(an, an.getLength() - 1, "}"); } protected void visit(XmlString an) { int pos = addChild(an, 0, Util.makeIndent(indent)); pos = addChild(an, pos, an.getXml()); } protected void visit(XmlLiteral an) { int pos = 0; for (XmlFragment frag : an.getFragments()) { pos = addChild(an, frag, depth); } } protected void visit(XmlElemRef an) { int pos = addChild(an, 0, Util.makeIndent(indent)); if (an.isAttributeAccess()) { pos = addChild(an, pos, "@"); } if (an.getNamespace() != null) { pos = addChild(an, an.getNamespace(), depth); pos = addChild(an, pos, "::"); } pos = addChild(an, pos, "["); pos = addChild(an, an.getExpression(), depth); pos = addChild(an, an.getLength() - 1, "]"); } protected void visit(XmlPropRef an) { int pos = addChild(an, 0, Util.makeIndent(indent)); if (an.isAttributeAccess()) { pos = addChild(an, pos, "@"); } if (an.getNamespace() != null) { pos = addChild(an, an.getNamespace(), depth); pos = addChild(an, pos, "::"); } pos = addChild(an, an.getPropName(), depth); } protected void visit(Yield an) { int pos = addChild(an, 0, "yield"); if (an.getValue() != null) { pos = addChild(an, an.getValue(), depth); } } protected void visit(Word an) { // } }