Skip to content

Commit

Permalink
infer non-empty-string on substr() comparison with constant string
Browse files Browse the repository at this point in the history
infer non-empty-string on substr() comparison with constant string

try reducing unnecessary work

cs
  • Loading branch information
clxmstaab committed May 16, 2022
1 parent e46c6d3 commit a24da7e
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/Analyser/TypeSpecifier.php
Expand Up @@ -242,6 +242,27 @@ 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() !== ''
) {
$argType = $scope->getType($exprNode->getArgs()[0]->value);

if ($argType->isString()->yes() && !$argType->isNonEmptyString()->yes()) {
return $this->create(
$exprNode->getArgs()[0]->value,
TypeCombinator::intersect($argType, new AccessoryNonEmptyStringType()),
$context,
false,
$scope,
);
}
}
}

$rightType = $scope->getType($expr->right);
Expand Down
1 change: 1 addition & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Expand Up @@ -911,6 +911,7 @@ public function dataFileAsserts(): iterable
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/bug-6609.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/non-empty-string-substr-specifying.php');
}

/**
Expand Down
63 changes: 63 additions & 0 deletions tests/PHPStan/Analyser/data/non-empty-string-substr-specifying.php
@@ -0,0 +1,63 @@
<?php

namespace NonEmptyStringSubstr;

use function PHPStan\Testing\assertType;

class Foo {
public function nonEmptySubstr(string $s, int $offset, int $length): void
{
if (substr($s, 10) === 'hallo') {
assertType('non-empty-string', $s);
}
assertType('string', $s);

if (substr($s, -10) === 'hallo') {
assertType('non-empty-string', $s);
}
assertType('string', $s);

if (substr($s, 10, 5) === 'hallo') {
assertType('non-empty-string', $s);
}
assertType('string', $s);

if (substr($s, 10, -5) === 'hallo') {
assertType('non-empty-string', $s);
}
assertType('string', $s);

if (substr($s, $offset) === 'hallo') {
assertType('non-empty-string', $s);
}
assertType('string', $s);

if (substr($s, $offset, $length) === 'hallo') {
assertType('non-empty-string', $s);
}
assertType('string', $s);

if (substr($s, $offset, $length) !== 'hallo') {
assertType('string', $s);
}
assertType('string', $s);

if (substr($s, $offset, $length) === '') {
assertType('string', $s);
}
assertType('string', $s);

if (substr($s, $offset, $length) == '') {
assertType('string', $s);
}
assertType('string', $s);

$x = (substr($s, 10) === 'hallo');
assertType('string', $s);
var_dump($x);

$x = (substr($s, 10) !== 'hallo');
assertType('string', $s);
var_dump($x);
}
}

0 comments on commit a24da7e

Please sign in to comment.