use of com.google.javascript.rhino.StaticSlot in project closure-compiler by google.
the class AstFactory method getVarDefinitionNode.
private Node getVarDefinitionNode(StaticScope scope, String name) {
StaticSlot var = checkNotNull(scope.getSlot(name), "Missing var %s in scope %s", name, scope);
StaticRef declaration = checkNotNull(var.getDeclaration(), "Cannot find type for var with missing declaration %s", var);
return checkNotNull(declaration.getNode(), "Missing node for declaration %s", declaration);
}
use of com.google.javascript.rhino.StaticSlot in project closure-compiler by google.
the class NamedType method localVariableShadowsGlobalNamespace.
/**
* Check for an obscure but very confusing error condition where a local variable shadows a
* global namespace.
*/
private boolean localVariableShadowsGlobalNamespace(String root) {
StaticSlot rootVar = resolutionScope.getSlot(root);
if (rootVar != null) {
checkNotNull(rootVar.getScope(), rootVar);
StaticScope parent = rootVar.getScope().getParentScope();
if (parent != null) {
StaticSlot globalVar = parent.getSlot(root);
return globalVar != null;
}
}
return false;
}
use of com.google.javascript.rhino.StaticSlot in project closure-compiler by google.
the class SymbolTable method createPropertyScopeFor.
/**
* Build a property scope for the given symbol. Any properties of the symbol will be added to the
* property scope.
*
* <p>It is important that property scopes are created in order from the leaves up to the root, so
* this should only be called from #fillPropertyScopes. If you try to create a property scope for
* a parent before its leaf, then the leaf will get cut and re-added to the parent property scope,
* and weird things will happen.
*/
// This function uses == to compare types to be exact same instances.
private void createPropertyScopeFor(Symbol s) {
// for a previous symbol.
if (s.propertyScope != null) {
return;
}
ObjectType type = getType(s) == null ? null : getType(s).toObjectType();
if (type == null) {
return;
}
// reuse ModuleScope corresponding to 'some.foo' module.
if (s.getName().equals("exports") && s.getDeclarationNode().isModuleBody()) {
s.propertyScope = scopes.get(s.getDeclarationNode());
return;
}
// Create an empty property scope for the given symbol, maybe with a parent scope if it has
// an implicit prototype.
SymbolScope parentPropertyScope = maybeGetParentPropertyScope(type);
s.setPropertyScope(new SymbolScope(null, parentPropertyScope, type, s));
// If this symbol represents some 'a.b.c.prototype', add any instance properties of a.b.c
// into the symbol scope.
ObjectType instanceType = type;
Iterable<String> propNames = type.getOwnPropertyNames();
if (instanceType.isFunctionPrototypeType()) {
// Guard against modifying foo.prototype when foo is a regular (non-constructor) function.
if (instanceType.getOwnerFunction().hasInstanceType()) {
// Merge the properties of "Foo.prototype" and "new Foo()" together.
instanceType = instanceType.getOwnerFunction().getInstanceType();
propNames = Iterables.concat(propNames, instanceType.getOwnPropertyNames());
}
}
// Add all declared properties in propNames into the property scope
for (String propName : propNames) {
StaticSlot newProp = instanceType.getSlot(propName);
if (newProp.getDeclaration() == null) {
// them, because we index things by node.
continue;
}
// We have symbol tables that do not do type analysis. They just try
// to build a complete index of all objects in the program. So we might
// already have symbols for things like "Foo.bar". If this happens,
// throw out the old symbol and use the type-based symbol.
Symbol oldProp = symbols.get(newProp.getDeclaration().getNode(), s.getName() + "." + propName);
if (oldProp != null && compiler.getModuleMap().getClosureModule(oldProp.getName()) != null) {
// instead keeping 'a.b.c.Foo' in global namespace.
continue;
}
// at the same node. We bail out here to be safe.
if (symbols.get(newProp.getDeclaration().getNode(), newProp.getName()) != null) {
if (logger.isLoggable(Level.FINE)) {
logger.fine("Found duplicate symbol " + newProp);
}
continue;
}
Symbol newSym = copySymbolTo(newProp, s.propertyScope);
if (oldProp != null) {
if (newSym.getJSDocInfo() == null) {
newSym.setJSDocInfo(oldProp.getJSDocInfo());
}
newSym.setPropertyScope(oldProp.propertyScope);
for (Reference ref : oldProp.references.values()) {
newSym.defineReferenceAt(ref.getNode());
}
// All references/scopes from oldProp were updated to use the newProp. Time to remove
// oldProp.
removeSymbol(oldProp);
}
}
}
use of com.google.javascript.rhino.StaticSlot in project closure-compiler by google.
the class JSTypeRegistry method createTypeFromCommentNode.
/**
* Creates a JSType from the nodes representing a type.
*
* @param n The node with type info.
* @param sourceName The source file name.
* @param scope A scope for doing type name lookups.
*/
public JSType createTypeFromCommentNode(Node n, String sourceName, StaticTypedScope scope) {
switch(n.getToken()) {
case // Record type.
LC:
return createRecordTypeFromNodes(n.getFirstChild(), sourceName, scope);
case // Not nullable
BANG:
{
JSType child = createTypeFromCommentNode(n.getFirstChild(), sourceName, scope);
if (child instanceof NamedType) {
return ((NamedType) child).getBangType();
}
return child.restrictByNotNullOrUndefined();
}
case // Nullable or unknown
QMARK:
Node firstChild = n.getFirstChild();
if (firstChild == null) {
return getNativeType(UNKNOWN_TYPE);
}
return createNullableType(createTypeFromCommentNode(firstChild, sourceName, scope));
case // Optional
EQUALS:
// TODO(b/117162687): stop automatically converting {string=} to {(string|undefined)]}
return createOptionalType(createTypeFromCommentNode(n.getFirstChild(), sourceName, scope));
case // Var args
ITER_REST:
return createTypeFromCommentNode(n.getFirstChild(), sourceName, scope);
case // The AllType
STAR:
return getNativeType(ALL_TYPE);
case // Union type
PIPE:
ImmutableList.Builder<JSType> builder = ImmutableList.builder();
for (Node child = n.getFirstChild(); child != null; child = child.getNext()) {
builder.add(createTypeFromCommentNode(child, sourceName, scope));
}
return createUnionType(builder.build());
case // When the return value of a function is not specified
EMPTY:
return getNativeType(UNKNOWN_TYPE);
case // Only allowed in the return value of a function.
VOID:
return getNativeType(VOID_TYPE);
case TYPEOF:
{
String name = n.getFirstChild().getString();
// TODO(sdh): require var to be const?
QualifiedName qname = QualifiedName.of(name);
String root = qname.getRoot();
StaticScope declarationScope = scope.getTopmostScopeOfEventualDeclaration(root);
StaticSlot rootSlot = scope.getSlot(root);
JSType type = scope.lookupQualifiedName(qname);
if (type == null || type.isUnknownType() || rootSlot.getScope() != declarationScope) {
// eventually resolve if necessary.
return NamedType.builder(this, "typeof " + name).setScope(scope).setResolutionKind(ResolutionKind.TYPEOF).setErrorReportingLocationFrom(n).build();
}
if (type.isLiteralObject()) {
JSType scopeType = type;
type = NamedType.builder(this, "typeof " + name).setResolutionKind(ResolutionKind.NONE).setReferencedType(scopeType).build();
}
return type;
}
case STRINGLIT:
{
JSType nominalType = getType(scope, n.getString(), sourceName, n.getLineno(), n.getCharno());
ImmutableList<JSType> templateArgs = parseTemplateArgs(nominalType, n, sourceName, scope);
// Handle forward declared types
if (nominalType.isNamedType() && !nominalType.isResolved()) {
if (templateArgs != null) {
nominalType = nominalType.toMaybeNamedType().toBuilder().setTemplateTypes(templateArgs).build();
}
return addNullabilityBasedOnParseContext(n, nominalType, scope);
}
if (!(nominalType instanceof ObjectType) || isNonNullableName(scope, n.getString())) {
return nominalType;
}
if (templateArgs == null || !nominalType.isRawTypeOfTemplatizedType() || nominalType.isUnknownType()) {
// given isRawTypeOfTemplatizedType, but in some contexts is not.
return addNullabilityBasedOnParseContext(n, nominalType, scope);
}
return addNullabilityBasedOnParseContext(n, createTemplatizedType((ObjectType) nominalType, templateArgs), scope);
}
case FUNCTION:
JSType thisType = null;
boolean isConstructor = false;
Node current = n.getFirstChild();
if (current.isThis() || current.isNew()) {
Node contextNode = current.getFirstChild();
JSType candidateThisType = createTypeFromCommentNode(contextNode, sourceName, scope);
// and 'this' access should raise warnings.
if (candidateThisType.isNullType() || candidateThisType.isVoidType()) {
thisType = candidateThisType;
} else if (current.isThis()) {
thisType = candidateThisType.restrictByNotNullOrUndefined();
} else if (current.isNew()) {
thisType = ObjectType.cast(candidateThisType.restrictByNotNullOrUndefined());
if (thisType == null) {
reporter.warning(Msg.JSDOC_FUNCTION_NEWNOTOBJECT.format(), sourceName, contextNode.getLineno(), contextNode.getCharno());
}
}
isConstructor = current.getToken() == Token.NEW;
current = current.getNext();
}
FunctionParamBuilder paramBuilder = new FunctionParamBuilder(this);
if (current.getToken() == Token.PARAM_LIST) {
for (Node arg = current.getFirstChild(); arg != null; arg = arg.getNext()) {
if (arg.getToken() == Token.ITER_REST) {
if (!arg.hasChildren()) {
paramBuilder.addVarArgs(getNativeType(UNKNOWN_TYPE));
} else {
paramBuilder.addVarArgs(createTypeFromCommentNode(arg.getFirstChild(), sourceName, scope));
}
} else {
JSType type = createTypeFromCommentNode(arg, sourceName, scope);
if (arg.getToken() == Token.EQUALS) {
boolean addSuccess = paramBuilder.addOptionalParams(type);
if (!addSuccess) {
reporter.warning(Msg.JSDOC_FUNCTION_VARARGS.format(), sourceName, arg.getLineno(), arg.getCharno());
}
} else {
paramBuilder.addRequiredParams(type);
}
}
}
current = current.getNext();
}
JSType returnType = createTypeFromCommentNode(current, sourceName, scope);
return FunctionType.builder(this).withParameters(paramBuilder.build()).withReturnType(returnType).withTypeOfThis(thisType).withKind(isConstructor ? FunctionType.Kind.CONSTRUCTOR : FunctionType.Kind.ORDINARY).build();
default:
throw new IllegalStateException("Unexpected node in type expression: " + n);
}
}
Aggregations