Skip to content

Commit 8fd217a

Browse files
authored
Named argument detection is scope-PHP version dependent
1 parent 202dd81 commit 8fd217a

22 files changed

+119
-56
lines changed

src/Analyser/MutatingScope.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3139,7 +3139,7 @@ private function enterFunctionLike(
31393139

31403140
$paramExprString = '$' . $parameter->getName();
31413141
if ($parameter->isVariadic()) {
3142-
if ($this->phpVersion->supportsNamedArguments() && $functionReflection->acceptsNamedArguments()->yes()) {
3142+
if (!$this->getPhpVersion()->supportsNamedArguments()->no() && $functionReflection->acceptsNamedArguments()->yes()) {
31433143
$parameterType = new ArrayType(new UnionType([new IntegerType(), new StringType()]), $parameterType);
31443144
} else {
31453145
$parameterType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $parameterType), new AccessoryArrayListType());
@@ -3154,7 +3154,7 @@ private function enterFunctionLike(
31543154

31553155
$nativeParameterType = $parameter->getNativeType();
31563156
if ($parameter->isVariadic()) {
3157-
if ($this->phpVersion->supportsNamedArguments() && $functionReflection->acceptsNamedArguments()->yes()) {
3157+
if (!$this->getPhpVersion()->supportsNamedArguments()->no() && $functionReflection->acceptsNamedArguments()->yes()) {
31583158
$nativeParameterType = new ArrayType(new UnionType([new IntegerType(), new StringType()]), $nativeParameterType);
31593159
} else {
31603160
$nativeParameterType = TypeCombinator::intersect(new ArrayType(new IntegerType(), $nativeParameterType), new AccessoryArrayListType());
@@ -3629,7 +3629,7 @@ public function getFunctionType($type, bool $isNullable, bool $isVariadic): Type
36293629
);
36303630
}
36313631
if ($isVariadic) {
3632-
if ($this->phpVersion->supportsNamedArguments()) {
3632+
if (!$this->getPhpVersion()->supportsNamedArguments()->no()) {
36333633
return new ArrayType(new UnionType([new IntegerType(), new StringType()]), $this->getFunctionType(
36343634
$type,
36353635
false,

src/Php/PhpVersions.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,9 @@ public function producesWarningForFinalPrivateMethods(): TrinaryLogic
2828
return IntegerRangeType::fromInterval(80000, null)->isSuperTypeOf($this->phpVersions)->result;
2929
}
3030

31+
public function supportsNamedArguments(): TrinaryLogic
32+
{
33+
return IntegerRangeType::fromInterval(80000, null)->isSuperTypeOf($this->phpVersions)->result;
34+
}
35+
3136
}

src/Rules/FunctionCallParametersCheck.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
use PhpParser\Node\Expr;
77
use PHPStan\Analyser\MutatingScope;
88
use PHPStan\Analyser\Scope;
9-
use PHPStan\Php\PhpVersion;
109
use PHPStan\Reflection\ExtendedParameterReflection;
1110
use PHPStan\Reflection\ParameterReflection;
1211
use PHPStan\Reflection\ParametersAcceptor;
@@ -42,7 +41,6 @@ final class FunctionCallParametersCheck
4241
public function __construct(
4342
private RuleLevelHelper $ruleLevelHelper,
4443
private NullsafeCheck $nullsafeCheck,
45-
private PhpVersion $phpVersion,
4644
private UnresolvableTypeHelper $unresolvableTypeHelper,
4745
private PropertyReflectionFinder $propertyReflectionFinder,
4846
private bool $checkArgumentTypes,
@@ -201,7 +199,7 @@ public function check(
201199
];
202200
}
203201

204-
if ($hasNamedArguments && !$this->phpVersion->supportsNamedArguments() && !(bool) $funcCall->getAttribute('isAttribute', false)) {
202+
if ($hasNamedArguments && !$scope->getPhpVersion()->supportsNamedArguments()->yes() && !(bool) $funcCall->getAttribute('isAttribute', false)) {
205203
$errors[] = RuleErrorBuilder::message('Named arguments are supported only on PHP 8.0 and later.')
206204
->identifier('argument.namedNotSupported')
207205
->line($funcCall->getStartLine())

tests/PHPStan/Analyser/Bug9307CallMethodsRuleTest.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace PHPStan\Analyser;
44

5-
use PHPStan\Php\PhpVersion;
65
use PHPStan\Rules\FunctionCallParametersCheck;
76
use PHPStan\Rules\Methods\CallMethodsRule;
87
use PHPStan\Rules\Methods\MethodCallCheck;
@@ -12,7 +11,6 @@
1211
use PHPStan\Rules\Rule;
1312
use PHPStan\Rules\RuleLevelHelper;
1413
use PHPStan\Testing\RuleTestCase;
15-
use const PHP_VERSION_ID;
1614

1715
/**
1816
* @extends RuleTestCase<CallMethodsRule>
@@ -26,7 +24,7 @@ protected function getRule(): Rule
2624
$ruleLevelHelper = new RuleLevelHelper($reflectionProvider, true, false, true, true, false, false);
2725
return new CallMethodsRule(
2826
new MethodCallCheck($reflectionProvider, $ruleLevelHelper, true, true),
29-
new FunctionCallParametersCheck($ruleLevelHelper, new NullsafeCheck(), new PhpVersion(PHP_VERSION_ID), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true),
27+
new FunctionCallParametersCheck($ruleLevelHelper, new NullsafeCheck(), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true),
3028
);
3129
}
3230

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php // lint > 7.4
2+
3+
namespace Bug2600PhpVersionScope;
4+
5+
use function PHPStan\Testing\assertType;
6+
7+
if (PHP_VERSION_ID >= 80000) {
8+
class Foo8 {
9+
/**
10+
* @param mixed $x
11+
*/
12+
public function doBaz(...$x) {
13+
assertType('array<int|string, mixed>', $x);
14+
}
15+
}
16+
} else {
17+
class Foo9 {
18+
/**
19+
* @param mixed $x
20+
*/
21+
public function doBaz(...$x) {
22+
assertType('list<mixed>', $x);
23+
}
24+
}
25+
26+
}

tests/PHPStan/Rules/Classes/ClassAttributesRuleTest.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace PHPStan\Rules\Classes;
44

5-
use PHPStan\Php\PhpVersion;
65
use PHPStan\Rules\AttributesCheck;
76
use PHPStan\Rules\ClassCaseSensitivityCheck;
87
use PHPStan\Rules\ClassForbiddenNameCheck;
@@ -35,7 +34,6 @@ protected function getRule(): Rule
3534
new FunctionCallParametersCheck(
3635
new RuleLevelHelper($reflectionProvider, true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, false),
3736
new NullsafeCheck(),
38-
new PhpVersion(80000),
3937
new UnresolvableTypeHelper(),
4038
new PropertyReflectionFinder(),
4139
true,

tests/PHPStan/Rules/Classes/ClassConstantAttributesRuleTest.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace PHPStan\Rules\Classes;
44

5-
use PHPStan\Php\PhpVersion;
65
use PHPStan\Rules\AttributesCheck;
76
use PHPStan\Rules\ClassCaseSensitivityCheck;
87
use PHPStan\Rules\ClassForbiddenNameCheck;
@@ -30,7 +29,6 @@ protected function getRule(): Rule
3029
new FunctionCallParametersCheck(
3130
new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false),
3231
new NullsafeCheck(),
33-
new PhpVersion(80000),
3432
new UnresolvableTypeHelper(),
3533
new PropertyReflectionFinder(),
3634
true,

tests/PHPStan/Rules/Classes/ForbiddenNameCheckExtensionRuleTest.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace PHPStan\Rules\Classes;
44

5-
use PHPStan\Php\PhpVersion;
65
use PHPStan\Rules\ClassCaseSensitivityCheck;
76
use PHPStan\Rules\ClassForbiddenNameCheck;
87
use PHPStan\Rules\ClassNameCheck;
@@ -26,7 +25,7 @@ protected function getRule(): Rule
2625
$reflectionProvider = $this->createReflectionProvider();
2726
return new InstantiationRule(
2827
$reflectionProvider,
29-
new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true),
28+
new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true),
3029
new ClassNameCheck(
3130
new ClassCaseSensitivityCheck($reflectionProvider, true),
3231
new ClassForbiddenNameCheck(self::getContainer()),

tests/PHPStan/Rules/Classes/InstantiationRuleTest.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace PHPStan\Rules\Classes;
44

5-
use PHPStan\Php\PhpVersion;
65
use PHPStan\Rules\ClassCaseSensitivityCheck;
76
use PHPStan\Rules\ClassForbiddenNameCheck;
87
use PHPStan\Rules\ClassNameCheck;
@@ -26,7 +25,7 @@ protected function getRule(): Rule
2625
$reflectionProvider = $this->createReflectionProvider();
2726
return new InstantiationRule(
2827
$reflectionProvider,
29-
new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new PhpVersion(80000), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true),
28+
new FunctionCallParametersCheck(new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false), new NullsafeCheck(), new UnresolvableTypeHelper(), new PropertyReflectionFinder(), true, true, true, true),
3029
new ClassNameCheck(
3130
new ClassCaseSensitivityCheck($reflectionProvider, true),
3231
new ClassForbiddenNameCheck(self::getContainer()),
@@ -290,6 +289,10 @@ public function testBug4056(): void
290289

291290
public function testNamedArguments(): void
292291
{
292+
if (PHP_VERSION_ID < 80000) {
293+
$this->markTestSkipped('Test requires PHP 8.0');
294+
}
295+
293296
$this->analyse([__DIR__ . '/data/instantiation-named-arguments.php'], [
294297
[
295298
'Missing parameter $j (int) in call to InstantiationNamedArguments\Foo constructor.',
@@ -501,6 +504,10 @@ public function testBug10248(): void
501504

502505
public function testBug11815(): void
503506
{
507+
if (PHP_VERSION_ID < 80000) {
508+
$this->markTestSkipped('Test requires PHP 8.0');
509+
}
510+
504511
$this->analyse([__DIR__ . '/data/bug-11815.php'], []);
505512
}
506513

tests/PHPStan/Rules/EnumCases/EnumCaseAttributesRuleTest.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace PHPStan\Rules\EnumCases;
44

5-
use PHPStan\Php\PhpVersion;
65
use PHPStan\Rules\AttributesCheck;
76
use PHPStan\Rules\ClassCaseSensitivityCheck;
87
use PHPStan\Rules\ClassForbiddenNameCheck;
@@ -30,7 +29,6 @@ protected function getRule(): Rule
3029
new FunctionCallParametersCheck(
3130
new RuleLevelHelper($reflectionProvider, true, false, true, false, false, false),
3231
new NullsafeCheck(),
33-
new PhpVersion(80100),
3432
new UnresolvableTypeHelper(),
3533
new PropertyReflectionFinder(),
3634
true,

0 commit comments

Comments
 (0)