@Override public TernaryValue testForEquality(JSType that) { TernaryValue result = super.testForEquality(that); if (result != null) { return result; } if (that.canCastTo(getNativeType(SYMBOL_VALUE_OR_OBJECT_TYPE))) { return UNKNOWN; } return FALSE; }
@Override public boolean matches(Node node, NodeMetadata metadata) { // TODO(mknichel): Figure out which node is the best to return for this // function: the GETPROP node, or the ASSIGN node when the property is // being assigned to. // TODO(mknichel): Support matching: // foo.prototype = { // bar: 1 // }; Node firstChild = node.getFirstChild(); if (node.isGetProp() && firstChild.isGetProp() && firstChild.getLastChild().isString() && "prototype".equals(firstChild.getLastChild().getString())) { JSType fnJsType = getJsType(metadata, JSTypeNative.FUNCTION_FUNCTION_TYPE); JSType jsType = node.getJSType(); if (jsType == null) { return false; } else if (requireFunctionType) { return jsType.canCastTo(fnJsType); } else { return !jsType.canCastTo(fnJsType); } } return false; } };
private static boolean typesAreRelated(JSType expected, JSType actual) { if (actual.isConstructor() && expected.isConstructor()) { // All constructors can cast to one another, even if they're incompatible. // If both types are constructors then compare the instance types instead. actual = actual.toMaybeFunctionType().getInstanceType(); expected = expected.toMaybeFunctionType().getInstanceType(); } actual = firstNonNull(actual.autobox(), actual); return actual.canCastTo(expected); }
@Override void considerPossibleReferenceInternal(Node possiblyReferencingNode) { if (possiblyReferencingNode.isName()) { // A matching NAME node must be a reference (there's no need to check that the referenced // Var is global, since local variables have all been renamed by normalization). isRemovable = false; } else if (possiblyReferencingNode.isGetProp()) { // Does the owner have type information? If so then this is a reference only if the owner // could be the global 'this' type. Absent type information, just always assume it might be. JSType ownerType = possiblyReferencingNode.getFirstChild().getJSType(); if (ownerType == null || ownerType.canCastTo( compiler.getTypeRegistry().getNativeType(JSTypeNative.GLOBAL_THIS))) { isRemovable = false; } } } }
/** * Expect that the first type can be cast to the second type. The first type * must have some relationship with 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 castType, JSType type) { if (!type.canCastTo(castType)) { registerMismatch(type, castType, report(t.makeError(n, INVALID_CAST, type.toString(), castType.toString()))); } else if (!type.isSubtypeWithoutStructuralTyping(castType)){ recordStructuralInterfaceUses(type, castType); } }
/** * Expect that the first type can be cast to the second type. The first type * must have some relationship with the second. * * @param t The node traversal. * @param n The node where warnings should point. * @param targetType The type being cast to. * @param sourceType The type being cast from. */ void expectCanCast(NodeTraversal t, Node n, JSType targetType, JSType sourceType) { if (!sourceType.canCastTo(targetType)) { registerMismatch( sourceType, targetType, report(t.makeError(n, INVALID_CAST, sourceType.toString(), targetType.toString()))); } else if (!sourceType.isSubtypeWithoutStructuralTyping(targetType)){ TypeMismatch.recordImplicitInterfaceUses( this.implicitInterfaceUses, n, sourceType, targetType); } }