public function addAlternate(PhpType $alternate)
 {
     // build() returns the bottom type by default, so we can
     // just bail out early here.
     if ($alternate->isNoType()) {
         return $this;
     }
     $this->isAllType = $this->isAllType || $alternate->isAllType();
     $isAlternateUnknown = $alternate instanceof UnknownType;
     // instanceof is desired here
     $this->isNativeUnknownType = $this->isNativeUnknownType || $isAlternateUnknown;
     if ($isAlternateUnknown) {
         $this->areAllUnknownsChecked = $this->areAllUnknownsChecked && $alternate->isChecked();
     }
     if (!$this->isAllType && !$this->isNativeUnknownType) {
         if ($alternate->isUnionType()) {
             $union = $alternate->toMaybeUnionType();
             foreach ($union->getAlternates() as $unionAlt) {
                 $this->addAlternate($unionAlt);
             }
         } else {
             // Look through the alternates we've got so far,
             // and check if any of them are duplicates of
             // one another.
             foreach ($this->alternates as $index => $current) {
                 // The Unknown type is special in that we cannot use our
                 // subtype based check, but need to check for equality to
                 // avoid duplicates, and not remove all other alternates.
                 if ($alternate->isUnknownType()) {
                     if ($alternate->equals($current)) {
                         return $this;
                     }
                     continue;
                 }
                 // Check if we already have a more general type in the union.
                 // Then, we do not add this alternate.
                 if ($alternate->isSubTypeOf($current)) {
                     return $this;
                 }
                 // Check if we have a subtype of the passed alternate. Then,
                 // we remove that alternate in favor of the newly passed one.
                 if ($current->isSubTypeOf($alternate)) {
                     unset($this->alternates[$index]);
                 }
             }
             $this->alternates[] = $alternate;
         }
     }
     return $this;
 }
 /**
  * Returns the array type contained in the given type, or null if no array
  * type is available.
  *
  * @param PhpType|null $type
  *
  * @return ArrayType|null
  */
 private function getContainedArrayType(PhpType $type = null)
 {
     if (null === $type) {
         return null;
     }
     if ($type->isArrayType()) {
         return $type;
     }
     if (!$type->isUnionType()) {
         return null;
     }
     foreach ($type->getAlternates() as $alt) {
         if ($alt->isArrayType()) {
             return $alt;
         }
     }
     return null;
 }
 private function restrictByCallable(PhpType $type = null, $outcome)
 {
     if (null === $type) {
         return $outcome ? $this->typeRegistry->getNativeType('callable') : null;
     }
     if ($outcome) {
         if ($type->isUnknownType() || $type->isAllType()) {
             return $this->typeRegistry->getNativeType('callable');
         }
         if ($type->isUnionType()) {
             $types = array();
             foreach ($type->getAlternates() as $altType) {
                 if ($altType->canBeCalled()) {
                     $types[] = $altType;
                 }
             }
             return $this->typeRegistry->createUnionType($types);
         }
         return $type->canBeCalled() ? $type : $this->typeRegistry->getNativeType('none');
     }
     if ($type->isCallableType()) {
         return $this->typeRegistry->getNativeType('none');
     }
     if ($type->isUnionType()) {
         $types = array();
         foreach ($type->getAlternates() as $altType) {
             if ($altType->isCallableType()) {
                 continue;
             }
             $types[] = $altType;
         }
         return $this->typeRegistry->createUnionType($types);
     }
     return $type;
 }
 private function isNullableObjectType(PhpType $type)
 {
     if (!$type->isUnionType()) {
         return false;
     }
     foreach ($type->getAlternates() as $alt) {
         if (null === $alt->toMaybeObjectType() && !$alt->isNullType()) {
             return false;
         }
     }
     return true;
 }
示例#5
0
 /**
  * Computes the restricted types given a non-successful shallow equality comparison.
  *
  * @return PhpType[] The first element is the restricted this type, the second element is the restricted type of the
  *                   passed type.
  */
 public function getTypesUnderShallowInequality(PhpType $that)
 {
     // union types
     if ($that->isUnionType()) {
         $p = $that->toMaybeUnionType()->getTypesUnderShallowInequality($this);
         return array($p[1], $p[0]);
     }
     // Other types.
     // There are only two types whose shallow inequality is deterministically
     // true -- null and false. We can just enumerate them. Should we ever add
     // a true type, this needs to be added here as well.
     if ($this->isNullType() && $that->isNullType()) {
         return array(null, null);
     }
     if ($this->isFalse() && $that->isFalse()) {
         return array(null, null);
     }
     return array($this, $that);
 }