/** * Tells the type system that {@code owner} may have a property named * {@code propertyName}. This allows the registry to keep track of what * types a property is defined upon. * * This is NOT the same as saying that {@code owner} must have a property * named type. ObjectType#hasProperty attempts to minimize false positives * ("if we're not sure, then don't type check this property"). The type * registry, on the other hand, should attempt to minimize false negatives * ("if this property is assigned anywhere in the program, it must * show up in the type registry"). */ public void registerPropertyOnType(String propertyName, JSType type) { UnionTypeBuilder typeSet = typesIndexedByProperty.get(propertyName); if (typeSet == null) { typeSet = new UnionTypeBuilder(this, PROPERTY_CHECKING_UNION_SIZE); typesIndexedByProperty.put(propertyName, typeSet); } typeSet.addAlternate(type); addReferenceTypeIndexedByProperty(propertyName, type); // Clear cached values that depend on typesIndexedByProperty. greatestSubtypeByProperty.remove(propertyName); }
private void addReferenceTypeIndexedByProperty( String propertyName, JSType type) { if (type instanceof ObjectType && ((ObjectType) type).hasReferenceName()) { Map<String, ObjectType> typeSet = eachRefTypeIndexedByProperty.computeIfAbsent(propertyName, k -> new LinkedHashMap<>()); ObjectType objType = (ObjectType) type; typeSet.put(objType.getReferenceName(), objType); } else if (type instanceof NamedType) { addReferenceTypeIndexedByProperty( propertyName, ((NamedType) type).getReferencedType()); } else if (type.isUnionType()) { for (JSType alternate : type.toMaybeUnionType().getAlternates()) { addReferenceTypeIndexedByProperty(propertyName, alternate); } } }
private void addReferenceTypeIndexedByProperty( String propertyName, JSType type) { if (type instanceof ObjectType && ((ObjectType) type).hasReferenceName()) { Map<String, ObjectType> typeSet = eachRefTypeIndexedByProperty.get(propertyName); if (typeSet == null) { typeSet = new LinkedHashMap<String, ObjectType>(); eachRefTypeIndexedByProperty.put(propertyName, typeSet); } ObjectType objType = (ObjectType) type; typeSet.put(objType.getReferenceName(), objType); } else if (type instanceof NamedType) { addReferenceTypeIndexedByProperty( propertyName, ((NamedType) type).getReferencedType()); } else if (type.isUnionType()) { for (JSType alternate : type.toMaybeUnionType().getAlternates()) { addReferenceTypeIndexedByProperty(propertyName, alternate); } } }
/** * Tells the type system that {@code owner} may have a property named * {@code propertyName}. This allows the registry to keep track of what * types a property is defined upon. * * This is NOT the same as saying that {@code owner} must have a property * named type. ObjectType#hasProperty attempts to minimize false positives * ("if we're not sure, then don't type check this property"). The type * registry, on the other hand, should attempt to minimize false negatives * ("if this property is assigned anywhere in the program, it must * show up in the type registry"). */ public void registerPropertyOnType(String propertyName, JSType type) { if (isObjectLiteralThatCanBeSkipped(type)) { type = getSentinelObjectLiteral(); } if (type.isUnionType()) { typesIndexedByProperty.putAll(propertyName, type.toMaybeUnionType().getAlternates()); } else { typesIndexedByProperty.put(propertyName, type); } addReferenceTypeIndexedByProperty(propertyName, type); // Clear cached values that depend on typesIndexedByProperty. greatestSubtypeByProperty.remove(propertyName); }