Skip to content

Commit 2ec416e

Browse files
committed
All universalObjectCratesClasses allow dynamic properties
1 parent 808ab51 commit 2ec416e

File tree

8 files changed

+28
-2
lines changed

8 files changed

+28
-2
lines changed

conf/config.neon

+4
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,7 @@ services:
486486
implicitThrows: %exceptions.implicitThrows%
487487
treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain%
488488
detectDeadTypeInMultiCatch: %featureToggles.detectDeadTypeInMultiCatch%
489+
universalObjectCratesClasses: %universalObjectCratesClasses%
489490

490491
-
491492
class: PHPStan\Analyser\ConstantResolver
@@ -1916,6 +1917,7 @@ services:
19161917
class: PHPStan\Reflection\BetterReflection\BetterReflectionProvider
19171918
arguments:
19181919
reflector: @betterReflectionReflector
1920+
universalObjectCratesClasses: %universalObjectCratesClasses%
19191921
autowired: false
19201922

19211923
-
@@ -1931,6 +1933,8 @@ services:
19311933

19321934
-
19331935
implement: PHPStan\Reflection\BetterReflection\BetterReflectionProviderFactory
1936+
arguments:
1937+
universalObjectCratesClasses: %universalObjectCratesClasses%
19341938

19351939
-
19361940
class: PHPStan\Reflection\BetterReflection\SourceStubber\PhpStormStubsSourceStubberFactory

conf/config.stubValidator.neon

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ services:
2020
class: PHPStan\Reflection\BetterReflection\BetterReflectionProvider
2121
arguments:
2222
reflector: @stubReflector
23+
universalObjectCratesClasses: %universalObjectCratesClasses%
2324
autowired: false
2425

2526
stubReflector:

src/Analyser/NodeScopeResolver.php

+3
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ class NodeScopeResolver
205205
/**
206206
* @param string[][] $earlyTerminatingMethodCalls className(string) => methods(string[])
207207
* @param array<int, string> $earlyTerminatingFunctionCalls
208+
* @param string[] $universalObjectCratesClasses
208209
*/
209210
public function __construct(
210211
private readonly ReflectionProvider $reflectionProvider,
@@ -226,6 +227,7 @@ public function __construct(
226227
private readonly bool $polluteScopeWithAlwaysIterableForeach,
227228
private readonly array $earlyTerminatingMethodCalls,
228229
private readonly array $earlyTerminatingFunctionCalls,
230+
private readonly array $universalObjectCratesClasses,
229231
private readonly bool $implicitThrows,
230232
private readonly bool $treatPhpDocTypesAsCertain,
231233
private readonly bool $detectDeadTypeInMultiCatch,
@@ -1707,6 +1709,7 @@ private function createAstClassReflection(Node\Stmt\ClassLike $stmt, string $cla
17071709
null,
17081710
null,
17091711
null,
1712+
$this->universalObjectCratesClasses,
17101713
sprintf('%s:%d', $scope->getFile(), $stmt->getStartLine()),
17111714
);
17121715
}

src/Reflection/BetterReflection/BetterReflectionProvider.php

+6
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ class BetterReflectionProvider implements ReflectionProvider
6868
/** @var array<string, GlobalConstantReflection> */
6969
private array $cachedConstants = [];
7070

71+
/**
72+
* @param string[] $universalObjectCratesClasses
73+
*/
7174
public function __construct(
7275
private ReflectionProvider\ReflectionProviderProvider $reflectionProviderProvider,
7376
private InitializerExprTypeResolver $initializerExprTypeResolver,
@@ -84,6 +87,7 @@ public function __construct(
8487
private FileHelper $fileHelper,
8588
private PhpStormStubsSourceStubber $phpstormStubsSourceStubber,
8689
private SignatureMapProvider $signatureMapProvider,
90+
private array $universalObjectCratesClasses,
8791
)
8892
{
8993
}
@@ -144,6 +148,7 @@ public function getClass(string $className): ClassReflection
144148
null,
145149
null,
146150
$this->stubPhpDocProvider->findClassPhpDoc($reflectionClass->getName()),
151+
$this->universalObjectCratesClasses,
147152
);
148153

149154
$this->classReflections[$reflectionClassName] = $classReflection;
@@ -221,6 +226,7 @@ public function getAnonymousClassReflection(Node\Stmt\Class_ $classNode, Scope $
221226
$scopeFile,
222227
null,
223228
$this->stubPhpDocProvider->findClassPhpDoc($className),
229+
$this->universalObjectCratesClasses,
224230
);
225231
$this->classReflections[$className] = self::$anonymousClasses[$className];
226232

src/Reflection/ClassReflection.php

+10-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
use PHPStan\PhpDoc\Tag\TypeAliasTag;
2727
use PHPStan\Reflection\Php\PhpClassReflectionExtension;
2828
use PHPStan\Reflection\Php\PhpPropertyReflection;
29+
use PHPStan\Reflection\Php\UniversalObjectCratesClassReflectionExtension;
2930
use PHPStan\Reflection\SignatureMap\SignatureMapProvider;
3031
use PHPStan\ShouldNotHappenException;
3132
use PHPStan\Type\CircularTypeAliasDefinitionException;
@@ -45,7 +46,6 @@
4546
use PHPStan\Type\TypehintHelper;
4647
use PHPStan\Type\VerbosityLevel;
4748
use ReflectionException;
48-
use stdClass;
4949
use function array_diff;
5050
use function array_filter;
5151
use function array_key_exists;
@@ -131,6 +131,7 @@ class ClassReflection
131131
* @param PropertiesClassReflectionExtension[] $propertiesClassReflectionExtensions
132132
* @param MethodsClassReflectionExtension[] $methodsClassReflectionExtensions
133133
* @param AllowedSubTypesClassReflectionExtension[] $allowedSubTypesClassReflectionExtensions
134+
* @param string[] $universalObjectCratesClasses
134135
*/
135136
public function __construct(
136137
private ReflectionProvider $reflectionProvider,
@@ -148,6 +149,7 @@ public function __construct(
148149
private ?string $anonymousFilename,
149150
private ?TemplateTypeMap $resolvedTemplateTypeMap,
150151
private ?ResolvedPhpDocBlock $stubPhpDocBlock,
152+
private array $universalObjectCratesClasses,
151153
private ?string $extraCacheKey = null,
152154
private ?TemplateTypeVarianceMap $resolvedCallSiteVarianceMap = null,
153155
)
@@ -389,7 +391,11 @@ public function allowsDynamicProperties(): bool
389391
return false;
390392
}
391393

392-
if ($this->is(stdClass::class)) {
394+
if (UniversalObjectCratesClassReflectionExtension::isUniversalObjectCrate(
395+
$this->reflectionProvider,
396+
$this->universalObjectCratesClasses,
397+
$this,
398+
)) {
393399
return true;
394400
}
395401

@@ -1412,6 +1418,7 @@ public function withTypes(array $types): self
14121418
$this->anonymousFilename,
14131419
$this->typeMapFromList($types),
14141420
$this->stubPhpDocBlock,
1421+
$this->universalObjectCratesClasses,
14151422
null,
14161423
$this->resolvedCallSiteVarianceMap,
14171424
);
@@ -1438,6 +1445,7 @@ public function withVariances(array $variances): self
14381445
$this->anonymousFilename,
14391446
$this->resolvedTemplateTypeMap,
14401447
$this->stubPhpDocBlock,
1448+
$this->universalObjectCratesClasses,
14411449
null,
14421450
$this->varianceMapFromList($variances),
14431451
);

src/Testing/RuleTestCase.php

+1
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ private function getAnalyser(): Analyser
9999
$this->shouldPolluteScopeWithAlwaysIterableForeach(),
100100
[],
101101
[],
102+
self::getContainer()->getParameter('universalObjectCratesClasses'),
102103
self::getContainer()->getParameter('exceptions')['implicitThrows'],
103104
$this->shouldTreatPhpDocTypesAsCertain(),
104105
self::getContainer()->getParameter('featureToggles')['detectDeadTypeInMultiCatch'],

src/Testing/TypeInferenceTestCase.php

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public static function processFile(
6666
true,
6767
static::getEarlyTerminatingMethodCalls(),
6868
static::getEarlyTerminatingFunctionCalls(),
69+
self::getContainer()->getParameter('universalObjectCratesClasses'),
6970
true,
7071
self::getContainer()->getParameter('treatPhpDocTypesAsCertain'),
7172
self::getContainer()->getParameter('featureToggles')['detectDeadTypeInMultiCatch'],

tests/PHPStan/Analyser/AnalyserTest.php

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use PHPStan\Rules\Properties\ReadWritePropertiesExtensionProvider;
2323
use PHPStan\Testing\PHPStanTestCase;
2424
use PHPStan\Type\FileTypeMapper;
25+
use stdClass;
2526
use function array_map;
2627
use function array_merge;
2728
use function assert;
@@ -643,6 +644,7 @@ private function createAnalyser(bool $reportUnmatchedIgnoredErrors): Analyser
643644
true,
644645
[],
645646
[],
647+
[stdClass::class],
646648
true,
647649
$this->shouldTreatPhpDocTypesAsCertain(),
648650
self::getContainer()->getParameter('featureToggles')['detectDeadTypeInMultiCatch'],

0 commit comments

Comments
 (0)