Skip to content

Commit 4292e7c

Browse files
committed
Added bleeding-edge feature flag
1 parent 5d36ee9 commit 4292e7c

10 files changed

+45
-15
lines changed

Diff for: conf/bleedingEdge.neon

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ parameters:
55
skipCheckGenericClasses!: []
66
stricterFunctionMap: true
77
reportPreciseLineForUnusedFunctionParameter: true
8+
narrowMethodScopeFromConstructor: true

Diff for: conf/config.neon

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ parameters:
2626
skipCheckGenericClasses: []
2727
stricterFunctionMap: false
2828
reportPreciseLineForUnusedFunctionParameter: false
29+
narrowMethodScopeFromConstructor: false
2930
fileExtensions:
3031
- php
3132
checkAdvancedIsset: false
@@ -495,6 +496,7 @@ services:
495496
implicitThrows: %exceptions.implicitThrows%
496497
treatPhpDocTypesAsCertain: %treatPhpDocTypesAsCertain%
497498
universalObjectCratesClasses: %universalObjectCratesClasses%
499+
narrowMethodScopeFromConstructor: %featureToggles.narrowMethodScopeFromConstructor%
498500

499501
-
500502
class: PHPStan\Analyser\ConstantResolver

Diff for: conf/parametersSchema.neon

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ parametersSchema:
3232
skipCheckGenericClasses: listOf(string()),
3333
stricterFunctionMap: bool()
3434
reportPreciseLineForUnusedFunctionParameter: bool()
35+
narrowMethodScopeFromConstructor: bool()
3536
])
3637
fileExtensions: listOf(string())
3738
checkAdvancedIsset: bool()

Diff for: src/Analyser/NodeScopeResolver.php

+17-14
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ public function __construct(
272272
private readonly array $universalObjectCratesClasses,
273273
private readonly bool $implicitThrows,
274274
private readonly bool $treatPhpDocTypesAsCertain,
275+
private readonly bool $narrowMethodScopeFromConstructor,
275276
)
276277
{
277278
$earlyTerminatingMethodNames = [];
@@ -793,7 +794,7 @@ private function processStmtNode(
793794
$methodReflection,
794795
), $methodScope);
795796

796-
if ($isConstructor) {
797+
if ($isConstructor && $this->narrowMethodScopeFromConstructor) {
797798
$scope = $statementResult->getScope()->rememberConstructorScope();
798799
}
799800
}
@@ -930,22 +931,24 @@ private function processStmtNode(
930931
$classStatementsGatherer = new ClassStatementsGatherer($classReflection, $nodeCallback);
931932
$this->processAttributeGroups($stmt, $stmt->attrGroups, $classScope, $classStatementsGatherer);
932933

933-
// analyze static methods first; constructor next; instance methods and property hooks last so we can carry over the scope
934934
$classLikeStatements = $stmt->stmts;
935-
usort($classLikeStatements, static function ($a, $b) {
936-
if ($a instanceof Node\Stmt\Property) {
937-
return 1;
938-
}
939-
if ($b instanceof Node\Stmt\Property) {
940-
return -1;
941-
}
935+
if ($this->narrowMethodScopeFromConstructor) {
936+
// analyze static methods first; constructor next; instance methods and property hooks last so we can carry over the scope
937+
usort($classLikeStatements, static function ($a, $b) {
938+
if ($a instanceof Node\Stmt\Property) {
939+
return 1;
940+
}
941+
if ($b instanceof Node\Stmt\Property) {
942+
return -1;
943+
}
942944

943-
if (!$a instanceof Node\Stmt\ClassMethod || !$b instanceof Node\Stmt\ClassMethod) {
944-
return 0;
945-
}
945+
if (!$a instanceof Node\Stmt\ClassMethod || !$b instanceof Node\Stmt\ClassMethod) {
946+
return 0;
947+
}
946948

947-
return [!$a->isStatic(), $a->name->toLowerString() !== '__construct'] <=> [!$b->isStatic(), $b->name->toLowerString() !== '__construct'];
948-
});
949+
return [!$a->isStatic(), $a->name->toLowerString() !== '__construct'] <=> [!$b->isStatic(), $b->name->toLowerString() !== '__construct'];
950+
});
951+
}
949952

950953
$this->processStmtNodes($stmt, $classLikeStatements, $classScope, $classStatementsGatherer, $context);
951954
$nodeCallback(new ClassPropertiesNode($stmt, $this->readWritePropertiesExtensionProvider, $classStatementsGatherer->getProperties(), $classStatementsGatherer->getPropertyUsages(), $classStatementsGatherer->getMethodCalls(), $classStatementsGatherer->getReturnStatementsNodes(), $classStatementsGatherer->getPropertyAssigns(), $classReflection), $classScope);

Diff for: src/Testing/RuleTestCase.php

+6
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ private function getAnalyser(DirectRuleRegistry $ruleRegistry): Analyser
110110
self::getContainer()->getParameter('universalObjectCratesClasses'),
111111
self::getContainer()->getParameter('exceptions')['implicitThrows'],
112112
$this->shouldTreatPhpDocTypesAsCertain(),
113+
$this->shouldNarrowMethodScopeFromConstructor(),
113114
);
114115
$fileAnalyser = new FileAnalyser(
115116
$this->createScopeFactory($reflectionProvider, $typeSpecifier),
@@ -261,6 +262,11 @@ protected function shouldFailOnPhpErrors(): bool
261262
return true;
262263
}
263264

265+
protected function shouldNarrowMethodScopeFromConstructor(): bool
266+
{
267+
return false;
268+
}
269+
264270
public static function getAdditionalConfigFiles(): array
265271
{
266272
return [

Diff for: src/Testing/TypeInferenceTestCase.php

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ public static function processFile(
9090
self::getContainer()->getParameter('universalObjectCratesClasses'),
9191
self::getContainer()->getParameter('exceptions')['implicitThrows'],
9292
self::getContainer()->getParameter('treatPhpDocTypesAsCertain'),
93+
true,
9394
);
9495
$resolver->setAnalysedFiles(array_map(static fn (string $file): string => $fileHelper->normalizePath($file), array_merge([$file], static::getAdditionalAnalysedFiles())));
9596

Diff for: tests/PHPStan/Analyser/AnalyserTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,7 @@ private function createAnalyser(): Analyser
733733
[stdClass::class],
734734
true,
735735
$this->shouldTreatPhpDocTypesAsCertain(),
736+
false,
736737
);
737738
$lexer = new Lexer();
738739
$fileAnalyser = new FileAnalyser(

Diff for: tests/PHPStan/Rules/Classes/ExistingClassInInstanceOfRuleTest.php

+5
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ protected function getRule(): Rule
2929
);
3030
}
3131

32+
public function shouldNarrowMethodScopeFromConstructor(): bool
33+
{
34+
return true;
35+
}
36+
3237
public function testClassDoesNotExist(): void
3338
{
3439
$this->analyse(

Diff for: tests/PHPStan/Rules/Constants/ConstantRuleTest.php

+5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ protected function getRule(): Rule
1717
return new ConstantRule(true);
1818
}
1919

20+
public function shouldNarrowMethodScopeFromConstructor(): bool
21+
{
22+
return true;
23+
}
24+
2025
public function testConstants(): void
2126
{
2227
define('FOO_CONSTANT', 'foo');

Diff for: tests/PHPStan/Rules/Functions/CallToNonExistentFunctionRuleTest.php

+6-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ protected function getRule(): Rule
1717
return new CallToNonExistentFunctionRule($this->createReflectionProvider(), true, true);
1818
}
1919

20+
public function shouldNarrowMethodScopeFromConstructor(): bool
21+
{
22+
return true;
23+
}
24+
2025
public function testEmptyFile(): void
2126
{
2227
$this->analyse([__DIR__ . '/data/empty.php'], []);
@@ -265,7 +270,7 @@ public function testRememberFunctionExistsFromConstructor(): void
265270
'Function another_unknown_function not found.',
266271
32,
267272
'Learn more at https://phpstan.org/user-guide/discovering-symbols',
268-
]
273+
],
269274
]);
270275
}
271276

0 commit comments

Comments
 (0)