Skip to content

Commit

Permalink
Adds type specifier for settype.
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisBrenton committed Feb 16, 2024
1 parent 0b78c55 commit f5f7545
Show file tree
Hide file tree
Showing 4 changed files with 570 additions and 0 deletions.
5 changes: 5 additions & 0 deletions conf/config.neon
Expand Up @@ -1528,6 +1528,11 @@ services:
tags:
- phpstan.broker.dynamicFunctionReturnTypeExtension

-
class: PHPStan\Type\Php\SetTypeFunctionTypeSpecifyingExtension
tags:
- phpstan.typeSpecifier.functionTypeSpecifyingExtension

-
class: PHPStan\Type\Php\StrCaseFunctionsReturnTypeExtension
tags:
Expand Down
53 changes: 53 additions & 0 deletions src/Type/Php/SetTypeFunctionTypeSpecifyingExtension.php
@@ -0,0 +1,53 @@
<?php declare(strict_types = 1);

namespace PHPStan\Type\Php;

use PhpParser\Node\Expr\FuncCall;
use PHPStan\Analyser\Scope;
use PHPStan\Analyser\SpecifiedTypes;
use PHPStan\Analyser\TypeSpecifierContext;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Type\ErrorType;
use PHPStan\Type\FunctionTypeSpecifyingExtension;
use PHPStan\Type\NullType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\TypeCombinator;
use stdClass;
use function count;
use function strtolower;

class SetTypeFunctionTypeSpecifyingExtension implements FunctionTypeSpecifyingExtension
{

public function isFunctionSupported(FunctionReflection $functionReflection, FuncCall $node, TypeSpecifierContext $context): bool
{
return strtolower($functionReflection->getName()) === 'settype'
&& count($node->getArgs()) > 1;
}

public function specifyTypes(FunctionReflection $functionReflection, FuncCall $node, Scope $scope, TypeSpecifierContext $context): SpecifiedTypes
{
$value = $node->getArgs()[0]->value;
$valueType = $scope->getType($value);
$castType = $scope->getType($node->getArgs()[1]->value);

$constantStrings = $castType->getConstantStrings();
$types = [];

foreach ($constantStrings as $constantString) {
$types[] = match ($constantString->getValue()) {
'bool', 'boolean' => $valueType->toBoolean(),
'int', 'integer' => $valueType->toInteger(),
'float', 'double' => $valueType->toFloat(),
'string' => $valueType->toString(),
'array' => $valueType->toArray(),
'object' => new ObjectType(stdClass::class),
'null' => new NullType(),
default => new ErrorType()
};
}

return new SpecifiedTypes(['$value' => [$value, TypeCombinator::union(...$types)]], [], true);
}

}
1 change: 1 addition & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Expand Up @@ -1431,6 +1431,7 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/data/assert-inheritance.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-9123.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-10037.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/set-type-type-specifying.php');
}

/**
Expand Down

0 comments on commit f5f7545

Please sign in to comment.