/**
  * 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;
 }
示例#2
0
 /** Gets the number of properties of this object. */
 @Override
 public int getPropertiesCount() {
   ObjectType implicitPrototype = getImplicitPrototype();
   if (implicitPrototype == null) {
     return this.properties.size();
   }
   int localCount = 0;
   for (String property : properties.keySet()) {
     if (!implicitPrototype.hasProperty(property)) {
       localCount++;
     }
   }
   return implicitPrototype.getPropertiesCount() + localCount;
 }
示例#3
0
  /** Determines if typeA is a subtype of typeB */
  static boolean isSubtype(ObjectType typeA, RecordType typeB) {
    // 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,
    //    2a) if the property of typeA is declared, it must be equal
    //        to the type of the property of typeB,
    //    2b) otherwise, it must be a subtype of the property of typeB.
    //
    // To figure out why this is true, consider the following pseudo-code:
    // /** @type {{a: (Object,null)}} */ var x;
    // /** @type {{a: !Object}} */ var y;
    // var z = {a: {}};
    // x.a = null;
    //
    // y cannot be assigned to x, because line 4 would violate y's declared
    // properties. But z can be assigned to x. Even though z and y are the
    // same type, the properties of z are inferred--and so an assignment
    // to the property of z would not violate any restrictions on it.
    for (String property : typeB.getOwnPropertyNames()) {
      if (!typeA.hasProperty(property)) {
        return false;
      }

      JSType propA = typeA.getPropertyType(property);
      JSType propB = typeB.getPropertyType(property);
      if (typeA.isPropertyTypeDeclared(property)) {
        // If one declared property isn't invariant,
        // then the whole record isn't covariant.
        if (!propA.isInvariant(propB)) {
          return false;
        }
      } else {
        // If one inferred property isn't a subtype,
        // then the whole record isn't covariant.
        if (!propA.isSubtype(propB)) {
          return false;
        }
      }
    }

    return true;
  }