com.google.javascript.jscomp.InferConsts Maven / Gradle / Ivy
/*
* 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);
}
}
}