All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.javascript.jscomp.AstAnalyzer Maven / Gradle / Ivy

/*
 * Copyright 2019 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;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.collect.ImmutableSet;
import com.google.javascript.rhino.Node;

/**
 * Logic for answering questions about portions of the AST.
 *
 * 

What kind of methods should go here? * *

Methods that answer questions about some portion of the AST and that may require global * information about the compilation, generally taking at least one {@link Node} as an argument. For * example: * *

    *
  • Does a node have side effects? *
  • Can we statically determine the value of a node? *
* *

What kind of logic should not go here? * *

Really simple logic that requires no global information, like finding the parameter list node * of a function, should be in {@link NodeUtil}. Logic that creates new Nodes or modifies the AST * should go in {@link AstFactory}. */ public class AstAnalyzer { /** * The set of builtin constructors that don't have side effects. * *

TODO(bradfordcsmith): If all of these are annotated {@code sideefectfree}, can we drop this * list? */ private static final ImmutableSet CONSTRUCTORS_WITHOUT_SIDE_EFFECTS = ImmutableSet.of("Array", "Date", "Error", "Object", "RegExp", "XMLHttpRequest"); private final AbstractCompiler compiler; AstAnalyzer(AbstractCompiler compiler) { this.compiler = checkNotNull(compiler); } /** * Returns true if the node may create new mutable state, or change existing state. * * @see XKCD Cartoon */ boolean mayEffectMutableState(Node n) { // TODO(bradfordcsmith): Move the implementation into this class when possible. return NodeUtil.mayEffectMutableState(n, compiler); } /** * Returns true if the node which may have side effects when executed. This version default to the * "safe" assumptions when the compiler object is not provided (RegExp have side-effects, etc). */ public boolean mayHaveSideEffects(Node n) { // TODO(b/131178806): Move implementation here when possible return NodeUtil.mayHaveSideEffects(n, compiler); } /** * Returns true if this function call may have side effects. * *

This method is guaranteed to return true all calls that have side-effects, but may also * return true for calls that have none. * * @param callNode - function call node */ boolean functionCallHasSideEffects(Node callNode) { return NodeUtil.functionCallHasSideEffects(callNode, compiler); } /** * Do calls to this constructor have side effects? * * @param newNode - constructor call node */ boolean constructorCallHasSideEffects(Node newNode) { checkArgument(newNode.isNew(), "Expected NEW node, got %s", newNode.getToken()); if (newNode.isNoSideEffectsCall()) { return false; } // allArgsUnescapedLocal() is actually confirming that all of the arguments are literals or // values created at the point they are passed in to the call and are not saved anywhere in the // calling scope. // TODO(bradfordcsmith): It would be good to rename allArgsUnescapedLocal() to something // that makes this clearer. if (newNode.isOnlyModifiesArgumentsCall() && NodeUtil.allArgsUnescapedLocal(newNode)) { return false; } Node nameNode = newNode.getFirstChild(); return !nameNode.isName() || !CONSTRUCTORS_WITHOUT_SIDE_EFFECTS.contains(nameNode.getString()); } /** * Returns true if the current node's type implies side effects. * *

This is a non-recursive version of the may have side effects check; used to check wherever * the current node's type is one of the reasons why a subtree has side effects. */ boolean nodeTypeMayHaveSideEffects(Node n) { return NodeUtil.nodeTypeMayHaveSideEffects(n, compiler); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy