Skip to content

Commit b0a99fd

Browse files
authored
Increment on non-numeric string is deprecated, use str_increment() instead
1 parent c8598f4 commit b0a99fd

File tree

6 files changed

+85
-3
lines changed

6 files changed

+85
-3
lines changed

build/ignore-by-php-version.neon.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@
3838
} else {
3939
$includes[] = __DIR__ . '/new-phpunit.neon';
4040
}
41+
42+
if (PHP_VERSION_ID < 80300) {
43+
$includes[] = __DIR__ . '/str-increment.neon';
44+
}
45+
4146
$config = [];
4247
$config['includes'] = $includes;
4348

build/str-increment.neon

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
parameters:
2+
ignoreErrors:
3+
-
4+
message: '#^Used function str_increment not found\.#'

src/Analyser/MutatingScope.php

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@
150150
use function array_values;
151151
use function count;
152152
use function explode;
153+
use function function_exists;
153154
use function get_class;
154155
use function implode;
155156
use function in_array;
@@ -160,6 +161,7 @@
160161
use function ltrim;
161162
use function md5;
162163
use function sprintf;
164+
use function str_increment;
163165
use function str_starts_with;
164166
use function strlen;
165167
use function strtolower;
@@ -1731,12 +1733,26 @@ static function (Node $node, Scope $scope) use ($arrowScope, &$arrowFunctionImpu
17311733
$newTypes = [];
17321734

17331735
foreach ($varScalars as $varValue) {
1736+
// until PHP 8.5 it was valid to increment/decrement an empty string.
1737+
// see https://github.com/php/php-src/issues/19597
17341738
if ($node instanceof Expr\PreInc) {
1735-
if (!is_bool($varValue)) {
1739+
if ($varValue === '') {
1740+
$varValue = '1';
1741+
} elseif (
1742+
is_string($varValue)
1743+
&& !is_numeric($varValue)
1744+
&& function_exists('str_increment')
1745+
) {
1746+
$varValue = str_increment($varValue);
1747+
} elseif (!is_bool($varValue)) {
17361748
++$varValue;
17371749
}
1738-
} elseif (is_numeric($varValue)) {
1739-
--$varValue;
1750+
} else {
1751+
if ($varValue === '') {
1752+
$varValue = -1;
1753+
} elseif (is_numeric($varValue)) {
1754+
--$varValue;
1755+
}
17401756
}
17411757

17421758
$newTypes[] = $this->getTypeFromValue($varValue);

src/Type/Php/StrIncrementDecrementFunctionReturnTypeExtension.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,15 @@
66
use PHPStan\Analyser\Scope;
77
use PHPStan\DependencyInjection\AutowiredService;
88
use PHPStan\Reflection\FunctionReflection;
9+
use PHPStan\ShouldNotHappenException;
910
use PHPStan\Type\Constant\ConstantStringType;
1011
use PHPStan\Type\DynamicFunctionReturnTypeExtension;
1112
use PHPStan\Type\ErrorType;
1213
use PHPStan\Type\Type;
1314
use PHPStan\Type\TypeCombinator;
1415
use function chr;
1516
use function count;
17+
use function function_exists;
1618
use function implode;
1719
use function in_array;
1820
use function is_float;
@@ -21,6 +23,7 @@
2123
use function is_string;
2224
use function ord;
2325
use function preg_match;
26+
use function str_increment;
2427
use function str_split;
2528
use function stripos;
2629

@@ -103,6 +106,14 @@ private function increment(string $s): string
103106
}
104107
}
105108

109+
if ($s === '') {
110+
throw new ShouldNotHappenException();
111+
}
112+
113+
if (function_exists('str_increment')) {
114+
return str_increment($s);
115+
}
116+
106117
return (string) ++$s;
107118
}
108119

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace PreDec;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
function doFoo() {
8+
$s = '';
9+
--$s;
10+
assertType("-1", $s);
11+
}
12+
13+
function doFoo2() {
14+
$s = '123';
15+
--$s;
16+
assertType("122", $s);
17+
}
18+
19+
function doFooBar() {
20+
$s = 'abc';
21+
--$s;
22+
assertType("'abc'", $s);
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
namespace PreInc;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
function doFoo() {
8+
$s = '';
9+
++$s;
10+
assertType("'1'", $s);
11+
}
12+
13+
function doFoo2() {
14+
$s = '123';
15+
++$s;
16+
assertType("124", $s);
17+
}
18+
19+
function doFooBar() {
20+
$s = 'abc';
21+
++$s;
22+
assertType("'abd'", $s);
23+
}

0 commit comments

Comments
 (0)