Skip to content

Commit

Permalink
Refactor RegexArrayShapeMatcher
Browse files Browse the repository at this point in the history
  • Loading branch information
staabm authored and ondrejmirtes committed Jul 28, 2024
1 parent 390fe08 commit cf1096d
Showing 1 changed file with 36 additions and 20 deletions.
56 changes: 36 additions & 20 deletions src/Type/Php/RegexArrayShapeMatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -293,26 +293,8 @@ private function buildArrayType(
$i = 0;
foreach ($captureGroups as $captureGroup) {
$isTrailingOptional = $i >= $countGroups - $trailingOptionals;
$groupValueType = $this->getValueType($captureGroup->getType(), $flags);

if (!$wasMatched->yes()) {
$optional = true;
} else {
if (!$isTrailingOptional) {
$optional = false;
if ($this->containsUnmatchedAsNull($flags) && !$captureGroup->isOptional()) {
$groupValueType = TypeCombinator::removeNull($groupValueType);
}
} elseif ($this->containsUnmatchedAsNull($flags)) {
$optional = false;
} else {
$optional = $captureGroup->isOptional();
}
}

if (!$isTrailingOptional && $captureGroup->isOptional() && !$this->containsUnmatchedAsNull($flags)) {
$groupValueType = TypeCombinator::union($groupValueType, new ConstantStringType(''));
}
$groupValueType = $this->createGroupValueType($captureGroup, $wasMatched, $flags, $isTrailingOptional);
$optional = $this->isGroupOptional($captureGroup, $wasMatched, $flags, $isTrailingOptional);

if ($captureGroup->isNamed()) {
$builder->setOffsetValueType(
Expand Down Expand Up @@ -346,6 +328,40 @@ private function buildArrayType(
return $builder->getArray();
}

private function isGroupOptional(RegexCapturingGroup $captureGroup, TrinaryLogic $wasMatched, int $flags, bool $isTrailingOptional): bool
{
if (!$wasMatched->yes()) {
$optional = true;
} else {
if (!$isTrailingOptional) {
$optional = false;
} elseif ($this->containsUnmatchedAsNull($flags)) {
$optional = false;
} else {
$optional = $captureGroup->isOptional();
}
}

return $optional;
}

private function createGroupValueType(RegexCapturingGroup $captureGroup, TrinaryLogic $wasMatched, int $flags, bool $isTrailingOptional): Type
{
$groupValueType = $this->getValueType($captureGroup->getType(), $flags);

if ($wasMatched->yes()) {
if (!$isTrailingOptional && $this->containsUnmatchedAsNull($flags) && !$captureGroup->isOptional()) {
$groupValueType = TypeCombinator::removeNull($groupValueType);
}
}

if (!$isTrailingOptional && !$this->containsUnmatchedAsNull($flags) && $captureGroup->isOptional()) {
$groupValueType = TypeCombinator::union($groupValueType, new ConstantStringType(''));
}

return $groupValueType;
}

private function containsUnmatchedAsNull(int $flags): bool
{
return ($flags & PREG_UNMATCHED_AS_NULL) !== 0 && (($flags & self::PREG_UNMATCHED_AS_NULL_ON_72_73) !== 0 || $this->phpVersion->supportsPregUnmatchedAsNull());
Expand Down

0 comments on commit cf1096d

Please sign in to comment.