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;
 }
 private function getReturnTypeAsString(PhpType $type, array $importedNamespaces)
 {
     if ($type->isNullType() || $type->isNoType()) {
         return 'void';
     }
     return $type->getDocType($importedNamespaces);
 }
示例#3
0
 /**
  * Emulates a loose comparison between two types, and returns the result.
  *
  * The result can be true, false, or unknown:
  *
  *     - true: loose comparison of these types is always true
  *     - false: loose comparison of these types is always false
  *     - unknown: outcome depends on the actual values of these types
  *
  * @see http://php.net/manual/en/types.comparisons.php (table with loose comparison ==)
  *
  * @param PhpType $thisType
  * @param PhpType $thatType
  */
 public function testForEquality(PhpType $that)
 {
     if ($that->isAllType() || $that->isUnknownType() || $that->isNoResolvedType() || $this->isAllType() || $this->isUnknownType() || $this->isNoResolvedType()) {
         return TernaryValue::get('unknown');
     }
     if ($this->isNoType() || $that->isNoType()) {
         if ($this->isNoType() && $that->isNoType()) {
             return TernaryValue::get('true');
         }
         return TernaryValue::get('unknown');
     }
     $isThisNumeric = $this->isIntegerType() || $this->isDoubleType();
     $isThatNumeric = $that->isIntegerType() || $that->isDoubleType();
     if (($isThisNumeric || $this->isStringType()) && $that->isArrayType() || ($isThatNumeric || $that->isStringType()) && $this->isArrayType()) {
         return TernaryValue::get('false');
     }
     if ($this->isObjectType() ^ $that->isObjectType()) {
         return TernaryValue::get('false');
     }
     if ($that->isUnionType()) {
         return $that->testForEquality($this);
     }
     if ($this->isArrayType() && $that->isArrayType()) {
         // TODO: Maybe make this more sophisticated by looking at the key,
         //       and element types.
         return TernaryValue::get('unknown');
     }
     // If this is reached, then this base type does not have enough information to
     // make an informed decision, but the method should be overridden by a subtype
     // as this method eventually is never allowed to return null.
     return null;
 }