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; }
public function isSubtypeOf(PhpType $that) { if (PhpType::isSubTypeOf($that)) { return true; } if ($that->isNoObjectType()) { return true; } if ($that->isCallableType() && (!$this->isNormalized() || $this->hasMethod('__invoke'))) { return true; } if (false === $that->isObjectType()) { return false; } if (false === $this->isNormalized()) { return true; } if ($that->isInterface()) { $name = strtolower($that->toMaybeObjectType()->getName()); foreach ($this->extendedInterfaces as $iName) { if ($name === strtolower($iName)) { return true; } } return false; } if ($that instanceof ProxyObjectType) { $name = strtolower($that->getReferenceName()); foreach ($this->extendedInterfaces as $iName) { if ($name === strtolower($iName)) { return true; } } return false; } return false; }
public function isSubTypeOf(PhpType $that) { if (PhpType::isSubTypeOf($that)) { return true; } if ($that->isNoObjectType()) { return true; } if ($that->isCallableType()) { return true; } if (false === $that->isObjectType()) { return false; } if (false === $this->isNormalized()) { return true; } if ($that->isInterface()) { $name = strtolower($that->toMaybeObjectType()->getName()); foreach ($this->implementedInterfaces as $iName) { if ($name === strtolower($iName)) { return true; } } return false; } // means it is a normal class if ($that->isClass()) { $name = strtolower($that->toMaybeObjectType()->getName()); foreach ($this->superClasses as $sName) { if ($name === strtolower($sName)) { return true; } } return false; } if ($that instanceof ProxyObjectType) { $name = strtolower($that->getReferenceName()); foreach ($this->implementedInterfaces as $iName) { if ($name === strtolower($iName)) { return true; } } foreach ($this->superClasses as $sName) { if ($name === strtolower($sName)) { return true; } } return false; } return false; }