/** * Copyright 2004-2016 Riccardo Solmi. All rights reserved. * This file is part of the Whole Platform. * * The Whole Platform is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The Whole Platform is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>. */ package org.whole.lang.javascript.util; import java.io.InputStreamReader; import java.util.LinkedList; import java.util.List; import org.mozilla.javascript.CompilerEnvirons; import org.mozilla.javascript.Context; import org.mozilla.javascript.Node; import org.mozilla.javascript.Parser; import org.mozilla.javascript.Token; import org.mozilla.javascript.ast.*; import org.whole.lang.builders.IBuilderOperation; import org.whole.lang.builders.ModelBuilderOperation; import org.whole.lang.codebase.IPersistenceProvider; import org.whole.lang.commons.builders.ICommonsBuilder; import org.whole.lang.commons.reflect.CommonsLanguageKit; import org.whole.lang.javascript.builders.IJavaScriptBuilder; import org.whole.lang.javascript.model.AssignmentOperatorEnum; import org.whole.lang.javascript.model.CommentKindEnum; import org.whole.lang.javascript.model.InfixOperatorEnum; import org.whole.lang.javascript.model.PostfixOperatorEnum; import org.whole.lang.javascript.model.PrefixOperatorEnum; import org.whole.lang.javascript.model.VariableDeclarationKindEnum; import org.whole.lang.javascript.model.XmlMemberOperatorEnum; import org.whole.lang.javascript.reflect.JavaScriptLanguageKit; import org.whole.lang.model.IEntity; /** * @author Enrico Persiani */ public class RhinoTransformerVisitor implements NodeVisitor { protected IJavaScriptBuilder jb; protected ICommonsBuilder cb; protected IBuilderOperation op; protected LinkedList<Comment> comments = new LinkedList<Comment>(); public RhinoTransformerVisitor(IBuilderOperation op) { this.jb = (IJavaScriptBuilder) op.wGetBuilder(JavaScriptLanguageKit.URI); this.cb = (ICommonsBuilder) op.wGetBuilder(CommonsLanguageKit.URI); this.op = op; } public static IEntity transform(IPersistenceProvider pp) throws Exception { CompilerEnvirons compilerEnvirons = CompilerEnvirons.ideEnvirons(); compilerEnvirons.setLanguageVersion(Context.VERSION_1_8); Parser parser = new Parser(compilerEnvirons); AstRoot astRoot = parser.parse(new InputStreamReader(pp.getInputStream(), pp.getEncoding()), "http://whole.sourceforge.net/test.js", 0); ModelBuilderOperation mop = new ModelBuilderOperation(); RhinoTransformerVisitor visitor = new RhinoTransformerVisitor(mop); astRoot.visit(visitor); return mop.wGetResult(); } protected void safeVisit(AstNode node) { if (node != null) node.visit(this); else cb.Resolver(); } protected <T extends AstNode> void safeVisitChildren(AstNode astNode) { if (astNode != null) { for (Node element : astNode) safeVisit((AstNode) element); } } protected <T extends AstNode> void safeVisitChildren(Iterable<T> iterable) { if (iterable != null) { for (T element : iterable) safeVisit(element); } } protected <T extends Node> void safeVisitStatements(Iterable<T> iterable) { if (iterable != null) { for (Node element : iterable) { AstNode statement = (AstNode) element; int absolutePosition = statement.getAbsolutePosition(); while (!comments.isEmpty() && absolutePosition > comments.getFirst().getAbsolutePosition()) safeVisit(comments.removeFirst()); safeVisit(statement); } } } public boolean visit(AstNode node) { switch (node.getType()) { case Token.SCRIPT: return visitAstRoot((AstRoot) node); case Token.COMMENT: return visitComment((Comment) node); case Token.ARRAYLIT: return visitArrayLiteral((ArrayLiteral) node); case Token.ARRAYCOMP: return visitArrayComprehension((ArrayComprehension) node); case Token.ASSIGN: case Token.ASSIGN_BITOR: case Token.ASSIGN_BITXOR: case Token.ASSIGN_BITAND: case Token.ASSIGN_LSH: case Token.ASSIGN_RSH: case Token.ASSIGN_URSH: case Token.ASSIGN_ADD: case Token.ASSIGN_SUB: case Token.ASSIGN_MUL: case Token.ASSIGN_DIV: case Token.ASSIGN_MOD: return visitAssignment((Assignment) node); case Token.BLOCK: return visitBlock(node); case Token.BREAK: return visitBreakStatement((BreakStatement) node); case Token.CATCH: return visitCatchClause((CatchClause) node); case Token.HOOK: return visitConditionalExpression((ConditionalExpression) node); case Token.CONTINUE: return visitContinueStatement((ContinueStatement) node); case Token.DO: return visitDoLoop((DoLoop) node); case Token.GETELEM: return visitElementGet((ElementGet) node); case Token.EMPTY: return visitEmptyExpression((EmptyExpression) node); case Token.EXPR_VOID: return node instanceof LabeledStatement ? visitLabeledStatement((LabeledStatement) node) : visitExpressionStatement((ExpressionStatement) node); case Token.EXPR_RESULT: return visitExpressionStatement((ExpressionStatement) node); case Token.FOR: return node instanceof ForLoop ? visitForLoop((ForLoop) node) : node instanceof ArrayComprehensionLoop ? visitArrayComprehensionLoop((ArrayComprehensionLoop) node) : visitForInLoop((ForInLoop) node); case Token.CALL: return visitFunctionCall((FunctionCall) node); case Token.FUNCTION: return visitFunctionNode((FunctionNode) node); case Token.IF: return visitIfStatement((IfStatement) node); case Token.COMMA: return visitCommaInfixExpression((InfixExpression) node); case Token.ADD: case Token.SUB: case Token.AND: case Token.BITAND: case Token.BITOR: case Token.BITXOR: case Token.EQ: case Token.NE: case Token.SHEQ: case Token.SHNE: case Token.MUL: case Token.DIV: case Token.MOD: case Token.OR: case Token.IN: case Token.INSTANCEOF: case Token.LE: case Token.LT: case Token.GE: case Token.GT: case Token.LSH: case Token.URSH: case Token.RSH: return visitInfixExpression((InfixExpression) node); case Token.THIS: case Token.NULL: case Token.TRUE: case Token.FALSE: return visitKeywordLiteral((KeywordLiteral) node); case Token.LABEL: return visitLabel((Label) node); case Token.LET: return node instanceof LetNode ? visitLetNode((LetNode) node) : node instanceof VariableDeclaration ? visitVariableDeclaration((VariableDeclaration) node) : visitVariableInitializer((VariableInitializer) node); case Token.LETEXPR: return visitLetNode((LetNode) node); case Token.NAME: return visitName((Name) node); case Token.NEW: return visitNewExpression((NewExpression) node); case Token.NUMBER: return visitNumberLiteral((NumberLiteral) node); case Token.OBJECTLIT: return visitObjectLiteral((ObjectLiteral) node); case Token.COLON: case Token.GET: case Token.SET: return visitObjectProperty((ObjectProperty) node); case Token.LP: return visitParenthesizedExpression((ParenthesizedExpression) node); case Token.GETPROP: return visitPropertyGet((PropertyGet) node); case Token.REGEXP: return visitRegExpLiteral((RegExpLiteral) node); case Token.RETURN: return visitReturnStatement((ReturnStatement) node); case Token.STRING: return visitStringLiteral((StringLiteral) node); case Token.CASE: return visitSwitchCase((SwitchCase) node); case Token.SWITCH: return visitSwitchStatement((SwitchStatement) node); case Token.THROW: return visitThrowStatement((ThrowStatement) node); case Token.TRY: return visitTryStatement((TryStatement) node); case Token.DEFAULTNAMESPACE: return visitXmlDefaultNamespaceExpression((UnaryExpression) node); case Token.VOID: case Token.NOT: case Token.POS: case Token.NEG: case Token.BITNOT: case Token.TYPEOF: case Token.INC: case Token.DEC: case Token.DELPROP: return visitUnaryExpression((UnaryExpression) node); case Token.VAR: case Token.CONST: return node instanceof VariableDeclaration ? visitVariableDeclaration((VariableDeclaration) node) : visitVariableInitializer((VariableInitializer) node); case Token.WHILE: return visitWhileLoop((WhileLoop) node); case Token.WITH: return visitWithStatement((WithStatement) node); case Token.DOTQUERY: return visitXmlDotQuery((XmlDotQuery) node); case Token.REF_MEMBER: return visitXmlElemRef((XmlElemRef) node); case Token.XML: return node instanceof XmlExpression ? visitXmlExpression((XmlExpression) node) : node instanceof XmlString ? visitXmlString((XmlString) node) : visitXmlLiteral((XmlLiteral) node); case Token.DOT: case Token.DOTDOT: return visitXmlMemberGet((XmlMemberGet) node); case Token.REF_NAME: return visitXmlPropRef((XmlPropRef) node); case Token.YIELD: return visitYield((Yield) node); default: return false; } } protected boolean visitYield(Yield node) { jb.YieldExpression_(); safeVisit(node.getValue()); jb._YieldExpression(); return false; } protected boolean visitXmlPropRef(XmlPropRef node) { jb.StaticXmlRef_(); jb.BooleanData(node.isAttributeAccess()); safeVisit(node.getNamespace()); safeVisit(node.getPropName()); jb._StaticXmlRef(); return false; } protected boolean visitXmlMemberGet(XmlMemberGet node) { jb.XmlMemberGet_(); safeVisit(node.getLeft()); switch (node.getType()) { case Token.DOT: jb.XmlMemberOperator(XmlMemberOperatorEnum.dot); break; case Token.DOTDOT: jb.XmlMemberOperator(XmlMemberOperatorEnum.dotdot); break; default: throw new IllegalArgumentException("usupported type"); } safeVisit(node.getRight()); jb._XmlMemberGet(); return false; } private boolean visitXmlLiteral(XmlLiteral node) { jb.XmlLiteral_(); jb.XmlFragments_(); safeVisitChildren(node.getFragments()); jb._XmlFragments(); jb._XmlLiteral(); return false; } private boolean visitXmlString(XmlString node) { jb.XmlString_(); jb.StringData(node.getXml()); jb._XmlString(); return false; } protected boolean visitXmlExpression(XmlExpression node) { jb.XmlExpression_(); safeVisit(node.getExpression()); jb._XmlExpression(); return false; } protected boolean visitXmlElemRef(XmlElemRef node) { jb.ComputedXmlRef_(); jb.BooleanData(node.isAttributeAccess()); safeVisit(node.getNamespace()); safeVisit(node.getExpression()); jb._ComputedXmlRef(); return false; } protected boolean visitXmlDotQuery(XmlDotQuery node) { jb.XmlDotQuery_(); safeVisit(node.getLeft()); safeVisit(node.getRight()); jb._XmlDotQuery(); return false; } protected boolean visitWithStatement(WithStatement node) { jb.WithStatement_(); safeVisit(node.getExpression()); safeVisit(node.getStatement()); jb._WithStatement(); return false; } protected boolean visitWhileLoop(WhileLoop node) { jb.WhileStatement_(); safeVisit(node.getCondition()); safeVisit(node.getBody()); jb._WhileStatement(); return false; } protected boolean visitVariableInitializer(VariableInitializer node) { jb.VariableInitializer_(); safeVisit(node.getTarget()); safeVisit(node.getInitializer()); jb._VariableInitializer(); return false; } protected boolean visitVariableDeclaration(VariableDeclaration node) { jb.VariableDeclaration_(); switch (node.getType()) { case Token.VAR: jb.VariableDeclarationKind(VariableDeclarationKindEnum.var); break; case Token.LET: jb.VariableDeclarationKind(VariableDeclarationKindEnum.let); break; case Token.CONST: jb.VariableDeclarationKind(VariableDeclarationKindEnum._const); break; default: throw new IllegalArgumentException("usupported type"); } jb.VariableInitializers_(); safeVisitChildren(node.getVariables()); jb._VariableInitializers(); jb._VariableDeclaration(); return false; } protected boolean visitXmlDefaultNamespaceExpression(UnaryExpression node) { jb.XmlDefaultNamespace_(); safeVisit(node.getOperand()); jb._XmlDefaultNamespace(); return false; } protected boolean visitUnaryExpression(UnaryExpression node) { if (node.isPrefix()) { jb.PrefixExpression_(); switch (node.getType()) { case Token.INC: jb.PrefixOperator(PrefixOperatorEnum.increment); break; case Token.DEC: jb.PrefixOperator(PrefixOperatorEnum.decrement); break; case Token.POS: jb.PrefixOperator(PrefixOperatorEnum.plus); break; case Token.NEG: jb.PrefixOperator(PrefixOperatorEnum.minus); break; case Token.BITNOT: jb.PrefixOperator(PrefixOperatorEnum.complement); break; case Token.NOT: jb.PrefixOperator(PrefixOperatorEnum.not); break; case Token.TYPEOF: jb.PrefixOperator(PrefixOperatorEnum.typeof); break; case Token.VOID: jb.PrefixOperator(PrefixOperatorEnum._void); break; case Token.DELPROP: jb.PrefixOperator(PrefixOperatorEnum.delete); break; default: throw new IllegalArgumentException("usupported type"); } safeVisit(node.getOperand()); jb._PrefixExpression(); } else { jb.PostfixExpression_(); safeVisit(node.getOperand()); switch (node.getType()) { case Token.INC: jb.PostfixOperator(PostfixOperatorEnum.increment); break; case Token.DEC: jb.PostfixOperator(PostfixOperatorEnum.decrement); break; default: throw new IllegalArgumentException("usupported type"); } jb._PostfixExpression(); } return false; } protected boolean visitTryStatement(TryStatement node) { jb.TryStatement_(); safeVisit(node.getTryBlock()); List<CatchClause> catchClauses = node.getCatchClauses(); if (!catchClauses.isEmpty()) { jb.CatchClauses_(); safeVisitChildren(catchClauses); jb._CatchClauses(); } else cb.Resolver(); safeVisit(node.getFinallyBlock()); jb._TryStatement(); return false; } protected boolean visitThrowStatement(ThrowStatement node) { jb.ThrowStatement_(); safeVisit(node.getExpression()); jb._ThrowStatement(); return false; } protected boolean visitSwitchStatement(SwitchStatement node) { jb.SwitchStatement_(); safeVisit(node.getExpression()); jb.SwitchCases_(); safeVisitChildren(node.getCases()); jb._SwitchCases(); jb._SwitchStatement(); return false; } protected boolean visitSwitchCase(SwitchCase node) { jb.SwitchCase_(); safeVisit(node.getExpression()); jb.Statements_(); safeVisitStatements(node.getStatements()); jb._Statements(); jb._SwitchCase(); return false; } protected boolean visitStringLiteral(StringLiteral node) { jb.StringLiteral_(); jb.StringData(node.getValue()); jb.StringData(Character.toString(node.getQuoteCharacter())); jb._StringLiteral(); return false; } protected boolean visitReturnStatement(ReturnStatement node) { jb.ReturnStatement_(); safeVisit(node.getReturnValue()); jb._ReturnStatement(); return false; } protected boolean visitRegExpLiteral(RegExpLiteral node) { jb.RegExpLiteral_(); jb.StringData(node.getValue()); jb.StringData(node.getFlags()); jb._RegExpLiteral(); return false; } protected boolean visitPropertyGet(PropertyGet node) { jb.StaticMemberExpression_(); safeVisit(node.getLeft()); safeVisit(node.getRight()); jb._StaticMemberExpression(); return false; } protected boolean visitParenthesizedExpression(ParenthesizedExpression node) { jb.ParenthesizedExpression_(); safeVisit(node.getExpression()); jb._ParenthesizedExpression(); return false; } protected boolean visitObjectProperty(ObjectProperty node) { jb.ObjectProperty_(); safeVisit(node.getLeft()); safeVisit(node.getRight()); jb._ObjectProperty(); return false; } protected boolean visitObjectLiteral(ObjectLiteral node) { jb.ObjectLiteral_(); jb.BooleanData(node.isDestructuring()); jb.ObjectProperties_(); safeVisitChildren(node.getElements()); jb._ObjectProperties(); jb._ObjectLiteral(); return false; } protected boolean visitNumberLiteral(NumberLiteral node) { jb.NumberLiteral(node.getNumber()); return false; } protected boolean visitNewExpression(NewExpression node) { jb.NewExpression_(); safeVisit(node.getTarget()); List<AstNode> arguments = node.getArguments(); if (!arguments.isEmpty()) { jb.Expressions_(); safeVisitChildren(arguments); jb._Expressions(); } else cb.Resolver(); jb._NewExpression(); return false; } protected boolean visitName(Name node) { String identifier = node.getIdentifier(); if ("*".equals(identifier)) jb.XmlAny(); else jb.Identifier(identifier); return false; } protected void buildLetContents(LetNode node) { jb.VariableInitializers_(); safeVisitChildren(node.getVariables().getVariables()); jb._VariableInitializers(); safeVisit(node.getBody()); } protected boolean visitLetNode(LetNode node) { switch (node.getType()) { case Token.LETEXPR: jb.LetExpression_(); buildLetContents(node); jb._LetExpression(); break; case Token.LET: jb.LetStatement_(); buildLetContents(node); jb._LetStatement(); break; default: throw new IllegalArgumentException("usupported type"); } return false; } protected boolean visitLabeledStatement(LabeledStatement node) { jb.LabeledStatement_(); jb.Labels_(); safeVisitChildren(node.getLabels()); jb._Labels(); safeVisit(node.getStatement()); jb._LabeledStatement(); return false; } protected boolean visitLabel(Label node) { jb.Label_(); jb.Identifier(node.getName()); jb._Label(); return false; } protected boolean visitKeywordLiteral(KeywordLiteral node) { switch (node.getType()) { case Token.THIS: jb.ThisLiteral(); break; case Token.NULL: jb.NullLiteral(); break; case Token.TRUE: jb.BooleanLiteral(true); break; case Token.FALSE: jb.BooleanLiteral(false); break; default: throw new IllegalArgumentException("usupported type"); } return false; } protected boolean visitCommaInfixExpression(InfixExpression node) { boolean inComma = node.getParent().getType() == Token.COMMA; if (!inComma) jb.Expressions_(); safeVisit(node.getLeft()); safeVisit(node.getRight()); if (!inComma) jb._Expressions(); return false; } protected boolean visitInfixExpression(InfixExpression node) { jb.InfixExpression_(); safeVisit(node.getLeft()); switch (node.getType()) { case Token.ADD: jb.InfixOperator(InfixOperatorEnum.plus); break; case Token.SUB: jb.InfixOperator(InfixOperatorEnum.minus); break; case Token.AND: jb.InfixOperator(InfixOperatorEnum.conditional_and); break; case Token.OR: jb.InfixOperator(InfixOperatorEnum.conditional_or); break; case Token.BITAND: jb.InfixOperator(InfixOperatorEnum.and); break; case Token.BITOR: jb.InfixOperator(InfixOperatorEnum.or); break; case Token.BITXOR: jb.InfixOperator(InfixOperatorEnum.xor); break; case Token.EQ: jb.InfixOperator(InfixOperatorEnum.equals); break; case Token.NE: jb.InfixOperator(InfixOperatorEnum.not_equals); break; case Token.SHEQ: jb.InfixOperator(InfixOperatorEnum.shallow_equals); break; case Token.SHNE: jb.InfixOperator(InfixOperatorEnum.shallow_not_equals); break; case Token.MUL: jb.InfixOperator(InfixOperatorEnum.times); break; case Token.DIV: jb.InfixOperator(InfixOperatorEnum.divide); break; case Token.MOD: jb.InfixOperator(InfixOperatorEnum.remainder); break; case Token.IN: jb.InfixOperator(InfixOperatorEnum.in); break; case Token.INSTANCEOF: jb.InfixOperator(InfixOperatorEnum._instanceof); break; case Token.LE: jb.InfixOperator(InfixOperatorEnum.less_equals); break; case Token.LT: jb.InfixOperator(InfixOperatorEnum.less); break; case Token.GE: jb.InfixOperator(InfixOperatorEnum.greater_equals); break; case Token.GT: jb.InfixOperator(InfixOperatorEnum.greater); break; case Token.LSH: jb.InfixOperator(InfixOperatorEnum.left_shift); break; case Token.URSH: jb.InfixOperator(InfixOperatorEnum.right_shift_unsigned); break; case Token.RSH: jb.InfixOperator(InfixOperatorEnum.right_shift_signed); break; default: throw new IllegalArgumentException("usupported type"); } safeVisit(node.getRight()); jb._InfixExpression(); return false; } protected boolean visitIfStatement(IfStatement node) { jb.IfStatement_(); safeVisit(node.getCondition()); safeVisit(node.getThenPart()); safeVisit(node.getElsePart()); jb._IfStatement(); return false; } protected boolean visitFunctionCall(FunctionCall node) { jb.CallExpression_(); safeVisit(node.getTarget()); List<AstNode> arguments = node.getArguments(); if (!arguments.isEmpty()) { jb.Expressions_(); safeVisitChildren(arguments); jb._Expressions(); } else cb.Resolver(); jb._CallExpression(); return false; } protected boolean visitFunctionNode(FunctionNode node) { boolean isTopLevel = node.getFunctionType() == FunctionNode.FUNCTION_STATEMENT; if (isTopLevel) jb.FunctionDeclaration_(); else jb.FunctionExpression_(); safeVisit(node.getFunctionName()); List<AstNode> params = node.getParams(); if (!params.isEmpty()) { jb.Expressions_(); safeVisitChildren(params); jb._Expressions(); } else cb.Resolver(); safeVisit(node.getBody()); if (isTopLevel) jb._FunctionDeclaration(); else jb._FunctionExpression(); return false; } protected boolean visitForInLoop(ForInLoop node) { boolean isForEach = node.isForEach(); if (isForEach) jb.ForEachStatement_(); else jb.ForInStatement_(); safeVisit(node.getIterator()); safeVisit(node.getIteratedObject()); safeVisit(node.getBody()); if (isForEach) jb._ForEachStatement(); else jb._ForInStatement(); return false; } protected boolean visitForLoop(ForLoop node) { jb.ForStatement_(); safeVisit(node.getInitializer()); safeVisit(node.getCondition()); safeVisit(node.getIncrement()); safeVisit(node.getBody()); jb._ForStatement(); return false; } protected boolean visitExpressionStatement(ExpressionStatement node) { jb.ExpressionStatement_(); safeVisit(node.getExpression()); jb._ExpressionStatement(); return false; } protected boolean visitEmptyExpression(EmptyExpression node) { int parentType = node.getParent().getType(); boolean isTopLevel = parentType == Token.SCRIPT || parentType == Token.BLOCK; if (isTopLevel) jb.ExpressionStatement_(); jb.EmptyExpression(); if (isTopLevel) jb._ExpressionStatement(); return false; } protected boolean visitElementGet(ElementGet node) { jb.ComputedMemberExpression_(); safeVisit(node.getTarget()); safeVisit(node.getElement()); jb._ComputedMemberExpression(); return false; } protected boolean visitDoLoop(DoLoop node) { jb.DoWhileStatement_(); safeVisit(node.getBody()); safeVisit(node.getCondition()); jb._DoWhileStatement(); return false; } protected boolean visitContinueStatement(ContinueStatement node) { jb.ContinueStatement_(); safeVisit(node.getLabel()); jb._ContinueStatement(); return false; } protected boolean visitConditionalExpression(ConditionalExpression node) { jb.ConditionalExpression_(); safeVisit(node.getTestExpression()); safeVisit(node.getTrueExpression()); safeVisit(node.getFalseExpression()); jb._ConditionalExpression(); return false; } protected boolean visitCatchClause(CatchClause node) { jb.CatchClause_(); safeVisit(node.getVarName()); safeVisit(node.getCatchCondition()); safeVisit(node.getBody()); jb._CatchClause(); return false; } protected boolean visitBreakStatement(BreakStatement node) { jb.BreakStatement_(); safeVisit(node.getBreakLabel()); jb._BreakStatement(); return false; } // node can be either a Scope or a Block protected boolean visitBlock(AstNode node) { jb.Statements_(); safeVisitStatements(node); jb._Statements(); return false; } protected boolean visitAssignment(Assignment node) { jb.AssignmentExpression_(); safeVisit(node.getLeft()); switch (node.getType()) { case Token.ASSIGN: jb.AssignmentOperator(AssignmentOperatorEnum.assign); break; case Token.ASSIGN_BITOR: jb.AssignmentOperator(AssignmentOperatorEnum.bit_or_assign); break; case Token.ASSIGN_BITXOR: jb.AssignmentOperator(AssignmentOperatorEnum.bit_xor_assign); break; case Token.ASSIGN_BITAND: jb.AssignmentOperator(AssignmentOperatorEnum.bit_and_assign); break; case Token.ASSIGN_LSH: jb.AssignmentOperator(AssignmentOperatorEnum.left_shift_assign); break; case Token.ASSIGN_RSH: jb.AssignmentOperator(AssignmentOperatorEnum.right_shift_signed_assign); break; case Token.ASSIGN_URSH: jb.AssignmentOperator(AssignmentOperatorEnum.right_shift_unsigned_assign); break; case Token.ASSIGN_ADD: jb.AssignmentOperator(AssignmentOperatorEnum.plus_assign); break; case Token.ASSIGN_SUB: jb.AssignmentOperator(AssignmentOperatorEnum.minus_assign); break; case Token.ASSIGN_MUL: jb.AssignmentOperator(AssignmentOperatorEnum.times_assign); break; case Token.ASSIGN_DIV: jb.AssignmentOperator(AssignmentOperatorEnum.divide_assign); break; case Token.ASSIGN_MOD: jb.AssignmentOperator(AssignmentOperatorEnum.remainder_assign); break; default: throw new IllegalArgumentException("usupported type"); } safeVisit(node.getRight()); jb._AssignmentExpression(); return false; } protected boolean visitArrayLiteral(ArrayLiteral node) { jb.ArrayLiteral_(); jb.BooleanData(node.isDestructuring()); jb.Expressions_(); safeVisitChildren(node.getElements()); jb._Expressions(); jb._ArrayLiteral(); return false; } protected boolean visitAstRoot(AstRoot node) { if (node.getComments() != null) this.comments = new LinkedList<Comment>(node.getComments()); jb.Program_(); jb.Statements_(); safeVisitStatements(node); jb._Statements(); jb._Program(); return false; } protected boolean visitComment(Comment node) { String value = node.getValue(); jb.Comment_(); switch (node.getCommentType()) { case LINE: value = value.replaceAll("^//", ""); jb.CommentKind(CommentKindEnum.line); break; case BLOCK_COMMENT: value = value.replaceAll("(^/\\*)|(\\*/$)", ""); jb.CommentKind(CommentKindEnum.block); break; case JSDOC: value = value.replaceAll("(^/\\*\\*)|(\\*/$)", ""); jb.CommentKind(CommentKindEnum.jsdoc); break; case HTML: value = value.replaceAll("(^<!--)|(-->$)", ""); jb.CommentKind(CommentKindEnum.html); break; default: throw new IllegalArgumentException("usupported type"); } jb.StringData(value); jb._Comment(); return false; } protected boolean visitArrayComprehensionLoop(ArrayComprehensionLoop node) { boolean isForEach = node.isForEach(); if (isForEach) jb.ForEachComprehensionBlock_(); else jb.ForInComprehensionBlock_(); safeVisit(node.getIterator()); safeVisit(node.getIteratedObject()); if (isForEach) jb._ForEachComprehensionBlock(); else jb._ForInComprehensionBlock(); return false; } protected boolean visitArrayComprehension(ArrayComprehension node) { jb.ArrayComprehensionExpression_(); safeVisit(node.getResult()); jb.ComprehensionBlocks_(); safeVisitChildren(node.getLoops()); jb._ComprehensionBlocks(); safeVisit(node.getFilter()); jb._ArrayComprehensionExpression(); return false; } }