Search in sources :

Example 1 with StaticTypedSlot

use of com.google.javascript.rhino.jstype.StaticTypedSlot in project closure-compiler by google.

the class TypeInference method getPropertyType.

private JSType getPropertyType(JSType objType, String propName, Node n, FlowScope scope) {
    // We often have a couple of different types to choose from for the
    // property. Ordered by accuracy, we have
    // 1) A locally inferred qualified name (which is in the FlowScope)
    // 2) A globally declared qualified name (which is in the FlowScope)
    // 3) A property on the owner type (which is on objType)
    // 4) A name in the type registry (as a last resort)
    JSType propertyType = null;
    boolean isLocallyInferred = false;
    // Scopes sometimes contain inferred type info about qualified names.
    String qualifiedName = n.getQualifiedName();
    StaticTypedSlot var = qualifiedName != null ? scope.getSlot(qualifiedName) : null;
    if (var != null) {
        JSType varType = var.getType();
        if (varType != null) {
            boolean isDeclared = !var.isTypeInferred();
            isLocallyInferred = (var != getDeclaredVar(scope, qualifiedName));
            if (isDeclared || isLocallyInferred) {
                propertyType = varType;
            }
        }
    }
    if (propertyType == null && objType != null) {
        JSType foundType = objType.findPropertyType(propName);
        if (foundType != null) {
            propertyType = foundType;
        }
    }
    if ((propertyType == null || propertyType.isUnknownType()) && qualifiedName != null) {
        // If we find this node in the registry, then we can infer its type.
        ObjectType regType = ObjectType.cast(registry.getType(scope.getDeclarationScope(), qualifiedName));
        if (regType != null) {
            propertyType = regType.getConstructor();
        }
    }
    if (propertyType == null) {
        return unknownType;
    } else if (propertyType.equals(unknownType) && isLocallyInferred) {
        // then use CHECKED_UNKNOWN_TYPE instead to indicate that.
        return getNativeType(CHECKED_UNKNOWN_TYPE);
    } else {
        return propertyType;
    }
}
Also used : ObjectType(com.google.javascript.rhino.jstype.ObjectType) JSType(com.google.javascript.rhino.jstype.JSType) StaticTypedSlot(com.google.javascript.rhino.jstype.StaticTypedSlot)

Example 2 with StaticTypedSlot

use of com.google.javascript.rhino.jstype.StaticTypedSlot in project closure-compiler by google.

the class TypeInference method traverseName.

private FlowScope traverseName(Node n, FlowScope scope) {
    String varName = n.getString();
    Node value = n.getFirstChild();
    JSType type = n.getJSType();
    if (value != null) {
        // The only case where `value` isn't null is when we are in a name declaration/initialization
        // var x = 3;
        scope = traverse(value, scope);
        return updateScopeForAssignment(scope, n, getJSType(value), AssignmentType.DECLARATION);
    }
    if (NodeUtil.isNameDeclaration(n.getParent()) && isPossibleMixinApplication(n, /* rvalue= */
    null)) {
        addMissingInterfaceProperties(type);
    }
    if (n.getParent().isLet()) {
        // Whenever we see a LET, we're guaranteed it's not yet in the scope, and we don't need to
        // worry about it being from an outer scope.  In this case, it has no child, so the actual
        // type should be undefined, but we make a special allowance for type-annotated variables.
        // In that case, we use the annotated type instead.
        // TODO(sdh): I would have thought that #updateScopeForTypeChange would handle using the
        // declared type correctly, but for some reason it doesn't so we handle it here.
        JSType resultType = type != null ? type : getNativeType(VOID_TYPE);
        scope = updateScopeForAssignment(scope, n, resultType, AssignmentType.DECLARATION);
        type = resultType;
    } else {
        StaticTypedSlot var = scope.getSlot(varName);
        if (var != null) {
            // There are two situations where we don't want to use type information
            // from the scope, even if we have it.
            // 1) The var is escaped and assigned in an inner scope, e.g.,
            // function f() { var x = 3; function g() { x = null } (x); }
            boolean isInferred = var.isTypeInferred();
            boolean unflowable = isInferred && isUnflowable(getDeclaredVar(scope, varName));
            // 2) We're reading type information from another scope for an
            // inferred variable. That variable is assigned more than once,
            // and we can't know which type we're getting.
            // 
            // var t = null; function f() { (t); } doStuff(); t = {};
            // 
            // Notice that this heuristic isn't perfect. For example, you might
            // have:
            // 
            // function f() { (t); } f(); var t = 3;
            // 
            // In this case, we would infer the first reference to t as
            // type {number}, even though it's undefined.
            TypedVar maybeOuterVar = isInferred && containerScope.isLocal() ? containerScope.getParent().getVar(varName) : null;
            boolean nonLocalInferredSlot = var.equals(maybeOuterVar) && !maybeOuterVar.isMarkedAssignedExactlyOnce();
            if (!unflowable && !nonLocalInferredSlot) {
                type = var.getType();
                if (type == null) {
                    type = unknownType;
                }
            }
        }
    }
    n.setJSType(type);
    return scope;
}
Also used : JSType(com.google.javascript.rhino.jstype.JSType) StaticTypedSlot(com.google.javascript.rhino.jstype.StaticTypedSlot) Node(com.google.javascript.rhino.Node)

Example 3 with StaticTypedSlot

use of com.google.javascript.rhino.jstype.StaticTypedSlot in project closure-compiler by google.

the class TypeTransformation method evalTypeOfVar.

private JSType evalTypeOfVar(Node ttlAst) {
    String name = getCallArgument(ttlAst, 0).getString();
    StaticTypedSlot slot = typeEnv.getSlot(name);
    JSType type = slot != null ? slot.getType() : null;
    if (type == null) {
        reportWarning(ttlAst, VAR_UNDEFINED, name);
        return getUnknownType();
    }
    return type;
}
Also used : StaticTypedSlot(com.google.javascript.rhino.jstype.StaticTypedSlot) JSType(com.google.javascript.rhino.jstype.JSType)

Example 4 with StaticTypedSlot

use of com.google.javascript.rhino.jstype.StaticTypedSlot in project closure-compiler by google.

the class TypeTransformation method getType.

private JSType getType(String typeName) {
    JSType type = registry.getType(typeEnv, typeName);
    if (type != null) {
        return type;
    }
    StaticTypedSlot slot = typeEnv.getSlot(typeName);
    type = slot != null ? slot.getType() : null;
    if (type != null) {
        if (type.isConstructor() || type.isInterface()) {
            return type.toMaybeFunctionType().getInstanceType().getRawType();
        }
        if (type.isEnumElementType()) {
            return type.getEnumeratedTypeOfEnumElement();
        }
        return type;
    }
    JSDocInfo jsdoc = slot == null ? null : slot.getJSDocInfo();
    if (jsdoc != null && jsdoc.hasTypedefType()) {
        return this.registry.evaluateTypeExpression(jsdoc.getTypedefType(), typeEnv);
    }
    return null;
}
Also used : JSType(com.google.javascript.rhino.jstype.JSType) StaticTypedSlot(com.google.javascript.rhino.jstype.StaticTypedSlot) JSDocInfo(com.google.javascript.rhino.JSDocInfo)

Example 5 with StaticTypedSlot

use of com.google.javascript.rhino.jstype.StaticTypedSlot in project closure-compiler by google.

the class SemanticReverseAbstractInterpreter method caseAndOrMaybeShortCircuiting.

@CheckReturnValue
private FlowScope caseAndOrMaybeShortCircuiting(Node left, Node right, FlowScope blindScope, Outcome outcome) {
    // Perform two separate refinements, one for if short-circuiting occurred, and one for if it did
    // not.  Because it's not clear whether short-circuiting occurred, we actually have to ignore
    // both separate result flow scopes individually, but if they both refined the same slot, we
    // can join the two refinements.  TODO(sdh): look into simplifying this.  If joining were
    // more efficient, we should just be able to join the scopes unconditionally?
    Set<String> refinements = new HashSet<>();
    blindScope = new RefinementTrackingFlowScope(blindScope, refinements);
    FlowScope leftScope = firstPreciserScopeKnowingConditionOutcome(left, blindScope, outcome.not());
    StaticTypedSlot leftVar = refinements.size() == 1 ? leftScope.getSlot(refinements.iterator().next()) : null;
    if (leftVar == null) {
        // must create a child instead.
        return unwrap(blindScope);
    }
    refinements.clear();
    // Note: re-wrap the scope, in case it was unwrapped by a nested call to this method.
    FlowScope rightScope = new RefinementTrackingFlowScope(firstPreciserScopeKnowingConditionOutcome(left, blindScope, outcome), refinements);
    rightScope = firstPreciserScopeKnowingConditionOutcome(right, rightScope, outcome.not());
    StaticTypedSlot rightVar = refinements.size() == 1 ? rightScope.getSlot(refinements.iterator().next()) : null;
    if (rightVar == null || !leftVar.getName().equals(rightVar.getName())) {
        return unwrap(blindScope);
    }
    JSType type = leftVar.getType().getLeastSupertype(rightVar.getType());
    return unwrap(blindScope).inferSlotType(leftVar.getName(), type);
}
Also used : StaticTypedSlot(com.google.javascript.rhino.jstype.StaticTypedSlot) JSType(com.google.javascript.rhino.jstype.JSType) HashSet(java.util.HashSet) CheckReturnValue(com.google.errorprone.annotations.CheckReturnValue)

Aggregations

StaticTypedSlot (com.google.javascript.rhino.jstype.StaticTypedSlot)8 JSType (com.google.javascript.rhino.jstype.JSType)6 Node (com.google.javascript.rhino.Node)2 CheckReturnValue (com.google.errorprone.annotations.CheckReturnValue)1 JSDocInfo (com.google.javascript.rhino.JSDocInfo)1 ObjectType (com.google.javascript.rhino.jstype.ObjectType)1 StaticTypedRef (com.google.javascript.rhino.jstype.StaticTypedRef)1 StaticTypedScope (com.google.javascript.rhino.jstype.StaticTypedScope)1 NodeSubject.assertNode (com.google.javascript.rhino.testing.NodeSubject.assertNode)1 HashSet (java.util.HashSet)1