Skip to content

Commit

Permalink
str_pad() function return type extension
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Jul 15, 2021
1 parent 4f9488e commit 84503ce
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 0 deletions.
5 changes: 5 additions & 0 deletions conf/config.neon
Original file line number Diff line number Diff line change
Expand Up @@ -1265,6 +1265,11 @@ services:
tags:
- phpstan.broker.dynamicFunctionReturnTypeExtension

-
class: PHPStan\Type\Php\StrPadFunctionReturnTypeExtension
tags:
- phpstan.broker.dynamicFunctionReturnTypeExtension

-
class: PHPStan\Type\Php\ParseUrlFunctionDynamicReturnTypeExtension
tags:
Expand Down
53 changes: 53 additions & 0 deletions src/Type/Php/StrPadFunctionReturnTypeExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php declare(strict_types = 1);

namespace PHPStan\Type\Php;

use PhpParser\Node\Expr\FuncCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Type\Accessory\AccessoryNonEmptyStringType;
use PHPStan\Type\DynamicFunctionReturnTypeExtension;
use PHPStan\Type\IntegerRangeType;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\StringType;

class StrPadFunctionReturnTypeExtension implements DynamicFunctionReturnTypeExtension
{

public function isFunctionSupported(FunctionReflection $functionReflection): bool
{
return $functionReflection->getName() === 'str_pad';
}

public function getTypeFromFunctionCall(
FunctionReflection $functionReflection,
FuncCall $functionCall,
Scope $scope
): \PHPStan\Type\Type
{
$args = $functionCall->args;
if (count($args) < 2) {
return new StringType();
}

$inputType = $scope->getType($args[0]->value);
$lengthType = $scope->getType($args[1]->value);

if ($inputType->isNonEmptyString()->yes()) {
return new IntersectionType([
new StringType(),
new AccessoryNonEmptyStringType(),
]);
}

if (IntegerRangeType::fromInterval(1, null)->isSuperTypeOf($lengthType)->yes()) {
return new IntersectionType([
new StringType(),
new AccessoryNonEmptyStringType(),
]);
}

return new StringType();
}

}
5 changes: 5 additions & 0 deletions tests/PHPStan/Analyser/data/non-empty-string.php
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,11 @@ public function doFoo(string $s, string $nonEmpty)
assertType('0', strlen(''));
assertType('int<0, max>', strlen($s));
assertType('int<1, max>', strlen($nonEmpty));

assertType('non-empty-string', str_pad($nonEmpty, 0));
assertType('non-empty-string', str_pad($nonEmpty, 1));
assertType('string', str_pad($s, 0));
assertType('non-empty-string', str_pad($s, 1));
}

}

0 comments on commit 84503ce

Please sign in to comment.