Skip to content

Commit 7bc35cd

Browse files
committed
Fix function signatures with multiple variants on PHP 8
1 parent 14725cc commit 7bc35cd

File tree

8 files changed

+88
-63
lines changed

8 files changed

+88
-63
lines changed

resources/functionMap_php80delta.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@
6565
'imagegetclip' => ['array<int,int>', 'im'=>'resource'],
6666
'imagegrabscreen' => ['false|object'],
6767
'imagegrabwindow' => ['false|object', 'window_handle'=>'int', 'client_area='=>'int'],
68+
'imagejpeg' => ['bool', 'im'=>'GdImage', 'filename='=>'string|resource|null', 'quality='=>'int'],
69+
'imagejpeg\'1' => ['string|false', 'im'=>'GdImage', 'filename='=>'null', 'quality='=>'int'],
6870
'imagerotate' => ['false|object', 'src_im'=>'resource', 'angle'=>'float', 'bgdcolor'=>'int', 'ignoretransparent='=>'int'],
6971
'imagescale' => ['false|object', 'im'=>'resource', 'new_width'=>'int', 'new_height='=>'int', 'method='=>'int'],
7072
'mb_decode_numericentity' => ['string|false', 'string'=>'string', 'convmap'=>'array', 'encoding='=>'string'],
@@ -186,6 +188,8 @@
186188
'imagegetclip' => ['array<int,int>|false', 'im'=>'resource'],
187189
'imagegrabscreen' => ['false|resource'],
188190
'imagegrabwindow' => ['false|resource', 'window_handle'=>'int', 'client_area='=>'int'],
191+
'imagejpeg' => ['bool', 'im'=>'resource', 'filename='=>'string|resource|null', 'quality='=>'int'],
192+
'imagejpeg\'1' => ['string|false', 'im'=>'resource', 'filename='=>'null', 'quality='=>'int'],
189193
'imagerotate' => ['resource|false', 'src_im'=>'resource', 'angle'=>'float', 'bgdcolor'=>'int', 'ignoretransparent='=>'int'],
190194
'imagescale' => ['resource|false', 'im'=>'resource', 'new_width'=>'int', 'new_height='=>'int', 'method='=>'int'],
191195
'jpeg2wbmp' => ['bool', 'jpegname'=>'string', 'wbmpname'=>'string', 'dest_height'=>'int', 'dest_width'=>'int', 'threshold'=>'int'],

src/Reflection/SignatureMap/Php8SignatureMapProvider.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ public function getMethodSignature(string $className, string $methodName, ?\Refl
124124
return $this->functionSignatureMapProvider->getMethodSignature($className, $methodName, $reflectionMethod, $variant);
125125
}
126126

127+
if ($this->functionSignatureMapProvider->hasMethodSignature($className, $methodName, 1)) {
128+
return $this->functionSignatureMapProvider->getMethodSignature($className, $methodName, $reflectionMethod, $variant);
129+
}
130+
127131
$methodNode = $this->findMethodNode($className, $methodName);
128132
if ($methodNode === null) {
129133
return $this->functionSignatureMapProvider->getMethodSignature($className, $methodName, $reflectionMethod, $variant);
@@ -153,6 +157,10 @@ public function getFunctionSignature(string $functionName, ?string $className, i
153157
return $this->functionSignatureMapProvider->getFunctionSignature($functionName, $className, $variant);
154158
}
155159

160+
if ($this->functionSignatureMapProvider->hasFunctionSignature($functionName, 1)) {
161+
return $this->functionSignatureMapProvider->getFunctionSignature($functionName, $className, $variant);
162+
}
163+
156164
$stubFile = self::DIRECTORY . '/' . Php8StubsMap::FUNCTIONS[$lowerName];
157165
$nodes = $this->fileNodesFetcher->fetchNodes($stubFile);
158166
$functions = $nodes->getFunctionNodes();

tests/PHPStan/Analyser/NodeScopeResolverTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10802,6 +10802,11 @@ public function dataBug1283(): array
1080210802
return $this->gatherAssertTypes(__DIR__ . '/data/bug-1283.php');
1080310803
}
1080410804

10805+
public function dataBug4538(): array
10806+
{
10807+
return $this->gatherAssertTypes(__DIR__ . '/data/bug-4538.php');
10808+
}
10809+
1080510810
/**
1080610811
* @param string $file
1080710812
* @return array<string, mixed[]>
@@ -11024,6 +11029,7 @@ private function gatherAssertTypes(string $file): array
1102411029
* @dataProvider dataBug2003
1102511030
* @dataProvider dataBug651
1102611031
* @dataProvider dataBug1283
11032+
* @dataProvider dataBug4538
1102711033
* @param string $assertType
1102811034
* @param string $file
1102911035
* @param mixed ...$args
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace Bug4538;
4+
5+
use function PHPStan\Analyser\assertType;
6+
7+
class Foo
8+
{
9+
/**
10+
* @param string $index
11+
*/
12+
public function bar(string $index): void
13+
{
14+
assertType('string|false', getenv($index));
15+
assertType('array<string>', getenv());
16+
}
17+
}

tests/PHPStan/Reflection/ParametersAcceptorSelectorTest.php

Lines changed: 38 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
use PHPStan\Type\StringType;
2222
use PHPStan\Type\UnionType;
2323
use PHPStan\Type\VerbosityLevel;
24-
use const PHP_VERSION_ID;
2524

2625
class ParametersAcceptorSelectorTest extends \PHPStan\Testing\TestCase
2726
{
@@ -42,16 +41,14 @@ public function dataSelectFromTypes(): \Generator
4241
$arrayRandVariants[0],
4342
];
4443

45-
if (PHP_VERSION_ID < 80000) {
46-
yield [
47-
[
48-
new ArrayType(new MixedType(), new MixedType()),
49-
],
50-
$arrayRandVariants,
51-
false,
52-
$arrayRandVariants[1],
53-
];
54-
}
44+
yield [
45+
[
46+
new ArrayType(new MixedType(), new MixedType()),
47+
],
48+
$arrayRandVariants,
49+
false,
50+
$arrayRandVariants[1],
51+
];
5552

5653
$datePeriodConstructorVariants = $broker->getClass('DatePeriod')->getNativeMethod('__construct')->getVariants();
5754
yield [
@@ -65,29 +62,26 @@ public function dataSelectFromTypes(): \Generator
6562
false,
6663
$datePeriodConstructorVariants[0],
6764
];
68-
69-
if (PHP_VERSION_ID < 80000) {
70-
yield [
71-
[
72-
new ObjectType(\DateTimeInterface::class),
73-
new ObjectType(\DateInterval::class),
74-
new ObjectType(\DateTimeInterface::class),
75-
new IntegerType(),
76-
],
77-
$datePeriodConstructorVariants,
78-
false,
79-
$datePeriodConstructorVariants[1],
80-
];
81-
yield [
82-
[
83-
new StringType(),
84-
new IntegerType(),
85-
],
86-
$datePeriodConstructorVariants,
87-
false,
88-
$datePeriodConstructorVariants[2],
89-
];
90-
}
65+
yield [
66+
[
67+
new ObjectType(\DateTimeInterface::class),
68+
new ObjectType(\DateInterval::class),
69+
new ObjectType(\DateTimeInterface::class),
70+
new IntegerType(),
71+
],
72+
$datePeriodConstructorVariants,
73+
false,
74+
$datePeriodConstructorVariants[1],
75+
];
76+
yield [
77+
[
78+
new StringType(),
79+
new IntegerType(),
80+
],
81+
$datePeriodConstructorVariants,
82+
false,
83+
$datePeriodConstructorVariants[2],
84+
];
9185

9286
$ibaseWaitEventVariants = $broker->getFunction(new Name('ibase_wait_event'), null)->getVariants();
9387
yield [
@@ -181,7 +175,7 @@ public function dataSelectFromTypes(): \Generator
181175
null,
182176
[
183177
new NativeParameterReflection(
184-
PHP_VERSION_ID < 80000 ? 'str|token' : 'string|token',
178+
'str|token',
185179
false,
186180
new StringType(),
187181
PassedByReference::createNo(),
@@ -191,7 +185,7 @@ public function dataSelectFromTypes(): \Generator
191185
new NativeParameterReflection(
192186
'token',
193187
true,
194-
PHP_VERSION_ID < 80000 ? new StringType() : new UnionType([new StringType(), new NullType()]),
188+
new StringType(),
195189
PassedByReference::createNo(),
196190
false,
197191
null
@@ -201,17 +195,14 @@ public function dataSelectFromTypes(): \Generator
201195
new UnionType([new StringType(), new ConstantBooleanType(false)])
202196
),
203197
];
204-
205-
if (PHP_VERSION_ID < 80000) {
206-
yield [
207-
[
208-
new StringType(),
209-
],
210-
$strtokVariants,
211-
true,
212-
ParametersAcceptorSelector::combineAcceptors($strtokVariants),
213-
];
214-
}
198+
yield [
199+
[
200+
new StringType(),
201+
],
202+
$strtokVariants,
203+
true,
204+
ParametersAcceptorSelector::combineAcceptors($strtokVariants),
205+
];
215206

216207
$variadicVariants = [
217208
new FunctionVariant(

tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -312,13 +312,6 @@ public function testImplodeOnPhp74(): void
312312
];
313313
if (PHP_VERSION_ID < 70400) {
314314
$errors = [];
315-
} elseif (PHP_VERSION_ID >= 80000) {
316-
$errors = [
317-
[
318-
'Parameter #2 $array of function implode expects array, string given.',
319-
8,
320-
],
321-
];
322315
}
323316

324317
$this->analyse([__DIR__ . '/data/implode-74.php'], $errors);
@@ -331,7 +324,7 @@ public function testImplodeOnLessThanPhp74(): void
331324
}
332325

333326
$errors = [];
334-
if (PHP_VERSION_ID >= 70400 && PHP_VERSION_ID < 80000) {
327+
if (PHP_VERSION_ID >= 70400) {
335328
$errors = [
336329
[
337330
'Parameter #1 $glue of function implode expects string, array given.',
@@ -342,13 +335,6 @@ public function testImplodeOnLessThanPhp74(): void
342335
8,
343336
],
344337
];
345-
} elseif (PHP_VERSION_ID >= 80000) {
346-
$errors = [
347-
[
348-
'Parameter #2 $array of function implode expects array, string given.',
349-
8,
350-
],
351-
];
352338
}
353339

354340
$this->analyse([__DIR__ . '/data/implode-74.php'], $errors);
@@ -489,4 +475,9 @@ public function testBug4514(): void
489475
$this->analyse([__DIR__ . '/data/bug-4514.php'], []);
490476
}
491477

478+
public function testBug4530(): void
479+
{
480+
$this->analyse([__DIR__ . '/data/bug-4530.php'], []);
481+
}
482+
492483
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Bug4530;
4+
5+
$array1 = array("a" => "green", "b" => "brown", "c" => "blue", "red");
6+
$array2 = array("a" => "GREEN", "B" => "brown", "yellow", "red");
7+
8+
array_uintersect($array1, $array2, "strcasecmp");

tests/PHPStan/Rules/Methods/CallMethodsRuleTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ public function testCallMethods(): void
147147
108,
148148
],
149149
[
150-
PHP_VERSION_ID < 80000 ? 'Method PDO::query() invoked with 0 parameters, 1-4 required.' : 'Method PDO::query() invoked with 0 parameters, at least 1 required.',
150+
'Method PDO::query() invoked with 0 parameters, 1-4 required.',
151151
113,
152152
],
153153
[

0 commit comments

Comments
 (0)