-
Notifications
You must be signed in to change notification settings - Fork 460
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement array shapes for
preg_match()
$matches
by-ref parameter
- Loading branch information
Showing
26 changed files
with
807 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
--- Grammar.pp 2024-05-18 12:15:53 | ||
+++ Grammar.pp.fix 2024-05-18 12:15:05 | ||
@@ -109,7 +109,7 @@ | ||
// Please, see PCRESYNTAX(3), General Category properties, PCRE special category | ||
// properties and script names for \p{} and \P{}. | ||
%token character_type \\([CdDhHNRsSvVwWX]|[pP]{[^}]+}) | ||
-%token anchor \\(bBAZzG)|\^|\$ | ||
+%token anchor \\([bBAZzG])|\^|\$ | ||
%token match_point_reset \\K | ||
%token literal \\.|. | ||
|
||
@@ -168,7 +168,7 @@ | ||
::negative_class_:: #negativeclass | ||
| ::class_:: | ||
) | ||
- ( range() | literal() )+ | ||
+ ( <class_> | range() | literal() )+ | ||
::_class:: | ||
|
||
#range: | ||
@@ -178,7 +178,7 @@ | ||
capturing() | ||
| literal() | ||
|
||
-capturing: | ||
+#capturing: | ||
::comment_:: <comment>? ::_comment:: #comment | ||
| ( | ||
::named_capturing_:: <capturing_name> ::_named_capturing:: #namedcapturing | ||
@@ -191,6 +191,7 @@ | ||
|
||
literal: | ||
<character> | ||
+ | <range> | ||
| <dynamic_character> | ||
| <character_type> | ||
| <anchor> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
<?php declare(strict_types = 1); | ||
|
||
namespace PHPStan\Type\Php; | ||
|
||
use PhpParser\Node\Expr\FuncCall; | ||
use PHPStan\Analyser\Scope; | ||
use PHPStan\Reflection\FunctionReflection; | ||
use PHPStan\Reflection\ParameterReflection; | ||
use PHPStan\TrinaryLogic; | ||
use PHPStan\Type\FunctionParameterOutTypeExtension; | ||
use PHPStan\Type\Type; | ||
use function in_array; | ||
use function strtolower; | ||
|
||
final class PregMatchParameterOutTypeExtension implements FunctionParameterOutTypeExtension | ||
{ | ||
|
||
public function __construct( | ||
private RegexArrayShapeMatcher $regexShapeMatcher, | ||
) | ||
{ | ||
} | ||
|
||
public function isFunctionSupported(FunctionReflection $functionReflection, ParameterReflection $parameter): bool | ||
{ | ||
return in_array(strtolower($functionReflection->getName()), ['preg_match'], true) && $parameter->getName() === 'matches'; | ||
} | ||
|
||
public function getParameterOutTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $funcCall, ParameterReflection $parameter, Scope $scope): ?Type | ||
{ | ||
$args = $funcCall->getArgs(); | ||
$patternArg = $args[0] ?? null; | ||
$matchesArg = $args[2] ?? null; | ||
$flagsArg = $args[3] ?? null; | ||
|
||
if ( | ||
$patternArg === null || $matchesArg === null | ||
) { | ||
return null; | ||
} | ||
|
||
$patternType = $scope->getType($patternArg->value); | ||
$flagsType = null; | ||
if ($flagsArg !== null) { | ||
$flagsType = $scope->getType($flagsArg->value); | ||
} | ||
|
||
return $this->regexShapeMatcher->matchType($patternType, $flagsType, TrinaryLogic::createMaybe()); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
<?php declare(strict_types = 1); | ||
|
||
namespace PHPStan\Type\Php; | ||
|
||
use PhpParser\Node\Expr\FuncCall; | ||
use PHPStan\Analyser\Scope; | ||
use PHPStan\Analyser\SpecifiedTypes; | ||
use PHPStan\Analyser\TypeSpecifier; | ||
use PHPStan\Analyser\TypeSpecifierAwareExtension; | ||
use PHPStan\Analyser\TypeSpecifierContext; | ||
use PHPStan\Reflection\FunctionReflection; | ||
use PHPStan\TrinaryLogic; | ||
use PHPStan\Type\FunctionTypeSpecifyingExtension; | ||
use function in_array; | ||
use function strtolower; | ||
|
||
final class PregMatchTypeSpecifyingExtension implements FunctionTypeSpecifyingExtension, TypeSpecifierAwareExtension | ||
{ | ||
|
||
private TypeSpecifier $typeSpecifier; | ||
|
||
public function __construct( | ||
private RegexArrayShapeMatcher $regexShapeMatcher, | ||
) | ||
{ | ||
} | ||
|
||
public function setTypeSpecifier(TypeSpecifier $typeSpecifier): void | ||
{ | ||
$this->typeSpecifier = $typeSpecifier; | ||
} | ||
|
||
public function isFunctionSupported(FunctionReflection $functionReflection, FuncCall $node, TypeSpecifierContext $context): bool | ||
{ | ||
return in_array(strtolower($functionReflection->getName()), ['preg_match'], true) && !$context->null(); | ||
} | ||
|
||
public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes | ||
{ | ||
$args = $node->getArgs(); | ||
$patternArg = $args[0] ?? null; | ||
$matchesArg = $args[2] ?? null; | ||
$flagsArg = $args[3] ?? null; | ||
|
||
if ( | ||
$patternArg === null || $matchesArg === null | ||
) { | ||
return new SpecifiedTypes(); | ||
} | ||
|
||
$patternType = $scope->getType($patternArg->value); | ||
$flagsType = null; | ||
if ($flagsArg !== null) { | ||
$flagsType = $scope->getType($flagsArg->value); | ||
} | ||
|
||
$matchedType = $this->regexShapeMatcher->matchType($patternType, $flagsType, TrinaryLogic::createFromBoolean($context->true())); | ||
if ($matchedType === null) { | ||
return new SpecifiedTypes(); | ||
} | ||
|
||
$overwrite = false; | ||
if ($context->false()) { | ||
$overwrite = true; | ||
$context = $context->negate(); | ||
} | ||
|
||
return $this->typeSpecifier->create( | ||
$matchesArg->value, | ||
$matchedType, | ||
$context, | ||
$overwrite, | ||
$scope, | ||
$node, | ||
); | ||
} | ||
|
||
} |
Oops, something went wrong.