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

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

There is a newer version: 9.0.8
Show newest version
/*
 * Copyright 2014 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.javascript.rhino.JSDocInfo;
import com.google.javascript.rhino.Node;

/**
 * Attaches the CONST_VAR annotation to any variable that's
 * 1) Provably well-defined and assigned once in its lifetime.
 * 2) Annotated 'const'
 * 3) Declared with the 'const' keyword.
 * 4) Is constant by naming convention.
 *
 * These 3 are considered semantically equivalent. Notice that a variable
 * in a loop is never considered const.
 *
 * Note that criteria (1) is only used for normal code, not externs.
 *
 * @author [email protected] (Nick Santos)
 */
class InferConsts implements CompilerPass {
  private final AbstractCompiler compiler;

  InferConsts(AbstractCompiler compiler) {
    this.compiler = compiler;
  }

  @Override
  public void process(Node externs, Node js) {
    ReferenceCollectingCallback collector =
        new ReferenceCollectingCallback(
            compiler,
            ReferenceCollectingCallback.DO_NOTHING_BEHAVIOR,
            new Es6SyntacticScopeCreator(compiler));
    collector.process(js);

    for (Var v : collector.getAllSymbols()) {
      considerVar(v, collector.getReferences(v));
    }

    Scope globalExternsScope =
        new Es6SyntacticScopeCreator(compiler).createScope(externs, null);
    for (Var v : globalExternsScope.getAllSymbols()) {
      considerVar(v, null);
    }
  }

  private void considerVar(Var v, ReferenceCollection refCollection) {
    Node nameNode = v.getNameNode();
    JSDocInfo docInfo = v.getJSDocInfo();
    if (docInfo != null && docInfo.isConstant()) {
      nameNode.putBooleanProp(Node.IS_CONSTANT_VAR, true);
    } else if (nameNode != null && nameNode.getParent().isConst()) {
      nameNode.putBooleanProp(Node.IS_CONSTANT_VAR, true);
    } else if (nameNode != null
        && compiler.getCodingConvention().isConstant(nameNode.getString())) {
      nameNode.putBooleanProp(Node.IS_CONSTANT_VAR, true);
    } else if (nameNode != null
        && refCollection != null
        && refCollection.isWellDefined()
        && refCollection.isAssignedOnceInLifetime()
        && refCollection.firstReferenceIsAssigningDeclaration()) {
      nameNode.putBooleanProp(Node.IS_CONSTANT_VAR, true);
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy