com.google.javascript.jscomp.parsing.parser.codegeneration.ParseTreeTransformer.java Source code

Java tutorial

Introduction

Here is the source code for com.google.javascript.jscomp.parsing.parser.codegeneration.ParseTreeTransformer.java

Source

/*
 * Copyright 2011 The Closure Compiler Authors.
 *
 * 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.google.javascript.jscomp.parsing.parser.codegeneration;

import static com.google.javascript.jscomp.parsing.parser.codegeneration.ParseTreeFactory.*;

import com.google.common.collect.ImmutableList;
import com.google.javascript.jscomp.parsing.parser.trees.*;

/**
 * A base class for transforming parse trees.
 *
 * The ParseTreeTransformer walks every node and gives derived classes the opportunity
 * (but not the obligation) to transform every node in a tree. By default the ParseTreeTransformer
 * performs the identity transform.
 */
public class ParseTreeTransformer {

    public ParseTree transformAny(ParseTree tree) {
        if (tree == null) {
            return null;
        }

        switch (tree.type) {
        case ARGUMENT_LIST:
            return transform(tree.asArgumentList());
        case ARRAY_LITERAL_EXPRESSION:
            return transform(tree.asArrayLiteralExpression());
        case ARRAY_PATTERN:
            return transform(tree.asArrayPattern());
        case BINARY_OPERATOR:
            return transform(tree.asBinaryOperator());
        case BLOCK:
            return transform(tree.asBlock());
        case BREAK_STATEMENT:
            return transform(tree.asBreakStatement());
        case CALL_EXPRESSION:
            return transform(tree.asCallExpression());
        case CASE_CLAUSE:
            return transform(tree.asCaseClause());
        case CATCH:
            return transform(tree.asCatch());
        case CLASS_DECLARATION:
            return transform(tree.asClassDeclaration());
        case COMMA_EXPRESSION:
            return transform(tree.asCommaExpression());
        case CONDITIONAL_EXPRESSION:
            return transform(tree.asConditionalExpression());
        case CONTINUE_STATEMENT:
            return transform(tree.asContinueStatement());
        case DEBUGGER_STATEMENT:
            return transform(tree.asDebuggerStatement());
        case DEFAULT_CLAUSE:
            return transform(tree.asDefaultClause());
        case DEFAULT_PARAMETER:
            return transform(tree.asDefaultParameter());
        case DO_WHILE_STATEMENT:
            return transform(tree.asDoWhileStatement());
        case EMPTY_STATEMENT:
            return transform(tree.asEmptyStatement());
        case EXPORT_DECLARATION:
            return transform(tree.asExportDeclaration());
        case EXPRESSION_STATEMENT:
            return transform(tree.asExpressionStatement());
        case FINALLY:
            return transform(tree.asFinally());
        case FOR_OF_STATEMENT:
            return transform(tree.asForOfStatement());
        case FOR_IN_STATEMENT:
            return transform(tree.asForInStatement());
        case FOR_STATEMENT:
            return transform(tree.asForStatement());
        case FORMAL_PARAMETER_LIST:
            return transform(tree.asFormalParameterList());
        case FUNCTION_DECLARATION:
            return transform(tree.asFunctionDeclaration());
        case GET_ACCESSOR:
            return transform(tree.asGetAccessor());
        case IDENTIFIER_EXPRESSION:
            return transform(tree.asIdentifierExpression());
        case IF_STATEMENT:
            return transform(tree.asIfStatement());
        case IMPORT_DECLARATION:
            return transform(tree.asImportDeclaration());
        case IMPORT_SPECIFIER:
            return transform(tree.asImportSpecifier());
        case LABELLED_STATEMENT:
            return transform(tree.asLabelledStatement());
        case LITERAL_EXPRESSION:
            return transform(tree.asLiteralExpression());
        case MEMBER_EXPRESSION:
            return transform(tree.asMemberExpression());
        case MEMBER_LOOKUP_EXPRESSION:
            return transform(tree.asMemberLookupExpression());
        case MISSING_PRIMARY_EXPRESSION:
            return transform(tree.asMissingPrimaryExpression());
        case MODULE_IMPORT:
            return transform(tree.asModuleImport());
        case NEW_EXPRESSION:
            return transform(tree.asNewExpression());
        case NULL:
            return transform(tree.asNull());
        case OBJECT_LITERAL_EXPRESSION:
            return transform(tree.asObjectLiteralExpression());
        case OBJECT_PATTERN:
            return transform(tree.asObjectPattern());
        case OBJECT_PATTERN_FIELD:
            return transform(tree.asObjectPatternField());
        case PAREN_EXPRESSION:
            return transform(tree.asParenExpression());
        case POSTFIX_EXPRESSION:
            return transform(tree.asPostfixExpression());
        case PROGRAM:
            return transform(tree.asProgram());
        case PROPERTY_NAME_ASSIGNMENT:
            return transform(tree.asPropertyNameAssignment());
        case REST_PARAMETER:
            return transform(tree.asRestParameter());
        case RETURN_STATEMENT:
            return transform(tree.asReturnStatement());
        case SET_ACCESSOR:
            return transform(tree.asSetAccessor());
        case SPREAD_EXPRESSION:
            return transform(tree.asSpreadExpression());
        case SPREAD_PATTERN_ELEMENT:
            return transform(tree.asSpreadPatternElement());
        case SUPER_EXPRESSION:
            return transform(tree.asSuperExpression());
        case SWITCH_STATEMENT:
            return transform(tree.asSwitchStatement());
        case THIS_EXPRESSION:
            return transform(tree.asThisExpression());
        case THROW_STATEMENT:
            return transform(tree.asThrowStatement());
        case TRY_STATEMENT:
            return transform(tree.asTryStatement());
        case UNARY_EXPRESSION:
            return transform(tree.asUnaryExpression());
        case VARIABLE_DECLARATION:
            return transform(tree.asVariableDeclaration());
        case VARIABLE_DECLARATION_LIST:
            return transform(tree.asVariableDeclarationList());
        case VARIABLE_STATEMENT:
            return transform(tree.asVariableStatement());
        case WHILE_STATEMENT:
            return transform(tree.asWhileStatement());
        case WITH_STATEMENT:
            return transform(tree.asWithStatement());
        case YIELD_EXPRESSION:
            return transform(tree.asYieldStatement());
        default:
            throw new RuntimeException("Should never get here!");
        }
    }

    @SuppressWarnings("unchecked")
    protected <E extends ParseTree> ImmutableList<E> transformList(ImmutableList<E> list) {
        if (list == null || list.size() == 0) {
            return list;
        }

        ImmutableList.Builder<E> builder = null;

        for (int index = 0; index < list.size(); index++) {
            ParseTree element = list.get(index);
            ParseTree transformed = transformAny(element);

            if (builder != null || element != transformed) {
                if (builder == null) {
                    builder = ImmutableList.builder();
                    builder.addAll(list.subList(0, index));
                }
                builder.add((E) transformed);
            }
        }

        return builder != null ? builder.build() : list;
    }

    final protected ParseTree toSourceElement(ParseTree tree) {
        return tree.isSourceElement() ? tree : createExpressionStatement(tree);
    }

    final protected ImmutableList<ParseTree> transformSourceElements(ImmutableList<ParseTree> list) {
        if (list == null || list.size() == 0) {
            return list;
        }

        ImmutableList.Builder<ParseTree> builder = null;

        for (int index = 0; index < list.size(); index++) {
            ParseTree element = list.get(index);
            ParseTree transformed = toSourceElement(transformAny(element));

            if (builder != null || element != transformed) {
                if (builder == null) {
                    builder = ImmutableList.builder();
                    builder.addAll(list.subList(0, index));
                }
                builder.add(transformed);
            }
        }

        return builder != null ? builder.build() : list;
    }

    protected ParseTree transform(ArgumentListTree tree) {
        ImmutableList<ParseTree> arguments = transformList(tree.arguments);
        if (arguments == tree.arguments) {
            return tree;
        }
        return createArgumentList(arguments);
    }

    protected ParseTree transform(ArrayLiteralExpressionTree tree) {
        ImmutableList<ParseTree> elements = transformList(tree.elements);
        if (elements == tree.elements) {
            return tree;
        }
        return createArrayLiteralExpression(elements);
    }

    protected ParseTree transform(ArrayPatternTree tree) {
        ImmutableList<ParseTree> elements = transformList(tree.elements);
        if (elements == tree.elements) {
            return tree;
        }
        return createArrayPattern(elements);
    }

    protected ParseTree transform(BinaryOperatorTree tree) {
        ParseTree left = transformAny(tree.left);
        ParseTree right = transformAny(tree.right);
        if (left == tree.left && right == tree.right) {
            return tree;
        }
        return createBinaryOperator(left, tree.operator, right);
    }

    protected ParseTree transform(BlockTree tree) {
        ImmutableList<ParseTree> elements = transformList(tree.statements);
        if (elements == tree.statements) {
            return tree;
        }
        return createBlock(elements);
    }

    protected ParseTree transform(BreakStatementTree tree) {
        return tree;
    }

    protected ParseTree transform(CallExpressionTree tree) {
        ParseTree operand = transformAny(tree.operand);
        ArgumentListTree arguments = transformAny(tree.arguments).asArgumentList();
        if (operand == tree.operand && arguments == tree.arguments) {
            return tree;
        }
        return createCallExpression(operand, arguments);
    }

    protected ParseTree transform(CaseClauseTree tree) {
        ParseTree expression = transformAny(tree.expression);
        ImmutableList<ParseTree> statements = transformList(tree.statements);
        if (expression == tree.expression && statements == tree.statements) {
            return tree;
        }
        return createCaseClause(expression, statements);
    }

    protected ParseTree transform(CatchTree tree) {
        ParseTree catchBody = transformAny(tree.catchBody);
        if (catchBody == tree.catchBody) {
            return tree;
        }
        return createCatch(tree.exceptionName, catchBody);
    }

    protected ParseTree transform(ClassDeclarationTree tree) {
        ParseTree superClass = transformAny(tree.superClass);
        ImmutableList<ParseTree> elements = transformList(tree.elements);

        if (superClass == tree.superClass && elements == tree.elements) {
            return tree;
        }
        return createClassDeclaration(tree.name, superClass, elements);
    }

    protected ParseTree transform(CommaExpressionTree tree) {
        ImmutableList<ParseTree> expressions = transformList(tree.expressions);
        if (expressions == tree.expressions) {
            return tree;
        }
        return createCommaExpression(expressions);
    }

    protected ParseTree transform(ConditionalExpressionTree tree) {
        ParseTree condition = transformAny(tree.condition);
        ParseTree left = transformAny(tree.left);
        ParseTree right = transformAny(tree.right);
        if (condition == tree.condition && left == tree.left && right == tree.right) {
            return tree;
        }
        return createConditionalExpression(condition, left, right);
    }

    protected ParseTree transform(ContinueStatementTree tree) {
        return tree;
    }

    protected ParseTree transform(DebuggerStatementTree tree) {
        return tree;
    }

    protected ParseTree transform(DefaultClauseTree tree) {
        ImmutableList<ParseTree> statements = transformList(tree.statements);
        if (statements == tree.statements) {
            return tree;
        }
        return createDefaultClause(statements);
    }

    protected ParseTree transform(DefaultParameterTree tree) {
        ParseTree expression = transformAny(tree.expression);
        if (expression == tree.expression) {
            return tree;
        }
        return createDefaultParameter(tree.identifier, expression);
    }

    protected ParseTree transform(DoWhileStatementTree tree) {
        ParseTree body = transformAny(tree.body);
        ParseTree condition = transformAny(tree.condition);
        if (body == tree.body && condition == tree.condition) {
            return tree;
        }
        return createDoWhileStatement(body, condition);
    }

    protected ParseTree transform(EmptyStatementTree tree) {
        return tree;
    }

    protected ParseTree transform(ExportDeclarationTree tree) {
        ParseTree declaration = transformAny(tree.declaration);
        if (tree.declaration == declaration) {
            return tree;
        }
        return new ExportDeclarationTree(null, tree.isDefault, tree.isExportAll, declaration,
                tree.exportSpecifierList, tree.from);
    }

    protected ParseTree transform(ExpressionStatementTree tree) {
        ParseTree expression = transformAny(tree.expression);
        if (expression == tree.expression) {
            return tree;
        }
        return createExpressionStatement(expression);
    }

    protected ParseTree transform(FinallyTree tree) {
        ParseTree block = transformAny(tree.block);
        if (block == tree.block) {
            return tree;
        }
        return createFinally(block);
    }

    protected ParseTree transform(ForOfStatementTree tree) {
        ParseTree initializer = transformAny(tree.initializer);
        ParseTree collection = transformAny(tree.collection);
        ParseTree body = transformAny(tree.body);
        if (initializer == tree.initializer && collection == tree.collection && body == tree.body) {
            return tree;
        }
        return createForEachStatement(initializer.asVariableDeclarationList(), collection, body);
    }

    protected ParseTree transform(ForInStatementTree tree) {
        ParseTree initializer = transformAny(tree.initializer);
        ParseTree collection = transformAny(tree.collection);
        ParseTree body = transformAny(tree.body);
        if (initializer == tree.initializer && collection == tree.collection && body == tree.body) {
            return tree;
        }
        return createForInStatement(initializer, collection, body);
    }

    protected ParseTree transform(ForStatementTree tree) {
        ParseTree initializer = transformAny(tree.initializer);
        ParseTree condition = transformAny(tree.condition);
        ParseTree increment = transformAny(tree.increment);
        ParseTree body = transformAny(tree.body);
        if (initializer == tree.initializer && condition == tree.condition && increment == tree.increment
                && body == tree.body) {
            return tree;
        }
        return createForStatement(initializer, condition, increment, body);
    }

    protected ParseTree transform(FormalParameterListTree tree) {
        return tree;
    }

    protected ParseTree transform(FunctionDeclarationTree tree) {
        FormalParameterListTree parameters = transformAny(tree.formalParameterList).asFormalParameterList();
        BlockTree functionBody = transformAny(tree.functionBody).asBlock();
        if (parameters == tree.formalParameterList && functionBody == tree.functionBody) {
            return tree;
        }
        return createFunctionDeclaration(tree.name, parameters, functionBody);
    }

    protected ParseTree transform(GetAccessorTree tree) {
        BlockTree body = transformAny(tree.body).asBlock();
        if (body == tree.body) {
            return tree;
        }
        return createGetAccessor(tree.propertyName, tree.isStatic, body);
    }

    protected ParseTree transform(IdentifierExpressionTree tree) {
        return tree;
    }

    protected ParseTree transform(IfStatementTree tree) {
        ParseTree condition = transformAny(tree.condition);
        ParseTree ifClause = transformAny(tree.ifClause);
        ParseTree elseClause = transformAny(tree.elseClause);
        if (condition == tree.condition && ifClause == tree.ifClause && elseClause == tree.elseClause) {
            return tree;
        }
        return createIfStatement(condition, ifClause, elseClause);
    }

    protected ParseTree transform(ImportDeclarationTree tree) {
        ImmutableList<ParseTree> importSpecifierList = transformList(tree.importSpecifierList);
        if (importSpecifierList == tree.importSpecifierList) {
            return tree;
        }
        return new ImportDeclarationTree(null, tree.defaultBindingIndentifier, importSpecifierList,
                tree.moduleSpecifier);
    }

    protected ParseTree transform(ImportSpecifierTree tree) {
        return tree;
    }

    protected ParseTree transform(LabelledStatementTree tree) {
        ParseTree statement = transformAny(tree.statement);
        if (statement == tree.statement) {
            return tree;
        }
        return createLabelledStatement(tree.name, statement);
    }

    protected ParseTree transform(LiteralExpressionTree tree) {
        return tree;
    }

    protected ParseTree transform(MemberExpressionTree tree) {
        ParseTree operand = transformAny(tree.operand);
        if (operand == tree.operand) {
            return tree;
        }
        return createMemberExpression(operand, tree.memberName);
    }

    protected ParseTree transform(MemberLookupExpressionTree tree) {
        ParseTree operand = transformAny(tree.operand);
        ParseTree memberExpression = transformAny(tree.memberExpression);
        if (operand == tree.operand && memberExpression == tree.memberExpression) {
            return tree;
        }
        return createMemberLookupExpression(operand, memberExpression);
    }

    protected ParseTree transform(MissingPrimaryExpressionTree tree) {
        throw new RuntimeException("Should never transform trees that had errors during parse");
    }

    protected ParseTree transform(ModuleImportTree tree) {
        return new ModuleImportTree(null, tree.name, tree.from);
    }

    protected ParseTree transform(NewExpressionTree tree) {
        ParseTree operand = transformAny(tree.operand);
        ArgumentListTree arguments = (ArgumentListTree) transformAny(tree.arguments);

        if (operand == tree.operand && arguments == tree.arguments) {
            return tree;
        }
        return createNewExpression(operand, arguments);
    }

    protected ParseTree transform(NullTree tree) {
        return tree;
    }

    protected ParseTree transform(ObjectLiteralExpressionTree tree) {
        ImmutableList<ParseTree> propertyNameAndValues = transformList(tree.propertyNameAndValues);
        if (propertyNameAndValues == tree.propertyNameAndValues) {
            return tree;
        }
        return createObjectLiteralExpression(propertyNameAndValues);
    }

    protected ParseTree transform(ObjectPatternTree tree) {
        ImmutableList<ParseTree> fields = transformList(tree.fields);
        if (fields == tree.fields) {
            return tree;
        }
        return createObjectPattern(fields);
    }

    protected ParseTree transform(ObjectPatternFieldTree tree) {
        ParseTree element = transformAny(tree.element);
        if (element == tree.element) {
            return tree;
        }
        return createObjectPatternField(tree.identifier, element);
    }

    protected ParseTree transform(ParenExpressionTree tree) {
        ParseTree expression = transformAny(tree.expression);
        if (expression == tree.expression) {
            return tree;
        }
        return createParenExpression(expression);
    }

    protected ParseTree transform(PostfixExpressionTree tree) {
        ParseTree operand = transformAny(tree.operand);
        if (operand == tree.operand) {
            return tree;
        }
        return createPostfixExpression(operand, tree.operator);
    }

    protected ParseTree transform(ProgramTree tree) {
        ImmutableList<ParseTree> elements = transformList(tree.sourceElements);
        if (elements == tree.sourceElements) {
            return tree;
        }
        return new ProgramTree(null, elements, tree.sourceComments);
    }

    protected ParseTree transform(PropertyNameAssignmentTree tree) {
        ParseTree value = transformAny(tree.value);
        if (value == tree.value) {
            return tree;
        }
        return createPropertyNameAssignment(tree.name, value);
    }

    protected ParseTree transform(RestParameterTree tree) {
        return tree;
    }

    protected ParseTree transform(ReturnStatementTree tree) {
        ParseTree expression = transformAny(tree.expression);
        if (expression == tree.expression) {
            return tree;
        }
        return createReturnStatement(expression);
    }

    protected ParseTree transform(SetAccessorTree tree) {
        BlockTree body = transformAny(tree.body).asBlock();
        if (body == tree.body) {
            return tree;
        }
        return createSetAccessor(tree.propertyName, tree.isStatic, tree.parameter, body);
    }

    protected ParseTree transform(SpreadExpressionTree tree) {
        ParseTree expression = transformAny(tree.expression);
        if (expression == tree.expression) {
            return tree;
        }
        return createSpreadExpression(expression);
    }

    protected ParseTree transform(SpreadPatternElementTree tree) {
        ParseTree lvalue = transformAny(tree.lvalue);
        if (lvalue == tree.lvalue) {
            return tree;
        }
        return createSpreadPatternElement(lvalue);
    }

    protected ParseTree transform(SuperExpressionTree tree) {
        return tree;
    }

    protected ParseTree transform(SwitchStatementTree tree) {
        ParseTree expression = transformAny(tree.expression);
        ImmutableList<ParseTree> caseClauses = transformList(tree.caseClauses);
        if (expression == tree.expression && caseClauses == tree.caseClauses) {
            return tree;
        }
        return createSwitchStatement(expression, caseClauses);
    }

    protected ParseTree transform(ThisExpressionTree tree) {
        return tree;
    }

    protected ParseTree transform(ThrowStatementTree tree) {
        ParseTree value = transformAny(tree.value);
        if (value == tree.value) {
            return tree;
        }
        return createThrowStatement(value);
    }

    protected ParseTree transform(TryStatementTree tree) {
        ParseTree body = transformAny(tree.body);
        ParseTree catchBlock = transformAny(tree.catchBlock);
        ParseTree finallyBlock = transformAny(tree.finallyBlock);
        if (body == tree.body && catchBlock == tree.catchBlock && finallyBlock == tree.finallyBlock) {
            return tree;
        }
        return createTryStatement(body, catchBlock, finallyBlock);
    }

    protected ParseTree transform(UnaryExpressionTree tree) {
        ParseTree operand = transformAny(tree.operand);
        if (operand == tree.operand) {
            return tree;
        }
        return createUnaryExpression(tree.operator, operand);
    }

    protected ParseTree transform(VariableDeclarationTree tree) {
        ParseTree lvalue = transformAny(tree.lvalue);
        ParseTree initializer = transformAny(tree.initializer);
        if (lvalue == tree.lvalue && initializer == tree.initializer) {
            return tree;
        }
        return createVariableDeclaration(lvalue, initializer);
    }

    protected ParseTree transform(VariableDeclarationListTree tree) {
        ImmutableList<VariableDeclarationTree> declarations = transformList(tree.declarations);
        if (declarations == tree.declarations) {
            return tree;
        }
        return createVariableDeclarationList(tree.declarationType, declarations);
    }

    protected ParseTree transform(VariableStatementTree tree) {
        VariableDeclarationListTree declarations = transformAny(tree.declarations).asVariableDeclarationList();
        if (declarations == tree.declarations) {
            return tree;
        }
        return createVariableStatement(declarations);
    }

    protected ParseTree transform(WhileStatementTree tree) {
        ParseTree condition = transformAny(tree.condition);
        ParseTree body = transformAny(tree.body);
        if (condition == tree.condition && body == tree.body) {
            return tree;
        }
        return createWhileStatement(condition, body);
    }

    protected ParseTree transform(WithStatementTree tree) {
        ParseTree expression = transformAny(tree.expression);
        ParseTree body = transformAny(tree.body);
        if (expression == tree.expression && body == tree.body) {
            return tree;
        }
        return createWithStatement(expression, body);
    }

    protected ParseTree transform(YieldExpressionTree tree) {
        ParseTree expression = transformAny(tree.expression);
        if (expression == tree.expression) {
            return tree;
        }
        return createYieldStatement(expression);
    }
}