use of com.google.javascript.jscomp.GlobalNamespace.Name in project closure-compiler by google.
the class CheckGlobalNames method validateName.
private void validateName(Name name, boolean isDefined) {
// If the name is not defined, emit warnings for each reference. While
// we're looking through each reference, check all the module dependencies.
Ref declaration = name.getDeclaration();
Name parent = name.parent;
JSModuleGraph moduleGraph = compiler.getModuleGraph();
for (Ref ref : name.getRefs()) {
// Don't worry about global exprs.
boolean isGlobalExpr = ref.getNode().getParent().isExprResult();
if (!isDefined && !isTypedef(ref)) {
if (!isGlobalExpr) {
reportRefToUndefinedName(name, ref);
}
} else if (declaration != null && ref.getModule() != declaration.getModule() && !moduleGraph.dependsOn(ref.getModule(), declaration.getModule())) {
reportBadModuleReference(name, ref);
} else {
// Check for late references.
if (ref.scope.getClosestHoistScope().isGlobal()) {
// Prototype references are special, because in our reference graph,
// A.prototype counts as a reference to A.
boolean isPrototypeGet = (ref.type == Ref.Type.PROTOTYPE_GET);
Name owner = isPrototypeGet ? name : parent;
boolean singleGlobalParentDecl = owner != null && owner.getDeclaration() != null && owner.localSets == 0;
if (singleGlobalParentDecl && owner.getDeclaration().preOrderIndex > ref.preOrderIndex) {
String refName = isPrototypeGet ? name.getFullName() + ".prototype" : name.getFullName();
compiler.report(JSError.make(ref.node, NAME_DEFINED_LATE_WARNING, refName, owner.getFullName(), owner.getDeclaration().getSourceFile().getName(), String.valueOf(owner.getDeclaration().node.getLineno())));
}
}
}
}
}
use of com.google.javascript.jscomp.GlobalNamespace.Name in project closure-compiler by google.
the class CollapseProperties method flattenReferencesToCollapsibleDescendantNames.
/**
* Flattens all references to collapsible properties of a global name except
* their initial definitions. Recurs on subnames.
*
* @param n An object representing a global name
* @param alias The flattened name for {@code n}
*/
private void flattenReferencesToCollapsibleDescendantNames(Name n, String alias) {
if (n.props == null || n.isCollapsingExplicitlyDenied()) {
return;
}
for (Name p : n.props) {
String propAlias = appendPropForAlias(alias, p.getBaseName());
boolean isAllowedToCollapse = propertyCollapseLevel != PropertyCollapseLevel.MODULE_EXPORT || p.isModuleExport();
if (isAllowedToCollapse && p.canCollapse()) {
flattenReferencesTo(p, propAlias);
} else if (isAllowedToCollapse && p.isSimpleStubDeclaration() && !p.isCollapsingExplicitlyDenied()) {
flattenSimpleStubDeclaration(p, propAlias);
}
flattenReferencesToCollapsibleDescendantNames(p, propAlias);
}
}
use of com.google.javascript.jscomp.GlobalNamespace.Name in project closure-compiler by google.
the class Es6ConvertSuperConstructorCalls method isKnownToReturnOnlyUndefined.
private boolean isKnownToReturnOnlyUndefined(String functionQName) {
if (globalNamespace == null) {
return false;
}
Name globalName = globalNamespace.getSlot(functionQName);
if (globalName == null) {
return false;
}
Ref declarationRef = globalName.getDeclaration();
if (declarationRef == null) {
for (Ref ref : globalName.getRefs()) {
if (ref.isSet()) {
declarationRef = ref;
}
}
}
if (declarationRef == null) {
return false;
}
Node declaredVarOrProp = declarationRef.getNode();
if (declaredVarOrProp.isFromExterns()) {
return false;
}
Node declaration = declaredVarOrProp.getParent();
Node declaredValue = null;
if (declaration.isFunction()) {
declaredValue = declaration;
} else if (NodeUtil.isNameDeclaration(declaration) && declaredVarOrProp.isName()) {
if (declaredVarOrProp.hasChildren()) {
declaredValue = checkNotNull(declaredVarOrProp.getFirstChild());
} else {
// Declaration without an assigned value.
return false;
}
} else if (declaration.isAssign() && declaration.getFirstChild() == declaredVarOrProp) {
declaredValue = checkNotNull(declaration.getSecondChild());
} else if (declaration.isObjectLit() && declaredVarOrProp.hasOneChild()) {
declaredValue = checkNotNull(declaredVarOrProp.getFirstChild());
} else {
throw new IllegalStateException("Unexpected declaration format:\n" + declaration.toStringTree());
}
return isNodeKnownToOnlyReturnUndefined(declaredValue);
}
use of com.google.javascript.jscomp.GlobalNamespace.Name in project closure-compiler by google.
the class ProcessDefines method collectValidDefineValueExpressions.
private void collectValidDefineValueExpressions() {
LinkedHashSet<Name> namesToCheck = this.namespace.getAllSymbols().stream().filter(ProcessDefines::isGlobalConst).collect(toCollection(LinkedHashSet::new));
// All defines are implicitly valid in the values of other defines.
for (Define define : this.defineByDefineName.values()) {
namesToCheck.remove(define.name);
define.name.getRefs().stream().filter((r) -> !r.isSet()).map(Ref::getNode).forEachOrdered(this.validDefineValueExpressions::add);
}
// Do a breadth-first search of all const names to find those defined in terms of valid values.
while (true) {
LinkedHashSet<Name> namesToCheckAgain = new LinkedHashSet<>();
for (Name name : namesToCheck) {
Node declValue = getConstantDeclValue(name.getDeclaration().getNode());
switch(isValidDefineValue(declValue)) {
case TRUE:
for (Ref ref : name.getRefs()) {
this.validDefineValueExpressions.add(ref.getNode());
}
break;
case UNKNOWN:
namesToCheckAgain.add(name);
break;
default:
}
}
if (namesToCheckAgain.size() == namesToCheck.size()) {
break;
} else {
namesToCheck = namesToCheckAgain;
}
}
}
use of com.google.javascript.jscomp.GlobalNamespace.Name in project closure-compiler by google.
the class ProcessDefines method collectDefines.
/**
* Finds all defines, and creates a {@link Define} data structure for each one.
*/
private void collectDefines() {
for (Name name : this.namespace.getAllSymbols()) {
if (this.recognizeClosureDefines && name.getFullName().equals("CLOSURE_DEFINES")) {
collectClosureDefinesValues(name);
continue;
}
Ref declaration = this.selectDefineDeclaration(name);
if (declaration == null) {
continue;
}
int totalSets = name.getTotalSets();
Node valueParent = getValueParentForDefine(declaration);
Node value = valueParent != null ? valueParent.getLastChild() : null;
final String defineName;
if (this.isGoogDefineCall(value) && this.verifyGoogDefine(value)) {
Node nameNode = value.getSecondChild();
defineName = nameNode.getString();
} else {
defineName = name.getFullName();
}
Define existingDefine = this.defineByDefineName.putIfAbsent(defineName, new Define(defineName, name, declaration, valueParent, value));
if (existingDefine != null) {
declaration = existingDefine.declaration;
totalSets += existingDefine.name.getTotalSets();
}
/**
* We have to report this here because otherwise we don't remember which names have the same
* define name. It's not worth it tracking a set of names, because it makes the rest of the
* pass more complex.
*/
if (totalSets > 1) {
for (Ref ref : name.getRefs()) {
if (ref.isSet() && !ref.equals(declaration)) {
this.compiler.report(JSError.make(ref.getNode(), NON_CONST_DEFINE, defineName, declaration.getNode().getLocation()));
}
}
}
}
}
Aggregations