Skip to content

Commit 946cf18

Browse files
committed
New option: polluteScopeWithBlock
1 parent 2775be4 commit 946cf18

9 files changed

+85
-1
lines changed

conf/config.neon

+2
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ parameters:
154154
phpVersion: null
155155
polluteScopeWithLoopInitialAssignments: true
156156
polluteScopeWithAlwaysIterableForeach: true
157+
polluteScopeWithBlock: true
157158
propertyAlwaysWrittenTags: []
158159
propertyAlwaysReadTags: []
159160
fixerTmpDir: %pro.tmpDir% #unused
@@ -544,6 +545,7 @@ services:
544545
reflector: @nodeScopeResolverReflector
545546
polluteScopeWithLoopInitialAssignments: %polluteScopeWithLoopInitialAssignments%
546547
polluteScopeWithAlwaysIterableForeach: %polluteScopeWithAlwaysIterableForeach%
548+
polluteScopeWithBlock: %polluteScopeWithBlock%
547549
earlyTerminatingMethodCalls: %earlyTerminatingMethodCalls%
548550
earlyTerminatingFunctionCalls: %earlyTerminatingFunctionCalls%
549551
implicitThrows: %exceptions.implicitThrows%

conf/parametersSchema.neon

+1
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ parametersSchema:
148148
phpVersion: schema(anyOf(schema(int(), min(70100), max(80499))), nullable())
149149
polluteScopeWithLoopInitialAssignments: bool()
150150
polluteScopeWithAlwaysIterableForeach: bool()
151+
polluteScopeWithBlock: bool()
151152
propertyAlwaysWrittenTags: listOf(string())
152153
propertyAlwaysReadTags: listOf(string())
153154
additionalConstructors: listOf(string())

src/Analyser/NodeScopeResolver.php

+15-1
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ public function __construct(
253253
private readonly ScopeFactory $scopeFactory,
254254
private readonly bool $polluteScopeWithLoopInitialAssignments,
255255
private readonly bool $polluteScopeWithAlwaysIterableForeach,
256+
private readonly bool $polluteScopeWithBlock,
256257
private readonly array $earlyTerminatingMethodCalls,
257258
private readonly array $earlyTerminatingFunctionCalls,
258259
private readonly array $universalObjectCratesClasses,
@@ -1895,7 +1896,20 @@ static function (Node $node, Scope $scope) use ($nodeCallback): void {
18951896
new ImpurePoint($scope, $stmt, 'betweenPhpTags', 'output between PHP opening and closing tags', true),
18961897
];
18971898
} elseif ($stmt instanceof Node\Stmt\Block) {
1898-
return $this->processStmtNodes($stmt, $stmt->stmts, $scope, $nodeCallback, $context);
1899+
$result = $this->processStmtNodes($stmt, $stmt->stmts, $scope, $nodeCallback, $context);
1900+
if ($this->polluteScopeWithBlock) {
1901+
return $result;
1902+
}
1903+
1904+
return new StatementResult(
1905+
$scope->mergeWith($result->getScope()),
1906+
$result->hasYield(),
1907+
$result->isAlwaysTerminating(),
1908+
$result->getExitPoints(),
1909+
$result->getThrowPoints(),
1910+
$result->getImpurePoints(),
1911+
$result->getEndStatements(),
1912+
);
18991913
} elseif ($stmt instanceof Node\Stmt\Nop) {
19001914
$hasYield = false;
19011915
$throwPoints = $overridingThrowPoints ?? [];

src/Testing/RuleTestCase.php

+1
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ private function getAnalyser(DirectRuleRegistry $ruleRegistry): Analyser
9999
self::createScopeFactory($reflectionProvider, $typeSpecifier),
100100
$this->shouldPolluteScopeWithLoopInitialAssignments(),
101101
$this->shouldPolluteScopeWithAlwaysIterableForeach(),
102+
self::getContainer()->getParameter('polluteScopeWithBlock'),
102103
[],
103104
[],
104105
self::getContainer()->getParameter('universalObjectCratesClasses'),

src/Testing/TypeInferenceTestCase.php

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ public static function processFile(
7979
self::createScopeFactory($reflectionProvider, $typeSpecifier),
8080
self::getContainer()->getParameter('polluteScopeWithLoopInitialAssignments'),
8181
self::getContainer()->getParameter('polluteScopeWithAlwaysIterableForeach'),
82+
self::getContainer()->getParameter('polluteScopeWithBlock'),
8283
static::getEarlyTerminatingMethodCalls(),
8384
static::getEarlyTerminatingFunctionCalls(),
8485
self::getContainer()->getParameter('universalObjectCratesClasses'),

tests/PHPStan/Analyser/AnalyserTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,7 @@ private function createAnalyser(bool $enableIgnoreErrorsWithinPhpDocs): Analyser
735735
self::createScopeFactory($reflectionProvider, $typeSpecifier),
736736
false,
737737
true,
738+
true,
738739
[],
739740
[],
740741
[stdClass::class],
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Analyser;
4+
5+
use PHPStan\Testing\TypeInferenceTestCase;
6+
7+
class DoNotPolluteScopeWithBlockTest extends TypeInferenceTestCase
8+
{
9+
10+
public function dataFileAsserts(): iterable
11+
{
12+
yield from $this->gatherAssertTypes(__DIR__ . '/data/do-not-pollute-scope-with-block.php');
13+
}
14+
15+
/**
16+
* @dataProvider dataFileAsserts
17+
* @param mixed ...$args
18+
*/
19+
public function testFileAsserts(
20+
string $assertType,
21+
string $file,
22+
...$args,
23+
): void
24+
{
25+
$this->assertFileAsserts($assertType, $file, ...$args);
26+
}
27+
28+
public static function getAdditionalConfigFiles(): array
29+
{
30+
return [
31+
__DIR__ . '/../../../conf/bleedingEdge.neon',
32+
__DIR__ . '/do-not-pollute-scope-with-block.neon',
33+
];
34+
}
35+
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace DoNotPolluteScopeWithBlock;
4+
5+
use PHPStan\TrinaryLogic;
6+
use function PHPStan\Testing\assertType;
7+
use function PHPStan\Testing\assertVariableCertainty;
8+
9+
class Foo
10+
{
11+
12+
public function doFoo(): void
13+
{
14+
$a = 1;
15+
{
16+
$b = 2;
17+
}
18+
19+
assertVariableCertainty(TrinaryLogic::createYes(), $a);
20+
assertType('1', $a);
21+
22+
assertVariableCertainty(TrinaryLogic::createMaybe(), $b);
23+
assertType('2', $b);
24+
}
25+
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
parameters:
2+
polluteScopeWithBlock: false

0 commit comments

Comments
 (0)