@Override public JSType findPropertyType(String propertyName) { return hasProperty(propertyName) ? getPropertyType(propertyName) : null; }
@Override protected JSType findPropertyTypeWithoutConsideringTemplateTypes(String propertyName) { return hasProperty(propertyName) ? getPropertyType(propertyName) : null; }
public final ObjectType getTopDefiningInterface(String propertyName) { ObjectType foundType = null; if (hasProperty(propertyName)) { foundType = this; } for (ObjectType interfaceType : getCtorExtendedInterfaces()) { if (interfaceType.hasProperty(propertyName)) { foundType = interfaceType.getTopDefiningInterface(propertyName); } } return foundType; }
/** * Given an interface and a property, finds the top-most super interface * that has the property defined (including this interface). */ public static ObjectType getTopDefiningInterface(ObjectType type, String propertyName) { ObjectType foundType = null; if (type.hasProperty(propertyName)) { foundType = type; } for (ObjectType interfaceType : type.getCtorExtendedInterfaces()) { if (interfaceType.hasProperty(propertyName)) { foundType = getTopDefiningInterface(interfaceType, propertyName); } } return foundType; }
/** * Returns the type of the property with the given name if declared. Otherwise returns unknown. */ private JSType getPropertyTypeIfDeclared(@Nullable ObjectType objectType, String propertyName) { if (objectType != null && objectType.hasProperty(propertyName) && !objectType.isPropertyTypeInferred(propertyName)) { return objectType.getPropertyType(propertyName); } return getNativeType(UNKNOWN_TYPE); }
/** * Given a constructor or an interface type and a property, finds the top-most superclass that has * the property defined (including this constructor). */ public final ObjectType getTopMostDefiningType(String propertyName) { checkState(isConstructor() || isInterface()); checkArgument(getInstanceType().hasProperty(propertyName)); FunctionType ctor = this; if (isInterface()) { return getInstanceType().getTopDefiningInterface(propertyName); } ObjectType topInstanceType = null; do { topInstanceType = ctor.getInstanceType(); ctor = ctor.getSuperClassConstructor(); } while (ctor != null && ctor.getPrototype().hasProperty(propertyName)); return topInstanceType; }
/** * When a class has a stub for a property, and the property exists on a super interface, * use that type. */ private JSType getInheritedInterfacePropertyType(ObjectType obj, String propName) { if (obj != null && obj.isFunctionPrototypeType()) { FunctionType f = obj.getOwnerFunction(); for (ObjectType i : f.getImplementedInterfaces()) { if (i.hasProperty(propName)) { return i.getPropertyType(propName); } } } return null; }
/** * Given a constructor or an interface type and a property, finds the * top-most superclass that has the property defined (including this * constructor). */ public ObjectType getTopMostDefiningType(String propertyName) { Preconditions.checkState(isConstructor() || isInterface()); Preconditions.checkArgument(getInstanceType().hasProperty(propertyName)); FunctionType ctor = this; if (isInterface()) { return getTopDefiningInterface(getInstanceType(), propertyName); } ObjectType topInstanceType = null; do { topInstanceType = ctor.getInstanceType(); ctor = ctor.getSuperClassConstructor(); } while (ctor != null && ctor.getPrototype().hasProperty(propertyName)); return topInstanceType; }
/** Determines if typeA is a subtype of typeB */ private static boolean isSubtype(ObjectType typeA, RecordType typeB, ImplCache implicitImplCache, SubtypingMode subtypingMode) { // typeA is a subtype of record type typeB iff: // 1) typeA has all the properties declared in typeB. // 2) And for each property of typeB, its type must be // a super type of the corresponding property of typeA. for (String property : typeB.getOwnPropertyNames()) { if (!typeA.hasProperty(property)) { return false; } JSType propA = typeA.getPropertyType(property); JSType propB = typeB.getPropertyType(property); if (!propA.isSubtype(propB, implicitImplCache, subtypingMode)) { return false; } } return true; }
/** Determines if typeA is a subtype of typeB */ static boolean isSubtype(ObjectType typeA, RecordType typeB, ImplCache implicitImplCache) { // typeA is a subtype of record type typeB iff: // 1) typeA has all the properties declared in typeB. // 2) And for each property of typeB, its type must be // a super type of the corresponding property of typeA. for (String property : typeB.getOwnPropertyNames()) { if (!typeA.hasProperty(property)) { return false; } JSType propA = typeA.getPropertyType(property); JSType propB = typeB.getPropertyType(property); if (!propA.isSubtype(propB, implicitImplCache)) { return false; } } return true; }
private void mismatch(Node n, String msg, JSType found, JSType required) { if (!found.isSubtype(required, this.subtypingMode)) { Set<String> missing = null; Set<String> mismatch = null; if (required.isStructuralType()) { missing = new TreeSet<>(); mismatch = new TreeSet<>(); ObjectType requiredObject = required.toMaybeObjectType(); ObjectType foundObject = found.toMaybeObjectType(); if (requiredObject != null && foundObject != null) { for (String property : requiredObject.getPropertyNames()) { JSType propRequired = requiredObject.getPropertyType(property); boolean hasProperty = foundObject.hasProperty(property); if (!propRequired.isExplicitlyVoidable() || hasProperty) { if (hasProperty) { if (!foundObject .getPropertyType(property) .isSubtype(propRequired, subtypingMode)) { mismatch.add(property); } } else { missing.add(property); } } } } } registerMismatchAndReport(n, TYPE_MISMATCH_WARNING, msg, found, required, missing, mismatch); } }
private static boolean isStructuralSubtypeHelper( ObjectType typeA, ObjectType typeB, ImplCache implicitImplCache, SubtypingMode subtypingMode) { // typeA is a subtype of record type typeB iff: // 1) typeA has all the non-optional properties declared in typeB. // 2) And for each property of typeB, its type must be // a super type of the corresponding property of typeA. for (String property : typeB.getPropertyNames()) { JSType propB = typeB.getPropertyType(property); if (!typeA.hasProperty(property)) { // Currently, any type that explicitly includes undefined (eg, `?|undefined`) is optional. if (propB.isExplicitlyVoidable()) { continue; } return false; } JSType propA = typeA.getPropertyType(property); if (!propA.isSubtype(propB, implicitImplCache, subtypingMode)) { return false; } } return true; }
private static boolean isStructuralSubtypeHelper( ObjectType typeA, ObjectType typeB, ImplCache implicitImplCache) { // typeA is a subtype of record type typeB iff: // 1) typeA has all the non-optional properties declared in typeB. // 2) And for each property of typeB, its type must be // a super type of the corresponding property of typeA. for (String property : typeB.getPropertyNames()) { JSType propB = typeB.getPropertyType(property); if (!typeA.hasProperty(property)) { // Currently, any type that explicitly includes undefined (eg, `?|undefined`) is optional. if (propB.isExplicitlyVoidable()) { continue; } return false; } JSType propA = typeA.getPropertyType(property); if (!propA.isSubtype(propB, implicitImplCache)) { return false; } } return true; }
/** * Defines a property whose type is inferred. * @param propertyName the property's name * @param type the type * @param propertyNode the node corresponding to the inferred definition of * property that might later be accessed using {@code getPropertyNode}. */ public final boolean defineInferredProperty(String propertyName, JSType type, Node propertyNode) { if (hasProperty(propertyName)) { if (isPropertyTypeDeclared(propertyName)) { // We never want to hide a declared property with an inferred property. return true; } JSType originalType = getPropertyType(propertyName); type = originalType == null ? type : originalType.getLeastSupertype(type); } boolean result = defineProperty(propertyName, type, true, propertyNode); // All property definitions go through this method // or defineDeclaredProperty. Because the properties defined an an // object can affect subtyping, it's slightly more efficient // to register this after defining the property. registry.registerPropertyOnType(propertyName, this); return result; }
/** * Defines a property whose type is inferred. * @param propertyName the property's name * @param type the type * @param propertyNode the node corresponding to the inferred definition of * property that might later be accessed using {@code getPropertyNode}. */ public final boolean defineInferredProperty(String propertyName, JSType type, Node propertyNode) { if (hasProperty(propertyName)) { if (isPropertyTypeDeclared(propertyName)) { // We never want to hide a declared property with an inferred property. return true; } JSType originalType = getPropertyType(propertyName); type = originalType == null ? type : originalType.getLeastSupertype(type); } boolean result = defineProperty(propertyName, type, true, propertyNode); // All property definitions go through this method // or defineDeclaredProperty. Because the properties defined an an // object can affect subtyping, it's slightly more efficient // to register this after defining the property. registry.registerPropertyOnType(propertyName, this); return result; }
/** * @param constructor A constructor function defined by a call, which may be a mixin application. * The constructor implements at least one interface. If the constructor is missing some * properties of the inherited interfaces, this method declares these properties. */ private static void addMissingInterfaceProperties(JSType constructor) { if (constructor != null && constructor.isConstructor()) { FunctionType f = constructor.toMaybeFunctionType(); ObjectType proto = f.getPrototype(); for (ObjectType interf : f.getImplementedInterfaces()) { for (String pname : interf.getPropertyNames()) { if (!proto.hasProperty(pname)) { proto.defineDeclaredProperty(pname, interf.getPropertyType(pname), null); } } } } }
ObjectType objectType = ObjectType.cast(jsType); if (objectType != null) { hasProperty = objectType.hasProperty(propertyName);
ObjectType objectType = ObjectType.cast(jsType); if (objectType != null) { hasProperty = objectType.hasProperty(propertyName);
if (!objectType.hasProperty(propName) || objectType.isEquivalentTo( typeRegistry.getNativeType(UNKNOWN_TYPE))) {
if (prototype != null && prototype.hasProperty(propertyName)) { initializedConstantProperties.put(prototype, propertyName);