mirror of
https://github.com/danog/psalm.git
synced 2024-11-27 04:45:20 +01:00
Merge pull request #7027 from rarila/issue-6914
This commit is contained in:
commit
28c4f86993
@ -10273,7 +10273,7 @@ return [
|
||||
'preg_filter' => ['null|string|string[]', 'pattern'=>'mixed', 'replacement'=>'mixed', 'subject'=>'mixed', 'limit='=>'int', '&w_count='=>'int'],
|
||||
'preg_grep' => ['array|false', 'pattern'=>'string', 'array'=>'array', 'flags='=>'int'],
|
||||
'preg_last_error' => ['int'],
|
||||
'preg_match' => ['int|false', 'pattern'=>'string', 'subject'=>'string', '&w_matches='=>'string[]', 'flags='=>'0|', 'offset='=>'int'],
|
||||
'preg_match' => ['int|false', 'pattern'=>'string', 'subject'=>'string', '&w_matches='=>'string[]', 'flags='=>'0', 'offset='=>'int'],
|
||||
'preg_match\'1' => ['int|false', 'pattern'=>'string', 'subject'=>'string', '&w_matches='=>'array', 'flags='=>'int', 'offset='=>'int'],
|
||||
'preg_match_all' => ['int|false', 'pattern'=>'string', 'subject'=>'string', '&w_matches='=>'array', 'flags='=>'int', 'offset='=>'int'],
|
||||
'preg_quote' => ['string', 'str'=>'string', 'delimiter='=>'string'],
|
||||
|
@ -14454,7 +14454,7 @@ return [
|
||||
'preg_filter' => ['null|string|string[]', 'pattern'=>'mixed', 'replacement'=>'mixed', 'subject'=>'mixed', 'limit='=>'int', '&w_count='=>'int'],
|
||||
'preg_grep' => ['array|false', 'pattern'=>'string', 'array'=>'array', 'flags='=>'int'],
|
||||
'preg_last_error' => ['int'],
|
||||
'preg_match' => ['int|false', 'pattern'=>'string', 'subject'=>'string', '&w_matches='=>'string[]', 'flags='=>'0|', 'offset='=>'int'],
|
||||
'preg_match' => ['int|false', 'pattern'=>'string', 'subject'=>'string', '&w_matches='=>'string[]', 'flags='=>'0', 'offset='=>'int'],
|
||||
'preg_match\'1' => ['int|false', 'pattern'=>'string', 'subject'=>'string', '&w_matches='=>'array', 'flags='=>'int', 'offset='=>'int'],
|
||||
'preg_match_all' => ['int|false', 'pattern'=>'string', 'subject'=>'string', '&w_matches='=>'array', 'flags='=>'int', 'offset='=>'int'],
|
||||
'preg_quote' => ['string', 'str'=>'string', 'delimiter='=>'string'],
|
||||
|
@ -259,14 +259,14 @@ class CodeLocation
|
||||
}
|
||||
|
||||
if (preg_match($regex, $preview_snippet, $matches, PREG_OFFSET_CAPTURE)) {
|
||||
if (!isset($matches[1]) || (int)$matches[1][1] === -1) {
|
||||
if (!isset($matches[1]) || $matches[1][1] === -1) {
|
||||
throw new \LogicException(
|
||||
"Failed to match anything to 1st capturing group, "
|
||||
. "or regex doesn't contain 1st capturing group, regex type " . $this->regex_type
|
||||
);
|
||||
}
|
||||
$this->selection_start = $this->selection_start + (int)$matches[1][1];
|
||||
$this->selection_end = $this->selection_start + strlen((string)$matches[1][0]);
|
||||
$this->selection_start = $this->selection_start + $matches[1][1];
|
||||
$this->selection_end = $this->selection_start + strlen($matches[1][0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -635,7 +635,7 @@ class ArgumentsAnalyzer
|
||||
}
|
||||
}
|
||||
|
||||
if ($method_id === 'preg_match_all' && count($args) > 3) {
|
||||
if (($method_id === 'preg_match_all' || $method_id === 'preg_match') && count($args) > 3) {
|
||||
$args = array_reverse($args, true);
|
||||
}
|
||||
|
||||
|
@ -325,7 +325,7 @@ class ClassLikeDocblockParser
|
||||
$end_of_method_regex = '/(?<!array\()\) ?(\: ?(\??[\\\\a-zA-Z0-9_]+))?/';
|
||||
|
||||
if (preg_match($end_of_method_regex, $method_entry, $matches, PREG_OFFSET_CAPTURE)) {
|
||||
$method_entry = substr($method_entry, 0, (int) $matches[0][1] + strlen((string) $matches[0][0]));
|
||||
$method_entry = substr($method_entry, 0, $matches[0][1] + strlen($matches[0][0]));
|
||||
}
|
||||
|
||||
$method_entry = str_replace([', ', '( '], [',', '('], $method_entry);
|
||||
|
@ -963,6 +963,24 @@ function preg_replace_callback($pattern, $callback, $subject, int $limit = -1, &
|
||||
*/
|
||||
function preg_match_all($pattern, $subject, &$matches = [], int $flags = 1, int $offset = 0) {}
|
||||
|
||||
/**
|
||||
* @psalm-pure
|
||||
* @template TFlags as int-mask<0, 256, 512>
|
||||
*
|
||||
* @param string $pattern
|
||||
* @param string $subject
|
||||
* @param mixed $matches
|
||||
* @param TFlags $flags
|
||||
* @param-out (TFlags is 256 ? array<array-key, array{string, 0|positive-int}|array{'', -1}> :
|
||||
* TFlags is 512 ? array<array-key, string|null> :
|
||||
* TFlags is 768 ? array<array-key, array{string, 0|positive-int}|array{null, -1}> :
|
||||
* array<array-key, string>
|
||||
* ) $matches
|
||||
* @return 1|0|false
|
||||
* @psalm-ignore-falsable-return
|
||||
*/
|
||||
function preg_match($pattern, $subject, &$matches = [], int $flags = 0, int $offset = 0) {}
|
||||
|
||||
/**
|
||||
* @psalm-pure
|
||||
*
|
||||
|
@ -1282,6 +1282,13 @@ class FunctionCallTest extends TestCase
|
||||
|
||||
takesInt(preg_match("{foo}", "foo"));',
|
||||
],
|
||||
'pregMatch2' => [
|
||||
'<?php
|
||||
$r = preg_match("{foo}", "foo");',
|
||||
'assertions' => [
|
||||
'$r===' => '0|1|false',
|
||||
],
|
||||
],
|
||||
'pregMatchWithMatches' => [
|
||||
'<?php
|
||||
/** @param string[] $matches */
|
||||
@ -1291,6 +1298,14 @@ class FunctionCallTest extends TestCase
|
||||
|
||||
takesMatches($matches);',
|
||||
],
|
||||
'pregMatchWithMatches2' => [
|
||||
'<?php
|
||||
$r = preg_match("{foo}", "foo", $matches);',
|
||||
'assertions' => [
|
||||
'$r===' => '0|1|false',
|
||||
'$matches===' => 'array<array-key, string>',
|
||||
],
|
||||
],
|
||||
'pregMatchWithOffset' => [
|
||||
'<?php
|
||||
/** @param string[] $matches */
|
||||
@ -1300,18 +1315,46 @@ class FunctionCallTest extends TestCase
|
||||
|
||||
takesMatches($matches);',
|
||||
],
|
||||
'pregMatchWithOffset2' => [
|
||||
'<?php
|
||||
$r = preg_match("{foo}", "foo", $matches, 0, 10);',
|
||||
'assertions' => [
|
||||
'$r===' => '0|1|false',
|
||||
'$matches===' => 'array<array-key, string>',
|
||||
],
|
||||
],
|
||||
'pregMatchWithFlags' => [
|
||||
'<?php
|
||||
function takesInt(int $i) : void {}
|
||||
|
||||
if (preg_match("{foo}", "this is foo", $matches, PREG_OFFSET_CAPTURE)) {
|
||||
/**
|
||||
* @psalm-suppress MixedArrayAccess
|
||||
* @psalm-suppress MixedArgument
|
||||
*/
|
||||
takesInt($matches[0][1]);
|
||||
}',
|
||||
],
|
||||
'pregMatchWithFlagOffsetCapture' => [
|
||||
'<?php
|
||||
$r = preg_match("{foo}", "foo", $matches, PREG_OFFSET_CAPTURE);',
|
||||
'assertions' => [
|
||||
'$r===' => '0|1|false',
|
||||
'$matches===' => 'array<array-key, array{string, int}>',
|
||||
],
|
||||
],
|
||||
'PHP72-pregMatchWithFlagUnmatchedAsNull' => [
|
||||
'<?php
|
||||
$r = preg_match("{foo}", "foo", $matches, PREG_UNMATCHED_AS_NULL);',
|
||||
'assertions' => [
|
||||
'$r===' => '0|1|false',
|
||||
'$matches===' => 'array<array-key, null|string>',
|
||||
],
|
||||
],
|
||||
'PHP72-pregMatchWithFlagOffsetCaptureAndUnmatchedAsNull' => [
|
||||
'<?php
|
||||
$r = preg_match("{foo}", "foo", $matches, PREG_OFFSET_CAPTURE | PREG_UNMATCHED_AS_NULL);',
|
||||
'assertions' => [
|
||||
'$r===' => '0|1|false',
|
||||
'$matches===' => 'array<array-key, array{null|string, int}>',
|
||||
],
|
||||
],
|
||||
'pregReplaceCallback' => [
|
||||
'<?php
|
||||
function foo(string $s) : string {
|
||||
@ -1449,7 +1492,10 @@ class FunctionCallTest extends TestCase
|
||||
],
|
||||
'writeArgsAllowed' => [
|
||||
'<?php
|
||||
/** @return false|int */
|
||||
/**
|
||||
* @param 0|256|512|768 $flags
|
||||
* @return false|int
|
||||
*/
|
||||
function safeMatch(string $pattern, string $subject, ?array $matches = null, int $flags = 0) {
|
||||
return \preg_match($pattern, $subject, $matches, $flags);
|
||||
}
|
||||
|
@ -35,14 +35,18 @@ trait ValidCodeAnalysisTestTrait
|
||||
string $php_version = '7.3'
|
||||
): void {
|
||||
$test_name = $this->getTestName();
|
||||
if (strpos($test_name, 'PHP73-') !== false) {
|
||||
if (version_compare(PHP_VERSION, '7.3.0', '<')) {
|
||||
$this->markTestSkipped('Test case requires PHP 7.3.');
|
||||
}
|
||||
} elseif (strpos($test_name, 'PHP71-') !== false) {
|
||||
if (strpos($test_name, 'PHP71-') !== false) {
|
||||
if (version_compare(PHP_VERSION, '7.1.0', '<')) {
|
||||
$this->markTestSkipped('Test case requires PHP 7.1.');
|
||||
}
|
||||
} elseif (strpos($test_name, 'PHP72-') !== false) {
|
||||
if (version_compare(PHP_VERSION, '7.2.0', '<')) {
|
||||
$this->markTestSkipped('Test case requires PHP 7.2.');
|
||||
}
|
||||
} elseif (strpos($test_name, 'PHP73-') !== false) {
|
||||
if (version_compare(PHP_VERSION, '7.3.0', '<')) {
|
||||
$this->markTestSkipped('Test case requires PHP 7.3.');
|
||||
}
|
||||
} elseif (strpos($test_name, 'PHP80-') !== false) {
|
||||
if (version_compare(PHP_VERSION, '8.0.0', '<')) {
|
||||
$this->markTestSkipped('Test case requires PHP 8.0.');
|
||||
|
Loading…
Reference in New Issue
Block a user