// We never infer properties as optional on loose objects,
  // and we don't warn about possibly inexistent properties.
  boolean isLooseSubtypeOf(ObjectType other) {
    Preconditions.checkState(isLoose || other.isLoose);
    if (other == TOP_OBJECT) {
      return true;
    }

    if (!isLoose) {
      if (!objectKind.isSubtypeOf(other.objectKind)) {
        return false;
      }
      for (String pname : other.props.keySet()) {
        QualifiedName qname = new QualifiedName(pname);
        if (!mayHaveProp(qname) || !getProp(qname).isSubtypeOf(other.getProp(qname))) {
          return false;
        }
      }
    } else { // this is loose, other may be loose
      for (String pname : props.keySet()) {
        QualifiedName qname = new QualifiedName(pname);
        if (other.mayHaveProp(qname) && !getProp(qname).isSubtypeOf(other.getProp(qname))) {
          return false;
        }
      }
    }

    if (other.fn == null) {
      return this.fn == null || other.isLoose();
    } else if (this.fn == null) {
      return isLoose;
    }
    return fn.isLooseSubtypeOf(other.fn);
  }
예제 #2
0
 public boolean mayHaveProp(QualifiedName qname) {
   if (objs == null) {
     return false;
   }
   for (ObjectType o : objs) {
     if (o.mayHaveProp(qname)) {
       return true;
     }
   }
   return false;
 }
예제 #3
0
 public JSType getProp(QualifiedName qname) {
   if (isBottom() || isUnknown()) {
     return UNKNOWN;
   }
   Preconditions.checkState(objs != null);
   JSType ptype = BOTTOM;
   for (ObjectType o : objs) {
     if (o.mayHaveProp(qname)) {
       ptype = join(ptype, o.getProp(qname));
     }
   }
   if (ptype.isBottom()) {
     return null;
   }
   return ptype;
 }