From 64ed7dc7207aff6d7d833f9c0449b13257c4da40 Mon Sep 17 00:00:00 2001 From: Ruud Kamphuis Date: Wed, 2 Oct 2024 09:49:18 +0200 Subject: [PATCH] Introduce `Scope::getMaybeDefinedVariables()` --- src/Analyser/MutatingScope.php | 21 +++++++++++++++++++++ src/Analyser/Scope.php | 5 +++++ tests/PHPStan/Analyser/ScopeTest.php | 27 +++++++++++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/src/Analyser/MutatingScope.php b/src/Analyser/MutatingScope.php index 086a09c3c2..d8cc9faf06 100644 --- a/src/Analyser/MutatingScope.php +++ b/src/Analyser/MutatingScope.php @@ -574,6 +574,27 @@ public function getDefinedVariables(): array return $variables; } + /** + * @api + * @return array + */ + public function getMaybeDefinedVariables(): array + { + $variables = []; + foreach ($this->expressionTypes as $exprString => $holder) { + if (!$holder->getExpr() instanceof Variable) { + continue; + } + if (!$holder->getCertainty()->maybe()) { + continue; + } + + $variables[] = substr($exprString, 1); + } + + return $variables; + } + private function isGlobalVariable(string $variableName): bool { return in_array($variableName, self::SUPERGLOBAL_VARIABLES, true); diff --git a/src/Analyser/Scope.php b/src/Analyser/Scope.php index 0c1682209d..b1fe0cff97 100644 --- a/src/Analyser/Scope.php +++ b/src/Analyser/Scope.php @@ -67,6 +67,11 @@ public function canAnyVariableExist(): bool; */ public function getDefinedVariables(): array; + /** + * @return array + */ + public function getMaybeDefinedVariables(): array; + public function hasConstant(Name $name): bool; public function getPropertyReflection(Type $typeWithProperty, string $propertyName): ?ExtendedPropertyReflection; diff --git a/tests/PHPStan/Analyser/ScopeTest.php b/tests/PHPStan/Analyser/ScopeTest.php index fe0644cd30..cdad83a96f 100644 --- a/tests/PHPStan/Analyser/ScopeTest.php +++ b/tests/PHPStan/Analyser/ScopeTest.php @@ -5,16 +5,21 @@ use PhpParser\Node\Expr\ConstFetch; use PhpParser\Node\Name\FullyQualified; use PHPStan\Testing\PHPStanTestCase; +use PHPStan\TrinaryLogic; use PHPStan\Type\Constant\ConstantArrayType; use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\Constant\ConstantIntegerType; use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\IntegerRangeType; use PHPStan\Type\ObjectType; +use PHPStan\Type\StringType; use PHPStan\Type\Type; use PHPStan\Type\UnionType; use PHPStan\Type\VerbosityLevel; +/** + * @covers \PHPStan\Analyser\MutatingScope + */ class ScopeTest extends PHPStanTestCase { @@ -248,4 +253,26 @@ public function testGetConstantType(): void $this->assertSame('int<1, max>', $type->describe(VerbosityLevel::precise())); } + public function testDefinedVariables(): void + { + /** @var ScopeFactory $scopeFactory */ + $scopeFactory = self::getContainer()->getByType(ScopeFactory::class); + $scope = $scopeFactory->create(ScopeContext::create('file.php')) + ->assignVariable('a', new ConstantStringType('a'), new StringType(), TrinaryLogic::createYes()) + ->assignVariable('b', new ConstantStringType('b'), new StringType(), TrinaryLogic::createMaybe()); + + $this->assertSame(['a'], $scope->getDefinedVariables()); + } + + public function testMaybeDefinedVariables(): void + { + /** @var ScopeFactory $scopeFactory */ + $scopeFactory = self::getContainer()->getByType(ScopeFactory::class); + $scope = $scopeFactory->create(ScopeContext::create('file.php')) + ->assignVariable('a', new ConstantStringType('a'), new StringType(), TrinaryLogic::createYes()) + ->assignVariable('b', new ConstantStringType('b'), new StringType(), TrinaryLogic::createMaybe()); + + $this->assertSame(['b'], $scope->getMaybeDefinedVariables()); + } + }