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

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

Go to download

Closure Compiler is a JavaScript optimizing compiler. It parses your JavaScript, analyzes it, removes dead code and rewrites and minimizes what's left. It also checks syntax, variable references, and types, and warns about common JavaScript pitfalls. It is used in many of Google's JavaScript apps, including Gmail, Google Web Search, Google Maps, and Google Docs. This binary checks for style issues such as incorrect or missing JSDoc usage, and missing goog.require() statements. It does not do more advanced checks such as typechecking.

There is a newer version: v20200830
Show newest version
/*
 * Copyright 2010 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 com.google.common.base.Preconditions;
import com.google.javascript.jscomp.ReferenceCollectingCallback.ReferenceCollection;
import com.google.javascript.rhino.Node;

import java.util.HashMap;
import java.util.Map;

/**
 * An analysis pass that determines the visibility of variables -- that is,
 * whether a variable is truly local, a local captured by an inner scope, a
 * parameter, or a global variable.
 *
 * SideEffectsAnalysis uses this class to partition a potentially infinite
 * number of concrete storage locations into a (small) finite number of
 * abstract storage locations based on a variable's storage visibility.
 *
 * @author [email protected] (Devin Coughlin)
 */
class VariableVisibilityAnalysis implements CompilerPass {

  enum VariableVisibility {

    /** Local variable, not captured by closure */
    LOCAL,

    /** Local variable captured by a closure */
    CAPTURED_LOCAL,

    /**
     * Formal parameter declaration variable
     *
     * Parameters are different than local variables because they can be
     * aliased by elements of the arguments object.
     */
    PARAMETER,

    /** A global variable */
    GLOBAL
  }

  private AbstractCompiler compiler;

  /**
   * Maps the declaring name node for a variable to that variable's
   * visibility.
   */
  private Map visibilityByDeclaringNameNode;

  public VariableVisibilityAnalysis(AbstractCompiler compiler) {
    this.compiler = compiler;

    visibilityByDeclaringNameNode = new HashMap<>();
  }

  /**
   * Returns the visibility of of a variable, given that variable's declaring
   * name node.
   *
   * The name node's parent must be one of:
   * 
   *    Token.VAR (for a variable declaration)
   *    Token.FUNCTION (for a function declaration)
   *    Token.PARAM_LIST (for a function formal parameter)
   * 
* * The returned visibility will be one of: *
   *    LOCAL_VARIABLE : the variable is a local variable used only in its
   *        declared scope
   *    CAPTURED_LOCAL_VARIABLE : A local variable that is used in a capturing
   *        closure
   *     PARAMETER_VARIABLE : the variable is a formal parameter
   *     GLOBAL_VARIABLE : the variable is declared in the global scope
   *  
* * @param declaringNameNode The name node for a declaration. */ public VariableVisibility getVariableVisibility(Node declaringNameNode) { Node parent = declaringNameNode.getParent(); Preconditions.checkArgument(parent.isVar() || parent.isFunction() || parent.isParamList()); return visibilityByDeclaringNameNode.get(declaringNameNode); } /** * Determines the visibility class for each variable in root. */ @Override public void process(Node externs, Node root) { ReferenceCollectingCallback callback = new ReferenceCollectingCallback(compiler, ReferenceCollectingCallback.DO_NOTHING_BEHAVIOR, new Es6SyntacticScopeCreator(compiler)); callback.process(root); for (Var variable : callback.getAllSymbols()) { ReferenceCollection referenceCollection = callback.getReferences(variable); VariableVisibility visibility; if (variableIsParameter(variable)) { visibility = VariableVisibility.PARAMETER; } else if (variable.isLocal()) { if (referenceCollection.isEscaped()) { visibility = VariableVisibility.CAPTURED_LOCAL; } else { visibility = VariableVisibility.LOCAL; } } else if (variable.isGlobal()) { visibility = VariableVisibility.GLOBAL; } else { throw new IllegalStateException("Un-handled variable visibility for " + variable); } visibilityByDeclaringNameNode.put(variable.getNameNode(), visibility); } } /** * Returns true if the variable is a formal parameter. */ private static boolean variableIsParameter(Var variable) { Node variableParent = variable.getParentNode(); return variableParent != null && variableParent.isParamList(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy