From e9a7456091cb105a3636c8e1ed89a24193fbedee Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sat, 27 Jul 2024 21:59:52 +0200 Subject: [PATCH] Refactor RegexArrayShapeMatcher --- src/Type/Php/RegexArrayShapeMatcher.php | 56 ++++++++++++++++--------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/src/Type/Php/RegexArrayShapeMatcher.php b/src/Type/Php/RegexArrayShapeMatcher.php index 3e65133284..5a491db52f 100644 --- a/src/Type/Php/RegexArrayShapeMatcher.php +++ b/src/Type/Php/RegexArrayShapeMatcher.php @@ -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( @@ -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());