public function getCompositeType(array $types) { $types = $this->flattenComposedTypes($types); //Remove any redundant types: (\Iterator and \Traversable) becomes \Iterator /** @var $types IType[] */ foreach ($types as $outer => $outerType) { foreach ($types as $inner => $innerType) { if ($outer !== $inner && $innerType->isParentTypeOf($outerType)) { unset($types[$inner]); } } } if (count($types) === 0) { return $this->getNativeType(INativeType::TYPE_MIXED); } elseif (count($types) === 1) { return reset($types); } ksort($types, SORT_STRING); $typeId = TypeId::getComposite(array_keys($types)); if (!isset($this->compositeTypes[$typeId])) { $this->compositeTypes[$typeId] = $this->buildCompositeType($typeId, $types); } return $this->compositeTypes[$typeId]; }
public function testCompositeType() { $compositeType = $this->typeSystem->getType(TypeId::getComposite([TypeId::getObject('ArrayAccess'), TypeId::getObject('Countable')])); $indexer = $compositeType->getIndex(O\Expression::index(O\Expression::value([]), O\Expression::value('s'))); $this->assertEqualTypes($this->typeSystem->getObjectType('ArrayAccess'), $indexer->getSourceType()); $this->assertEqualsNativeType(INativeType::TYPE_MIXED, $indexer->getReturnType()); $method = $compositeType->getMethod(O\Expression::methodCall(O\Expression::value([]), O\Expression::value('offsetExists'))); $this->assertEqualTypes($this->typeSystem->getObjectType('ArrayAccess'), $method->getSourceType()); $this->assertEqualsNativeType(INativeType::TYPE_BOOL, $method->getReturnType()); $method = $compositeType->getMethod(O\Expression::methodCall(O\Expression::value([]), O\Expression::value('count'))); $this->assertEqualTypes($this->typeSystem->getObjectType('Countable'), $method->getSourceType()); $this->assertEqualsNativeType(INativeType::TYPE_INT, $method->getReturnType()); }