Search in sources :

Example 1 with StaticSlot

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);
}
Also used : StaticSlot(com.google.javascript.rhino.StaticSlot) StaticRef(com.google.javascript.rhino.StaticRef)

Example 2 with StaticSlot

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;
}
Also used : StaticSlot(com.google.javascript.rhino.StaticSlot) StaticScope(com.google.javascript.rhino.StaticScope)

Example 3 with StaticSlot

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);
        }
    }
}
Also used : ObjectType(com.google.javascript.rhino.jstype.ObjectType) StaticSlot(com.google.javascript.rhino.StaticSlot) SimpleReference(com.google.javascript.rhino.jstype.SimpleReference)

Example 4 with StaticSlot

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);
    }
}
Also used : ImmutableList(com.google.common.collect.ImmutableList) Node(com.google.javascript.rhino.Node) QualifiedName(com.google.javascript.rhino.QualifiedName) StaticScope(com.google.javascript.rhino.StaticScope) StaticSlot(com.google.javascript.rhino.StaticSlot)

Aggregations

StaticSlot (com.google.javascript.rhino.StaticSlot)4 StaticScope (com.google.javascript.rhino.StaticScope)2 ImmutableList (com.google.common.collect.ImmutableList)1 Node (com.google.javascript.rhino.Node)1 QualifiedName (com.google.javascript.rhino.QualifiedName)1 StaticRef (com.google.javascript.rhino.StaticRef)1 ObjectType (com.google.javascript.rhino.jstype.ObjectType)1 SimpleReference (com.google.javascript.rhino.jstype.SimpleReference)1