From a862bcdbcf5263cdaa78575554cfcd08f773e043 Mon Sep 17 00:00:00 2001 From: Markus Staab Date: Sun, 27 Mar 2022 21:05:56 +0200 Subject: [PATCH] infer non-empty-string on substr() comparison with constant string --- src/Analyser/TypeSpecifier.php | 19 +++++++ .../Analyser/NodeScopeResolverTest.php | 1 + .../non-empty-string-substr-specifying.php | 56 +++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 tests/PHPStan/Analyser/data/non-empty-string-substr-specifying.php diff --git a/src/Analyser/TypeSpecifier.php b/src/Analyser/TypeSpecifier.php index da3cbca409f..3df7d26fb67 100644 --- a/src/Analyser/TypeSpecifier.php +++ b/src/Analyser/TypeSpecifier.php @@ -58,6 +58,7 @@ use PHPStan\Type\TypeUtils; use PHPStan\Type\TypeWithClassName; use PHPStan\Type\UnionType; +use PHPStan\Type\VerbosityLevel; use function array_merge; use function array_reverse; use function count; @@ -242,6 +243,24 @@ public function specifyTypesInCondition( } } } + + if ( + $exprNode instanceof FuncCall + && $exprNode->name instanceof Name + && strtolower($exprNode->name->toString()) === 'substr' + && isset($exprNode->getArgs()[0]) + && $constantType instanceof ConstantStringType + && $constantType->getValue() !== '' + && $scope->getType($exprNode->getArgs()[0]->value)->isString()->yes() + ) { + return $this->create( + $exprNode->getArgs()[0]->value, + TypeCombinator::intersect($scope->getType($exprNode->getArgs()[0]->value), new AccessoryNonEmptyStringType()), + $context, + false, + $scope + ); + } } $rightType = $scope->getType($expr->right); diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index 92b3dd7059b..558fd50f811 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -903,6 +903,7 @@ public function dataFileAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7115.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/constant-array-type-identical.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/non-empty-string-str-containing-fns.php'); + yield from $this->gatherAssertTypes(__DIR__ . '/data/non-empty-string-substr-specifying.php'); } /** diff --git a/tests/PHPStan/Analyser/data/non-empty-string-substr-specifying.php b/tests/PHPStan/Analyser/data/non-empty-string-substr-specifying.php new file mode 100644 index 00000000000..6c10dab1306 --- /dev/null +++ b/tests/PHPStan/Analyser/data/non-empty-string-substr-specifying.php @@ -0,0 +1,56 @@ +