Skip to content

Commit

Permalink
RegexArrayShapeMatcher - Fix PREG_UNMATCHED_AS_NULL with optional lea…
Browse files Browse the repository at this point in the history
…ding groups
  • Loading branch information
staabm authored Jul 14, 2024
1 parent 8fad6d5 commit 0f3622a
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/Type/Php/RegexArrayShapeMatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ private function buildArrayType(
} else {
if ($i < $countGroups - $trailingOptionals) {
$optional = false;
if ($this->containsUnmatchedAsNull($flags)) {
if ($this->containsUnmatchedAsNull($flags) && !$captureGroup->isOptional()) {
$groupValueType = TypeCombinator::removeNull($groupValueType);
}
} elseif ($this->containsUnmatchedAsNull($flags)) {
Expand Down
36 changes: 36 additions & 0 deletions tests/PHPStan/Analyser/nsrt/bug-11311.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,39 @@ function unmatchedAsNullWithOptionalGroup(string $s): void {
assertType('array{}|array{string, string|null}', $matches);
}

function bug11331a(string $url):void {
// group a is actually optional as the entire (?:...) around it is optional
if (preg_match('{^
(?:
(?<a>.+)
)?
(?<b>.+)}mix', $url, $matches, PREG_UNMATCHED_AS_NULL)) {
assertType('array{0: string, a: string|null, 1: string|null, b: string, 2: string}', $matches);
}
}

function bug11331b(string $url):void {
if (preg_match('{^
(?:
(?<a>.+)
)?
(?<b>.+)?}mix', $url, $matches, PREG_UNMATCHED_AS_NULL)) {
assertType('array{0: string, a: string|null, 1: string|null, b: string|null, 2: string|null}', $matches);
}
}

function bug11331c(string $url):void {
if (preg_match('{^
(?:
(?:https?|git)://([^/]+)/ (?# group 1 here can be null if group 2 matches)
| (?# the alternation making it so that only either should match)
git@([^:]+):/? (?# group 2 here can be null if group 1 matches)
)
([^/]+)
/
([^/]+?)
(?:\.git|/)?
$}x', $url, $matches, PREG_UNMATCHED_AS_NULL)) {
assertType('array{string, string|null, string|null, string, string}', $matches);
}
}

0 comments on commit 0f3622a

Please sign in to comment.