Search in sources :

Example 1 with FunctionTypeI

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

the class CheckNullableReturn method isReturnTypeNullable.

/**
 * @return True if n is a function node which is explicitly annotated
 * as returning a nullable type, other than {?}.
 */
private static boolean isReturnTypeNullable(Node n) {
    if (n == null || !n.isFunction()) {
        return false;
    }
    FunctionTypeI functionType = n.getTypeI().toMaybeFunctionType();
    if (functionType == null) {
        // If the JSDoc declares a non-function type on a function node, we still shouldn't crash.
        return false;
    }
    TypeI returnType = functionType.getReturnType();
    if (returnType == null || returnType.isUnknownType() || !returnType.isNullable()) {
        return false;
    }
    JSDocInfo info = NodeUtil.getBestJSDocInfo(n);
    return info != null && info.hasReturnType();
}
Also used : TypeI(com.google.javascript.rhino.TypeI) FunctionTypeI(com.google.javascript.rhino.FunctionTypeI) FunctionTypeI(com.google.javascript.rhino.FunctionTypeI) JSDocInfo(com.google.javascript.rhino.JSDocInfo)

Example 2 with FunctionTypeI

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

the class TypedCodeGenerator method getFunctionAnnotation.

/**
 * @param fnNode A node for a function for which to generate a type annotation
 */
private String getFunctionAnnotation(Node fnNode) {
    TypeI type = fnNode.getTypeI();
    checkState(fnNode.isFunction() || type.isFunctionType());
    if (type == null || type.isUnknownType()) {
        return "";
    }
    FunctionTypeI funType = type.toMaybeFunctionType();
    if (type.equals(registry.getNativeType(JSTypeNative.FUNCTION_INSTANCE_TYPE))) {
        return "/** @type {!Function} */\n";
    }
    StringBuilder sb = new StringBuilder("/**\n");
    Node paramNode = null;
    // NAME param2
    if (fnNode != null && fnNode.isFunction()) {
        paramNode = NodeUtil.getFunctionParameters(fnNode).getFirstChild();
    }
    // Param types
    int minArity = funType.getMinArity();
    int maxArity = funType.getMaxArity();
    List<TypeI> formals = ImmutableList.copyOf(funType.getParameterTypes());
    for (int i = 0; i < formals.size(); i++) {
        sb.append(" * ");
        appendAnnotation(sb, "param", getParameterJSDocType(formals, i, minArity, maxArity));
        sb.append(" ").append(paramNode == null ? "p" + i : paramNode.getString()).append("\n");
        if (paramNode != null) {
            paramNode = paramNode.getNext();
        }
    }
    // Return type
    TypeI retType = funType.getReturnType();
    if (retType != null && // There is no annotation for the empty type.
    !retType.isBottom() && // Interfaces never return a value.
    !funType.isInterface() && !(funType.isConstructor() && retType.isVoidType())) {
        sb.append(" * ");
        appendAnnotation(sb, "return", retType.toAnnotationString(Nullability.EXPLICIT));
        sb.append("\n");
    }
    if (funType.isConstructor()) {
        appendConstructorAnnotations(sb, funType);
    } else if (funType.isInterface()) {
        appendInterfaceAnnotations(sb, funType);
    } else {
        TypeI thisType = funType.getTypeOfThis();
        if (thisType != null && !thisType.isUnknownType() && !thisType.isVoidType()) {
            if (fnNode == null || !thisType.equals(findMethodOwner(fnNode))) {
                sb.append(" * ");
                appendAnnotation(sb, "this", thisType.toAnnotationString(Nullability.EXPLICIT));
                sb.append("\n");
            }
        }
    }
    Collection<TypeI> typeParams = funType.getTypeParameters();
    if (!typeParams.isEmpty()) {
        sb.append(" * @template ");
        Joiner.on(",").appendTo(sb, Iterables.transform(typeParams, new Function<TypeI, String>() {

            @Override
            public String apply(TypeI var) {
                return formatTypeVar(var);
            }
        }));
        sb.append("\n");
    }
    sb.append(" */\n");
    return sb.toString();
}
Also used : Function(com.google.common.base.Function) TypeI(com.google.javascript.rhino.TypeI) ObjectTypeI(com.google.javascript.rhino.ObjectTypeI) FunctionTypeI(com.google.javascript.rhino.FunctionTypeI) Node(com.google.javascript.rhino.Node) FunctionTypeI(com.google.javascript.rhino.FunctionTypeI)

Example 3 with FunctionTypeI

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

the class TypedCodeGenerator method appendConstructorAnnotations.

// TODO(dimvar): it's awkward that we print @constructor after the extends/implements;
// we should print it first, like users write it. Same for @interface and @record.
private void appendConstructorAnnotations(StringBuilder sb, FunctionTypeI funType) {
    FunctionTypeI superConstructor = funType.getInstanceType().getSuperClassConstructor();
    if (superConstructor != null) {
        ObjectTypeI superInstance = superConstructor.getInstanceType();
        if (!superInstance.toString().equals("Object")) {
            sb.append(" * ");
            appendAnnotation(sb, "extends", superInstance.toAnnotationString(Nullability.IMPLICIT));
            sb.append("\n");
        }
    }
    // Avoid duplicates, add implemented type to a set first
    Set<String> interfaces = new TreeSet<>();
    for (ObjectTypeI interfaze : funType.getAncestorInterfaces()) {
        interfaces.add(interfaze.toAnnotationString(Nullability.IMPLICIT));
    }
    for (String interfaze : interfaces) {
        sb.append(" * ");
        appendAnnotation(sb, "implements", interfaze);
        sb.append("\n");
    }
    sb.append(" * @constructor\n");
}
Also used : ObjectTypeI(com.google.javascript.rhino.ObjectTypeI) TreeSet(java.util.TreeSet) FunctionTypeI(com.google.javascript.rhino.FunctionTypeI)

Example 4 with FunctionTypeI

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

the class AmbiguateProperties method computeRelatedTypes.

/**
 * Adds subtypes - and implementors, in the case of interfaces - of the type
 * to its JSTypeBitSet of related types. Union types are decomposed into their
 * alternative types.
 *
 * <p>The 'is related to' relationship is best understood graphically. Draw an
 * arrow from each instance type to the prototype of each of its
 * subclass. Draw an arrow from each prototype to its instance type. Draw an
 * arrow from each interface to its implementors. A type is related to another
 * if there is a directed path in the graph from the type to other. Thus, the
 * 'is related to' relationship is reflexive and transitive.
 *
 * <p>Example with Foo extends Bar which extends Baz and Bar implements I:
 * <pre>{@code
 * Foo -> Bar.prototype -> Bar -> Baz.prototype -> Baz
 *                          ^
 *                          |
 *                          I
 * }</pre>
 *
 * <p>Note that we don't need to correctly handle the relationships between
 * functions, because the function type is invalidating (i.e. its properties
 * won't be ambiguated).
 */
private void computeRelatedTypes(TypeI type) {
    if (type.isUnionType()) {
        type = type.restrictByNotNullOrUndefined();
        if (type.isUnionType()) {
            for (TypeI alt : type.getUnionMembers()) {
                computeRelatedTypes(alt);
            }
            return;
        }
    }
    if (relatedBitsets.containsKey(type)) {
        // We only need to generate the bit set once.
        return;
    }
    JSTypeBitSet related = new JSTypeBitSet(intForType.size());
    relatedBitsets.put(type, related);
    related.set(getIntForType(type));
    // A prototype is related to its instance.
    if (type.isPrototypeObject()) {
        FunctionTypeI maybeCtor = type.toMaybeObjectType().getOwnerFunction();
        if (maybeCtor.isConstructor() || maybeCtor.isInterface()) {
            addRelatedInstance(maybeCtor, related);
        }
        return;
    }
    // A class/interface is related to its subclasses/implementors.
    FunctionTypeI constructor = type.toMaybeObjectType().getConstructor();
    if (constructor != null) {
        for (FunctionTypeI subType : constructor.getDirectSubTypes()) {
            addRelatedInstance(subType, related);
        }
    }
}
Also used : FunctionTypeI(com.google.javascript.rhino.FunctionTypeI) TypeI(com.google.javascript.rhino.TypeI) ObjectTypeI(com.google.javascript.rhino.ObjectTypeI) FunctionTypeI(com.google.javascript.rhino.FunctionTypeI)

Example 5 with FunctionTypeI

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

the class AstValidator method validateCallType.

private void validateCallType(Node callNode) {
    // TODO(b/74537281): Shouldn't CALL nodes always have a type, even if it is unknown?
    Node callee = callNode.getFirstChild();
    TypeI calleeTypeI = checkNotNull(callee.getTypeI(), callNode);
    if (calleeTypeI.isFunctionType()) {
        FunctionTypeI calleeFunctionTypeI = calleeTypeI.toMaybeFunctionType();
        TypeI returnTypeI = calleeFunctionTypeI.getReturnType();
        // TODO(b/74537281): This will fail after CAST nodes have been removed from the AST.
        // Must be fixed before this check can be done after optimizations.
        expectMatchingTypeInformation(callNode, returnTypeI);
    }
// TODO(b/74537281): What other cases should be covered?
}
Also used : Node(com.google.javascript.rhino.Node) TypeI(com.google.javascript.rhino.TypeI) FunctionTypeI(com.google.javascript.rhino.FunctionTypeI) FunctionTypeI(com.google.javascript.rhino.FunctionTypeI)

Aggregations

FunctionTypeI (com.google.javascript.rhino.FunctionTypeI)15 TypeI (com.google.javascript.rhino.TypeI)10 ObjectTypeI (com.google.javascript.rhino.ObjectTypeI)9 Node (com.google.javascript.rhino.Node)3 JSDocInfo (com.google.javascript.rhino.JSDocInfo)2 Function (com.google.common.base.Function)1 FunctionType (com.google.javascript.rhino.jstype.FunctionType)1 ObjectType (com.google.javascript.rhino.jstype.ObjectType)1 ArrayList (java.util.ArrayList)1 TreeSet (java.util.TreeSet)1 Nullable (javax.annotation.Nullable)1