Skip to content

Commit 815270d

Browse files
committed
Observe @no-named-arguments above class
1 parent b98abe0 commit 815270d

File tree

4 files changed

+83
-0
lines changed

4 files changed

+83
-0
lines changed

src/Analyser/NodeScopeResolver.php

+3
Original file line numberDiff line numberDiff line change
@@ -6005,6 +6005,9 @@ public function getPhpDocs(Scope $scope, Node\FunctionLike|Node\Stmt\Property $n
60056005
$isPure = $resolvedPhpDoc->isPure();
60066006
$isAllowedPrivateMutation = $resolvedPhpDoc->isAllowedPrivateMutation();
60076007
$acceptsNamedArguments = $resolvedPhpDoc->acceptsNamedArguments();
6008+
if ($acceptsNamedArguments && $scope->isInClass()) {
6009+
$acceptsNamedArguments = $scope->getClassReflection()->acceptsNamedArguments();
6010+
}
60086011
$isReadOnly = $isReadOnly || $resolvedPhpDoc->isReadOnly();
60096012
$asserts = Assertions::createFromResolvedPhpDocBlock($resolvedPhpDoc);
60106013
$selfOutType = $resolvedPhpDoc->getSelfOutTag() !== null ? $resolvedPhpDoc->getSelfOutTag()->getType() : null;

src/Reflection/ClassReflection.php

+12
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ class ClassReflection
102102

103103
private ?bool $hasConsistentConstructor = null;
104104

105+
private ?bool $acceptsNamedArguments = null;
106+
105107
private ?TemplateTypeMap $templateTypeMap = null;
106108

107109
private ?TemplateTypeMap $activeTemplateTypeMap = null;
@@ -1243,6 +1245,16 @@ public function hasConsistentConstructor(): bool
12431245
return $this->hasConsistentConstructor;
12441246
}
12451247

1248+
public function acceptsNamedArguments(): bool
1249+
{
1250+
if ($this->acceptsNamedArguments === null) {
1251+
$resolvedPhpDoc = $this->getResolvedPhpDoc();
1252+
$this->acceptsNamedArguments = $resolvedPhpDoc === null || $resolvedPhpDoc->acceptsNamedArguments();
1253+
}
1254+
1255+
return $this->acceptsNamedArguments;
1256+
}
1257+
12461258
public function isFinalByKeyword(): bool
12471259
{
12481260
if ($this->isAnonymous()) {

tests/PHPStan/Rules/Properties/TypesAssignedToPropertiesRuleTest.php

+16
Original file line numberDiff line numberDiff line change
@@ -614,4 +614,20 @@ public function testGenericsInCallableInConstructor(): void
614614
$this->analyse([__DIR__ . '/data/generics-in-callable-in-constructor.php'], []);
615615
}
616616

617+
public function testBug11275(): void
618+
{
619+
if (PHP_VERSION_ID < 70400) {
620+
$this->markTestSkipped('Test requires PHP 7.4.');
621+
}
622+
623+
$this->checkExplicitMixed = true;
624+
$this->analyse([__DIR__ . '/data/bug-11275.php'], [
625+
[
626+
'Property Bug11275\D::$b (list<Bug11275\B>) does not accept array<int|string, Bug11275\B>.',
627+
50,
628+
'array<int|string, Bug11275\B> might not be a list.',
629+
],
630+
]);
631+
}
632+
617633
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php // lint >= 7.4
2+
3+
namespace Bug11275;
4+
5+
/**
6+
* @no-named-arguments
7+
*/
8+
final class A
9+
{
10+
/**
11+
* @var list<B>
12+
*/
13+
private array $b;
14+
15+
public function __construct(B ...$b)
16+
{
17+
$this->b = $b;
18+
}
19+
}
20+
21+
final class B
22+
{
23+
}
24+
25+
final class C
26+
{
27+
/**
28+
* @var list<B>
29+
*/
30+
private array $b;
31+
32+
/**
33+
* @no-named-arguments
34+
*/
35+
public function __construct(B ...$b)
36+
{
37+
$this->b = $b;
38+
}
39+
}
40+
41+
final class D
42+
{
43+
/**
44+
* @var list<B>
45+
*/
46+
private array $b;
47+
48+
public function __construct(B ...$b)
49+
{
50+
$this->b = $b;
51+
}
52+
}

0 commit comments

Comments
 (0)