private function restrictByNumericType(PhpType $type = null, $outcome) { if ($outcome) { return $this->typeRegistry->getNativeType('numeric'); } if (null === $type) { return null; } // String is excluded here since not all strings are necessarily numeric. // So, even if the condition evaluates to false, we could technically // still have a string inside the if (just that it is not numeric). if ($type->isIntegerType() || $type->isDoubleType()) { return $this->typeRegistry->getNativeType('none'); } if ($type->isUnionType()) { // Again, we do not restrict by string as explained above. return $type->getRestrictedUnion($this->typeRegistry->createUnionType(array('integer', 'double'))); } if ($type->isAllType()) { return $this->typeRegistry->createUnionType(array('object', 'string', 'null', 'array', 'boolean')); } return $type; }
/** * 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; }