Java Code Examples for com.google.javascript.rhino.jstype.JSType#canAssignTo()

The following examples show how to use com.google.javascript.rhino.jstype.JSType#canAssignTo() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: Closure_6_TypeValidator_t.java    From coming with MIT License 6 votes vote down vote up
/**
 * Expect that the first type can be assigned to a symbol of the second
 * type.
 *
 * @param t The node traversal.
 * @param n The node to issue warnings on.
 * @param rightType The type on the RHS of the assign.
 * @param leftType The type of the symbol on the LHS of the assign.
 * @param owner The owner of the property being assigned to.
 * @param propName The name of the property being assigned to.
 * @return True if the types matched, false otherwise.
 */
boolean expectCanAssignToPropertyOf(NodeTraversal t, Node n, JSType rightType,
    JSType leftType, Node owner, String propName) {
  // The NoType check is a hack to make typedefs work OK.
  if (!leftType.isNoType() && !rightType.canAssignTo(leftType)) {
    // Do not type-check interface methods, because we expect that
    // they will have dummy implementations that do not match the type
    // annotations.
    JSType ownerType = getJSType(owner);
    if (ownerType.isFunctionPrototypeType()) {
      FunctionType ownerFn = ownerType.toObjectType().getOwnerFunction();
      if (ownerFn.isInterface() &&
          rightType.isFunctionType() && leftType.isFunctionType()) {
        return true;
      }
    }

    mismatch(t, n,
        "assignment to property " + propName + " of " +
        getReadableJSTypeName(owner, true),
        rightType, leftType);
    return false;
  }
  return true;
}
 
Example 2
Source File: Closure_6_TypeValidator_s.java    From coming with MIT License 6 votes vote down vote up
private void registerMismatch(JSType found, JSType required, JSError error) {
  // Don't register a mismatch for differences in null or undefined or if the
  // code didn't downcast.
  found = found.restrictByNotNullOrUndefined();
  required = required.restrictByNotNullOrUndefined();
  if (found.canAssignTo(required) || required.canAssignTo(found)) {
    return;
  }

  mismatches.add(new TypeMismatch(found, required, error));
  if (found.isFunctionType() &&
      required.isFunctionType()) {
    FunctionType fnTypeA = found.toMaybeFunctionType();
    FunctionType fnTypeB = required.toMaybeFunctionType();
    Iterator<Node> paramItA = fnTypeA.getParameters().iterator();
    Iterator<Node> paramItB = fnTypeB.getParameters().iterator();
    while (paramItA.hasNext() && paramItB.hasNext()) {
      registerIfMismatch(paramItA.next().getJSType(),
          paramItB.next().getJSType(), error);
    }

    registerIfMismatch(
        fnTypeA.getReturnType(), fnTypeB.getReturnType(), error);
  }
}
 
Example 3
Source File: Closure_6_TypeValidator_t.java    From coming with MIT License 6 votes vote down vote up
private void registerMismatch(JSType found, JSType required, JSError error) {
  // Don't register a mismatch for differences in null or undefined or if the
  // code didn't downcast.
  found = found.restrictByNotNullOrUndefined();
  required = required.restrictByNotNullOrUndefined();
  if (found.canAssignTo(required) || required.canAssignTo(found)) {
    return;
  }

  mismatches.add(new TypeMismatch(found, required, error));
  if (found.isFunctionType() &&
      required.isFunctionType()) {
    FunctionType fnTypeA = found.toMaybeFunctionType();
    FunctionType fnTypeB = required.toMaybeFunctionType();
    Iterator<Node> paramItA = fnTypeA.getParameters().iterator();
    Iterator<Node> paramItB = fnTypeB.getParameters().iterator();
    while (paramItA.hasNext() && paramItB.hasNext()) {
      registerIfMismatch(paramItA.next().getJSType(),
          paramItB.next().getJSType(), error);
    }

    registerIfMismatch(
        fnTypeA.getReturnType(), fnTypeB.getReturnType(), error);
  }
}
 
Example 4
Source File: Closure_6_TypeValidator_t.java    From coming with MIT License 5 votes vote down vote up
private void registerIfMismatch(
    JSType found, JSType required, JSError error) {
  if (found != null && required != null &&
      !found.canAssignTo(required)) {
    registerMismatch(found, required, error);
  }
}
 
Example 5
Source File: Closure_6_TypeValidator_s.java    From coming with MIT License 5 votes vote down vote up
private void registerIfMismatch(
    JSType found, JSType required, JSError error) {
  if (found != null && required != null &&
      !found.canAssignTo(required)) {
    registerMismatch(found, required, error);
  }
}
 
Example 6
Source File: Closure_6_TypeValidator_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Expect that the property in an interface that this type implements is
 * implemented and correctly typed.
 */
private void expectInterfaceProperty(NodeTraversal t, Node n,
    ObjectType instance, ObjectType implementedInterface, String prop) {
  StaticSlot<JSType> propSlot = instance.getSlot(prop);
  if (propSlot == null) {
    // Not implemented
    String sourceName = n.getSourceFileName();
    sourceName = sourceName == null ? "" : sourceName;
    registerMismatch(instance, implementedInterface,
        report(JSError.make(sourceName, n,
        INTERFACE_METHOD_NOT_IMPLEMENTED,
        prop, implementedInterface.toString(), instance.toString())));
  } else {
    Node propNode = propSlot.getDeclaration() == null ?
        null : propSlot.getDeclaration().getNode();

    // Fall back on the constructor node if we can't find a node for the
    // property.
    propNode = propNode == null ? n : propNode;

    JSType found = propSlot.getType();
    JSType required
        = implementedInterface.getImplicitPrototype().getPropertyType(prop);
    found = found.restrictByNotNullOrUndefined();
    required = required.restrictByNotNullOrUndefined();
    if (!found.canAssignTo(required)) {
      // Implemented, but not correctly typed
      FunctionType constructor =
          implementedInterface.toObjectType().getConstructor();
      registerMismatch(found, required, report(t.makeError(propNode,
          HIDDEN_INTERFACE_PROPERTY_MISMATCH, prop,
          constructor.getTopMostDefiningType(prop).toString(),
          required.toString(), found.toString())));
    }
  }
}
 
Example 7
Source File: Closure_6_TypeValidator_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Expect that the first type can be cast to the second type. The first type
 * should be either a subtype or supertype of the second.
 *
 * @param t The node traversal.
 * @param n The node where warnings should point.
 * @param type The type being cast from.
 * @param castType The type being cast to.
 */
void expectCanCast(NodeTraversal t, Node n, JSType type, JSType castType) {
  castType = castType.restrictByNotNullOrUndefined();
  type = type.restrictByNotNullOrUndefined();

  if (!type.canAssignTo(castType) && !castType.canAssignTo(type)) {
    registerMismatch(type, castType, report(t.makeError(n, INVALID_CAST,
        castType.toString(), type.toString())));
  }
}
 
Example 8
Source File: Closure_6_TypeValidator_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Expect that the first type can be assigned to a symbol of the second
 * type.
 *
 * @param t The node traversal.
 * @param n The node to issue warnings on.
 * @param rightType The type on the RHS of the assign.
 * @param leftType The type of the symbol on the LHS of the assign.
 * @param msg An extra message for the mismatch warning, if necessary.
 * @return True if the types matched, false otherwise.
 */
boolean expectCanAssignTo(NodeTraversal t, Node n, JSType rightType,
    JSType leftType, String msg) {
  if (!rightType.canAssignTo(leftType)) {
    if ((leftType.isConstructor() || leftType.isEnumType()) && (rightType.isConstructor() || rightType.isEnumType())) {
      registerMismatch(rightType, leftType, null);
    } else {
    mismatch(t, n, msg, rightType, leftType);
    }
    return false;
  }
  return true;
}
 
Example 9
Source File: Closure_6_TypeValidator_s.java    From coming with MIT License 5 votes vote down vote up
/**
 * Expect that the first type can be assigned to a symbol of the second
 * type.
 *
 * @param t The node traversal.
 * @param n The node to issue warnings on.
 * @param rightType The type on the RHS of the assign.
 * @param leftType The type of the symbol on the LHS of the assign.
 * @param owner The owner of the property being assigned to.
 * @param propName The name of the property being assigned to.
 * @return True if the types matched, false otherwise.
 */
boolean expectCanAssignToPropertyOf(NodeTraversal t, Node n, JSType rightType,
    JSType leftType, Node owner, String propName) {
  // The NoType check is a hack to make typedefs work OK.
  if (!leftType.isNoType() && !rightType.canAssignTo(leftType)) {
    if ((leftType.isConstructor() || leftType.isEnumType()) && (rightType.isConstructor() || rightType.isEnumType())) {
      registerMismatch(rightType, leftType, null);
    } else {
    // Do not type-check interface methods, because we expect that
    // they will have dummy implementations that do not match the type
    // annotations.
    JSType ownerType = getJSType(owner);
    if (ownerType.isFunctionPrototypeType()) {
      FunctionType ownerFn = ownerType.toObjectType().getOwnerFunction();
      if (ownerFn.isInterface() &&
          rightType.isFunctionType() && leftType.isFunctionType()) {
        return true;
      }
    }

    mismatch(t, n,
        "assignment to property " + propName + " of " +
        getReadableJSTypeName(owner, true),
        rightType, leftType);
    }
    return false;
  }
  return true;
}
 
Example 10
Source File: Closure_6_TypeValidator_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * Expect that the property in an interface that this type implements is
 * implemented and correctly typed.
 */
private void expectInterfaceProperty(NodeTraversal t, Node n,
    ObjectType instance, ObjectType implementedInterface, String prop) {
  StaticSlot<JSType> propSlot = instance.getSlot(prop);
  if (propSlot == null) {
    // Not implemented
    String sourceName = n.getSourceFileName();
    sourceName = sourceName == null ? "" : sourceName;
    registerMismatch(instance, implementedInterface,
        report(JSError.make(sourceName, n,
        INTERFACE_METHOD_NOT_IMPLEMENTED,
        prop, implementedInterface.toString(), instance.toString())));
  } else {
    Node propNode = propSlot.getDeclaration() == null ?
        null : propSlot.getDeclaration().getNode();

    // Fall back on the constructor node if we can't find a node for the
    // property.
    propNode = propNode == null ? n : propNode;

    JSType found = propSlot.getType();
    JSType required
        = implementedInterface.getImplicitPrototype().getPropertyType(prop);
    found = found.restrictByNotNullOrUndefined();
    required = required.restrictByNotNullOrUndefined();
    if (!found.canAssignTo(required)) {
      // Implemented, but not correctly typed
      FunctionType constructor =
          implementedInterface.toObjectType().getConstructor();
      registerMismatch(found, required, report(t.makeError(propNode,
          HIDDEN_INTERFACE_PROPERTY_MISMATCH, prop,
          constructor.getTopMostDefiningType(prop).toString(),
          required.toString(), found.toString())));
    }
  }
}
 
Example 11
Source File: Closure_6_TypeValidator_t.java    From coming with MIT License 5 votes vote down vote up
/**
 * Expect that the first type can be cast to the second type. The first type
 * should be either a subtype or supertype of the second.
 *
 * @param t The node traversal.
 * @param n The node where warnings should point.
 * @param type The type being cast from.
 * @param castType The type being cast to.
 */
void expectCanCast(NodeTraversal t, Node n, JSType type, JSType castType) {
  castType = castType.restrictByNotNullOrUndefined();
  type = type.restrictByNotNullOrUndefined();

  if (!type.canAssignTo(castType) && !castType.canAssignTo(type)) {
    registerMismatch(type, castType, report(t.makeError(n, INVALID_CAST,
        castType.toString(), type.toString())));
  }
}
 
Example 12
Source File: Closure_96_TypeCheck_t.java    From coming with MIT License 4 votes vote down vote up
/**
 * Given a constructor type and a property name, check that the property has
 * the JSDoc annotation @override iff the property is declared on a
 * superclass. Several checks regarding inheritance correctness are also
 * performed.
 */
private void checkDeclaredPropertyInheritance(
    NodeTraversal t, Node n, FunctionType ctorType, String propertyName,
    JSDocInfo info, JSType propertyType) {
  // TODO(user): We're not 100% confident that type-checking works,
  // so we return quietly if the unknown type is a superclass of this type.
  // Remove this check as we become more confident. We should flag a warning
  // when the unknown type is on the inheritance chain, as it is likely
  // because of a programmer error.
  if (ctorType.hasUnknownSupertype()) {
    return;
  }

  FunctionType superClass = ctorType.getSuperClassConstructor();
  boolean superClassHasProperty = superClass != null &&
      superClass.getPrototype().hasProperty(propertyName);
  boolean declaredOverride = info != null && info.isOverride();

  boolean foundInterfaceProperty = false;
  if (ctorType.isConstructor()) {
    for (JSType implementedInterface : ctorType.getImplementedInterfaces()) {
      if (implementedInterface.isUnknownType()) {
        continue;
      }
      FunctionType interfaceType =
          implementedInterface.toObjectType().getConstructor();
      boolean interfaceHasProperty =
          interfaceType.getPrototype().hasProperty(propertyName);
      foundInterfaceProperty = foundInterfaceProperty || interfaceHasProperty;
      if (reportMissingOverride.isOn() && !declaredOverride &&
          interfaceHasProperty) {
        // @override not present, but the property does override an interface
        // property
        compiler.report(t.makeError(n, reportMissingOverride,
            HIDDEN_INTERFACE_PROPERTY, propertyName,
            interfaceType.getTopMostDefiningType(propertyName).toString()));
      }
      if (!declaredOverride) {
        continue;
      }
      // @override is present and we have to check that it is ok
      if (interfaceHasProperty) {
        JSType interfacePropType =
            interfaceType.getPrototype().getPropertyType(propertyName);
        if (!propertyType.canAssignTo(interfacePropType)) {
          compiler.report(t.makeError(n,
              HIDDEN_INTERFACE_PROPERTY_MISMATCH, propertyName,
              interfaceType.getTopMostDefiningType(propertyName).toString(),
              interfacePropType.toString(), propertyType.toString()));
        }
      }
    }
  }

  if (!declaredOverride && !superClassHasProperty) {
    // nothing to do here, it's just a plain new property
    return;
  }

  JSType topInstanceType = superClassHasProperty ?
      superClass.getTopMostDefiningType(propertyName) : null;
  if (reportMissingOverride.isOn() && ctorType.isConstructor() &&
      !declaredOverride && superClassHasProperty) {
    // @override not present, but the property does override a superclass
    // property
    compiler.report(t.makeError(n, reportMissingOverride,
        HIDDEN_SUPERCLASS_PROPERTY, propertyName,
        topInstanceType.toString()));
  }
  if (!declaredOverride) {
    // there's no @override to check
    return;
  }
  // @override is present and we have to check that it is ok
  if (superClassHasProperty) {
    // there is a superclass implementation
    JSType superClassPropType =
        superClass.getPrototype().getPropertyType(propertyName);
    if (!propertyType.canAssignTo(superClassPropType)) {
      compiler.report(
          t.makeError(n, HIDDEN_SUPERCLASS_PROPERTY_MISMATCH,
              propertyName, topInstanceType.toString(),
              superClassPropType.toString(), propertyType.toString()));
    }
  } else if (!foundInterfaceProperty) {
    // there is no superclass nor interface implementation
    compiler.report(
        t.makeError(n, UNKNOWN_OVERRIDE,
            propertyName, ctorType.getInstanceType().toString()));
  }
}
 
Example 13
Source File: Closure_96_TypeCheck_s.java    From coming with MIT License 4 votes vote down vote up
/**
 * Given a constructor type and a property name, check that the property has
 * the JSDoc annotation @override iff the property is declared on a
 * superclass. Several checks regarding inheritance correctness are also
 * performed.
 */
private void checkDeclaredPropertyInheritance(
    NodeTraversal t, Node n, FunctionType ctorType, String propertyName,
    JSDocInfo info, JSType propertyType) {
  // TODO(user): We're not 100% confident that type-checking works,
  // so we return quietly if the unknown type is a superclass of this type.
  // Remove this check as we become more confident. We should flag a warning
  // when the unknown type is on the inheritance chain, as it is likely
  // because of a programmer error.
  if (ctorType.hasUnknownSupertype()) {
    return;
  }

  FunctionType superClass = ctorType.getSuperClassConstructor();
  boolean superClassHasProperty = superClass != null &&
      superClass.getPrototype().hasProperty(propertyName);
  boolean declaredOverride = info != null && info.isOverride();

  boolean foundInterfaceProperty = false;
  if (ctorType.isConstructor()) {
    for (JSType implementedInterface : ctorType.getImplementedInterfaces()) {
      if (implementedInterface.isUnknownType()) {
        continue;
      }
      FunctionType interfaceType =
          implementedInterface.toObjectType().getConstructor();
      boolean interfaceHasProperty =
          interfaceType.getPrototype().hasProperty(propertyName);
      foundInterfaceProperty = foundInterfaceProperty || interfaceHasProperty;
      if (reportMissingOverride.isOn() && !declaredOverride &&
          interfaceHasProperty) {
        // @override not present, but the property does override an interface
        // property
        compiler.report(t.makeError(n, reportMissingOverride,
            HIDDEN_INTERFACE_PROPERTY, propertyName,
            interfaceType.getTopMostDefiningType(propertyName).toString()));
      }
      if (!declaredOverride) {
        continue;
      }
      // @override is present and we have to check that it is ok
      if (interfaceHasProperty) {
        JSType interfacePropType =
            interfaceType.getPrototype().getPropertyType(propertyName);
        if (!propertyType.canAssignTo(interfacePropType)) {
          compiler.report(t.makeError(n,
              HIDDEN_INTERFACE_PROPERTY_MISMATCH, propertyName,
              interfaceType.getTopMostDefiningType(propertyName).toString(),
              interfacePropType.toString(), propertyType.toString()));
        }
      }
    }
  }

  if (!declaredOverride && !superClassHasProperty) {
    // nothing to do here, it's just a plain new property
    return;
  }

  JSType topInstanceType = superClassHasProperty ?
      superClass.getTopMostDefiningType(propertyName) : null;
  if (reportMissingOverride.isOn() && ctorType.isConstructor() &&
      !declaredOverride && superClassHasProperty) {
    // @override not present, but the property does override a superclass
    // property
    compiler.report(t.makeError(n, reportMissingOverride,
        HIDDEN_SUPERCLASS_PROPERTY, propertyName,
        topInstanceType.toString()));
  }
  if (!declaredOverride) {
    // there's no @override to check
    return;
  }
  // @override is present and we have to check that it is ok
  if (superClassHasProperty) {
    // there is a superclass implementation
    JSType superClassPropType =
        superClass.getPrototype().getPropertyType(propertyName);
    if (!propertyType.canAssignTo(superClassPropType)) {
      compiler.report(
          t.makeError(n, HIDDEN_SUPERCLASS_PROPERTY_MISMATCH,
              propertyName, topInstanceType.toString(),
              superClassPropType.toString(), propertyType.toString()));
    }
  } else if (!foundInterfaceProperty) {
    // there is no superclass nor interface implementation
    compiler.report(
        t.makeError(n, UNKNOWN_OVERRIDE,
            propertyName, ctorType.getInstanceType().toString()));
  }
}
 
Example 14
Source File: Closure_6_TypeValidator_s.java    From coming with MIT License 3 votes vote down vote up
/**
 * Expect that the type of an argument matches the type of the parameter
 * that it's fulfilling.
 *
 * @param t The node traversal.
 * @param n The node to issue warnings on.
 * @param argType The type of the argument.
 * @param paramType The type of the parameter.
 * @param callNode The call node, to help with the warning message.
 * @param ordinal The argument ordinal, to help with the warning message.
 */
void expectArgumentMatchesParameter(NodeTraversal t, Node n, JSType argType,
    JSType paramType, Node callNode, int ordinal) {
  if (!argType.canAssignTo(paramType)) {
    mismatch(t, n,
        String.format("actual parameter %d of %s does not match " +
            "formal parameter", ordinal,
            getReadableJSTypeName(callNode.getFirstChild(), false)),
        argType, paramType);
  }
}
 
Example 15
Source File: Closure_6_TypeValidator_s.java    From coming with MIT License 3 votes vote down vote up
/**
 * Expect that the first type can override a property of the second
 * type.
 *
 * @param t The node traversal.
 * @param n The node to issue warnings on.
 * @param overridingType The overriding type.
 * @param hiddenType The type of the property being overridden.
 * @param propertyName The name of the property, for use in the
 *     warning message.
 * @param ownerType The type of the owner of the property, for use
 *     in the warning message.
 */
void expectCanOverride(NodeTraversal t, Node n, JSType overridingType,
    JSType hiddenType, String propertyName, JSType ownerType) {
  if (!overridingType.canAssignTo(hiddenType)) {
    registerMismatch(overridingType, hiddenType,
        report(t.makeError(n, HIDDEN_PROPERTY_MISMATCH, propertyName,
          ownerType.toString(), hiddenType.toString(),
          overridingType.toString())));
  }
}
 
Example 16
Source File: Closure_6_TypeValidator_t.java    From coming with MIT License 3 votes vote down vote up
/**
 * Expect that the first type can override a property of the second
 * type.
 *
 * @param t The node traversal.
 * @param n The node to issue warnings on.
 * @param overridingType The overriding type.
 * @param hiddenType The type of the property being overridden.
 * @param propertyName The name of the property, for use in the
 *     warning message.
 * @param ownerType The type of the owner of the property, for use
 *     in the warning message.
 */
void expectCanOverride(NodeTraversal t, Node n, JSType overridingType,
    JSType hiddenType, String propertyName, JSType ownerType) {
  if (!overridingType.canAssignTo(hiddenType)) {
    registerMismatch(overridingType, hiddenType,
        report(t.makeError(n, HIDDEN_PROPERTY_MISMATCH, propertyName,
          ownerType.toString(), hiddenType.toString(),
          overridingType.toString())));
  }
}
 
Example 17
Source File: Closure_6_TypeValidator_t.java    From coming with MIT License 3 votes vote down vote up
/**
 * Expect that the type of an argument matches the type of the parameter
 * that it's fulfilling.
 *
 * @param t The node traversal.
 * @param n The node to issue warnings on.
 * @param argType The type of the argument.
 * @param paramType The type of the parameter.
 * @param callNode The call node, to help with the warning message.
 * @param ordinal The argument ordinal, to help with the warning message.
 */
void expectArgumentMatchesParameter(NodeTraversal t, Node n, JSType argType,
    JSType paramType, Node callNode, int ordinal) {
  if (!argType.canAssignTo(paramType)) {
    mismatch(t, n,
        String.format("actual parameter %d of %s does not match " +
            "formal parameter", ordinal,
            getReadableJSTypeName(callNode.getFirstChild(), false)),
        argType, paramType);
  }
}
 
Example 18
Source File: Closure_6_TypeValidator_t.java    From coming with MIT License 3 votes vote down vote up
/**
 * Expect that the first type can be assigned to a symbol of the second
 * type.
 *
 * @param t The node traversal.
 * @param n The node to issue warnings on.
 * @param rightType The type on the RHS of the assign.
 * @param leftType The type of the symbol on the LHS of the assign.
 * @param msg An extra message for the mismatch warning, if necessary.
 * @return True if the types matched, false otherwise.
 */
boolean expectCanAssignTo(NodeTraversal t, Node n, JSType rightType,
    JSType leftType, String msg) {
  if (!rightType.canAssignTo(leftType)) {
    mismatch(t, n, msg, rightType, leftType);
    return false;
  }
  return true;
}