Skip to content

Commit

Permalink
RexFunctionsDynamicReturnTypeExtension - fix default arg handling (#678)
Browse files Browse the repository at this point in the history
* RexFunctionsDynamicReturnTypeExtension - fix default arg handling

* fix

* Union test

---------

Co-authored-by: Markus Staab <[email protected]>
  • Loading branch information
gharlan and staabm authored Mar 16, 2024
1 parent dab2289 commit d55091f
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 10 deletions.
10 changes: 7 additions & 3 deletions lib/extension/RexFunctionsDynamicReturnTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Scalar\String_;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Reflection\MethodReflection;
Expand Down Expand Up @@ -74,14 +75,17 @@ private function getType(array $args, Scope $scope): ?Type
return null;
}

$defaultArgType = new ConstantStringType('');
$results = [];
if (count($args) >= 3) {
$defaultArgType = $scope->getType($args[2]->value);
$defaultArgTypeStrings = $defaultArgType->getConstantStrings();
if (count($defaultArgTypeStrings) !== 1 || $defaultArgTypeStrings[0]->getValue() !== '') {
$results[] = $defaultArgType;
}
}

$typeStrings = $scope->getType($args[1]->value)->getConstantStrings();
if (count($typeStrings) > 0) {
$results = [];
foreach ($typeStrings as $typeString) {
$resolvedType = $this->resolveTypeFromString($typeString->getValue());
if ($resolvedType === null) {
Expand All @@ -91,7 +95,7 @@ private function getType(array $args, Scope $scope): ?Type
$results[] = $resolvedType;
}

return TypeCombinator::union($defaultArgType, ...$results);
return TypeCombinator::union(...$results);
}

return null;
Expand Down
22 changes: 15 additions & 7 deletions tests/data/rex-sapi.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,19 @@ function doBar()
function doFooBar()
{
assertType('string', rex_get('HTTP_REFERER', 'string', ''));
assertType("''|int", rex_get('HTTP_REFERER', 'int', ''));
assertType("''|int", rex_get('HTTP_REFERER', 'integer', ''));
assertType("''|float", rex_get('HTTP_REFERER', 'float', ''));
assertType("''|float", rex_get('HTTP_REFERER', 'double', ''));
assertType("''|float", rex_get('HTTP_REFERER', 'real', ''));
assertType("''|bool", rex_get('HTTP_REFERER', 'bool', ''));
assertType("''|bool", rex_get('HTTP_REFERER', 'boolean', ''));
assertType('int', rex_get('HTTP_REFERER', 'int', ''));
assertType('int', rex_get('HTTP_REFERER', 'integer', ''));
assertType('float', rex_get('HTTP_REFERER', 'float', ''));
assertType('float', rex_get('HTTP_REFERER', 'double', ''));
assertType('float', rex_get('HTTP_REFERER', 'real', ''));
assertType('bool', rex_get('HTTP_REFERER', 'bool', ''));
assertType('bool', rex_get('HTTP_REFERER', 'boolean', ''));
}

function doQux()
{
assertType('int', rex_get('HTTP_REFERER', 'int', 1));
assertType('int|null', rex_get('HTTP_REFERER', 'int', null));
assertType("'foo'|int", rex_get('HTTP_REFERER', 'int', 'foo'));
assertType("'foo'|int", rex_get('HTTP_REFERER', 'int', rand(0,1) ? 'foo' : ''));
}

0 comments on commit d55091f

Please sign in to comment.