Skip to content

Commit

Permalink
Simplify by not using TypeTraverser
Browse files Browse the repository at this point in the history
  • Loading branch information
herndlm committed Dec 26, 2024
1 parent b8309fd commit fc54113
Showing 1 changed file with 55 additions and 51 deletions.
106 changes: 55 additions & 51 deletions src/Analyser/TypeSpecifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -988,71 +988,75 @@ private function specifyTypesForCountFuncCall(
return null;
}

$resultType = TypeTraverser::map($type, static function (Type $type, callable $traverse) use ($sizeType, $context) {
if ($type instanceof UnionType) {
return $traverse($type);
}

$isSizeSuperTypeOfArraySize = $sizeType->isSuperTypeOf($type->getArraySize());
if ($isSizeSuperTypeOfArraySize->no()) {
return new NeverType();
$resultTypes = [];
$innerTypes = $type instanceof UnionType ? $type->getTypes() : [$type];
foreach ($innerTypes as $innerType) {
$isSizeSuperTypeOfArraySize = $sizeType->isSuperTypeOf($innerType->getArraySize());
if ($context->truthy() && $isSizeSuperTypeOfArraySize->no()) {
$resultTypes[] = new ConstantArrayType([], []);
continue;
}
if ($context->falsey() && $isSizeSuperTypeOfArraySize->maybe()) {
return new NeverType();
if ($context->falsey() && !$isSizeSuperTypeOfArraySize->yes()) {
continue;
}

if ($type->isList()->yes()) {
if (
$sizeType instanceof ConstantIntegerType
&& $sizeType->getValue() < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT
) {
// turn optional offsets non-optional
$valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty();
for ($i = 0; $i < $sizeType->getValue(); $i++) {
$offsetType = new ConstantIntegerType($i);
$valueTypesBuilder->setOffsetValueType($offsetType, $type->getOffsetValueType($offsetType));
}
return $valueTypesBuilder->getArray();
if (
$innerType->isList()->yes()
&& $sizeType instanceof ConstantIntegerType
&& $sizeType->getValue() < ConstantArrayTypeBuilder::ARRAY_COUNT_LIMIT
) {
// turn optional offsets non-optional
$valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty();
for ($i = 0; $i < $sizeType->getValue(); $i++) {
$offsetType = new ConstantIntegerType($i);
$valueTypesBuilder->setOffsetValueType($offsetType, $innerType->getOffsetValueType($offsetType));
}
$resultTypes[] = $valueTypesBuilder->getArray();
continue;
}

if (
$sizeType instanceof IntegerRangeType
&& $sizeType->getMin() !== null
) {
// turn optional offsets non-optional
$valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty();
for ($i = 0; $i < $sizeType->getMin(); $i++) {
if (
$innerType->isList()->yes()
&& $sizeType instanceof IntegerRangeType
&& $sizeType->getMin() !== null
) {
// turn optional offsets non-optional
$valueTypesBuilder = ConstantArrayTypeBuilder::createEmpty();
for ($i = 0; $i < $sizeType->getMin(); $i++) {
$offsetType = new ConstantIntegerType($i);
$valueTypesBuilder->setOffsetValueType($offsetType, $innerType->getOffsetValueType($offsetType));
}
if ($sizeType->getMax() !== null) {
for ($i = $sizeType->getMin(); $i < $sizeType->getMax(); $i++) {
$offsetType = new ConstantIntegerType($i);
$valueTypesBuilder->setOffsetValueType($offsetType, $type->getOffsetValueType($offsetType));
$valueTypesBuilder->setOffsetValueType($offsetType, $innerType->getOffsetValueType($offsetType), true);
}
if ($sizeType->getMax() !== null) {
for ($i = $sizeType->getMin(); $i < $sizeType->getMax(); $i++) {
$offsetType = new ConstantIntegerType($i);
$valueTypesBuilder->setOffsetValueType($offsetType, $type->getOffsetValueType($offsetType), true);
}
} elseif ($type->isConstantArray()->yes()) {
for ($i = $sizeType->getMin();; $i++) {
$offsetType = new ConstantIntegerType($i);
$hasOffset = $type->hasOffsetValueType($offsetType);
if ($hasOffset->no()) {
break;
}
$valueTypesBuilder->setOffsetValueType($offsetType, $type->getOffsetValueType($offsetType), !$hasOffset->yes());
} elseif ($innerType->isConstantArray()->yes()) {
for ($i = $sizeType->getMin();; $i++) {
$offsetType = new ConstantIntegerType($i);
$hasOffset = $innerType->hasOffsetValueType($offsetType);
if ($hasOffset->no()) {
break;
}
} else {
return TypeCombinator::intersect($type, new NonEmptyArrayType());
$valueTypesBuilder->setOffsetValueType($offsetType, $innerType->getOffsetValueType($offsetType), !$hasOffset->yes());
}

return $valueTypesBuilder->getArray();
} else {
$resultTypes[] = TypeCombinator::intersect($innerType, new NonEmptyArrayType());
continue;
}

return $context->truthy() ? $type : new NeverType();
$resultTypes[] = $valueTypesBuilder->getArray();
continue;
}

return $context->truthy() ? TypeCombinator::intersect($type, new NonEmptyArrayType()) : new NeverType();
});
if (!$context->truthy()) {
continue;
}

$resultTypes[] = $innerType;
}

return $this->create($countFuncCall->getArgs()[0]->value, $resultType, $context, $scope)->setRootExpr($rootExpr);
return $this->create($countFuncCall->getArgs()[0]->value, TypeCombinator::union(...$resultTypes), $context, $scope)->setRootExpr($rootExpr);
}

private function specifyTypesForConstantBinaryExpression(
Expand Down

0 comments on commit fc54113

Please sign in to comment.