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 17, 2024
1 parent 0b78c55 commit 9685155
Show file tree
Hide file tree
Showing 4 changed files with 752 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 @@ -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
71 changes: 71 additions & 0 deletions src/Type/Php/SetTypeFunctionTypeSpecifyingExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?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) {
switch ($constantString->getValue()) {
case 'bool':
case 'boolean':
$types[] = $valueType->toBoolean();
break;
case 'int':
case 'integer':
$types[] = $valueType->toInteger();
break;
case 'float':
case 'double':
$types[] = $valueType->toFloat();
break;
case 'string':
$types[] = $valueType->toString();
break;
case 'array':
$types[] = $valueType->toArray();
break;
case 'object':
$types[] = new ObjectType(stdClass::class);
break;
case 'null':
$types[] = new NullType();
break;
default:
$types[] = new ErrorType();
}
}

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

}
3 changes: 3 additions & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class NodeScopeResolverTest extends TypeInferenceTestCase

public function dataFileAsserts(): iterable
{
yield from $this->gatherAssertTypes(__DIR__ . '/data/set-type-type-specifying.php');
return;
require_once __DIR__ . '/data/implode.php';

Check failure on line 20 in tests/PHPStan/Analyser/NodeScopeResolverTest.php

View workflow job for this annotation

GitHub Actions / PHPStan with result cache (8.1)

Unreachable statement - code above always terminates.

Check failure on line 20 in tests/PHPStan/Analyser/NodeScopeResolverTest.php

View workflow job for this annotation

GitHub Actions / PHPStan with result cache (8.3)

Unreachable statement - code above always terminates.

Check failure on line 20 in tests/PHPStan/Analyser/NodeScopeResolverTest.php

View workflow job for this annotation

GitHub Actions / PHPStan with result cache (8.2)

Unreachable statement - code above always terminates.

Check failure on line 20 in tests/PHPStan/Analyser/NodeScopeResolverTest.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1, ubuntu-latest)

Unreachable statement - code above always terminates.

Check failure on line 20 in tests/PHPStan/Analyser/NodeScopeResolverTest.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.2, ubuntu-latest)

Unreachable statement - code above always terminates.

Check failure on line 20 in tests/PHPStan/Analyser/NodeScopeResolverTest.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.3, ubuntu-latest)

Unreachable statement - code above always terminates.

Check failure on line 20 in tests/PHPStan/Analyser/NodeScopeResolverTest.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, ubuntu-latest)

Unreachable statement - code above always terminates.

Check failure on line 20 in tests/PHPStan/Analyser/NodeScopeResolverTest.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.4, ubuntu-latest)

Unreachable statement - code above always terminates.

Check failure on line 20 in tests/PHPStan/Analyser/NodeScopeResolverTest.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.3, ubuntu-latest)

Unreachable statement - code above always terminates.

Check failure on line 20 in tests/PHPStan/Analyser/NodeScopeResolverTest.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.2, ubuntu-latest)

Unreachable statement - code above always terminates.

Check failure on line 20 in tests/PHPStan/Analyser/NodeScopeResolverTest.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.2, windows-latest)

Unreachable statement - code above always terminates.

Check failure on line 20 in tests/PHPStan/Analyser/NodeScopeResolverTest.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.3, windows-latest)

Unreachable statement - code above always terminates.

Check failure on line 20 in tests/PHPStan/Analyser/NodeScopeResolverTest.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1, windows-latest)

Unreachable statement - code above always terminates.

Check failure on line 20 in tests/PHPStan/Analyser/NodeScopeResolverTest.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0, windows-latest)

Unreachable statement - code above always terminates.

Check failure on line 20 in tests/PHPStan/Analyser/NodeScopeResolverTest.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.4, windows-latest)

Unreachable statement - code above always terminates.

Check failure on line 20 in tests/PHPStan/Analyser/NodeScopeResolverTest.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.3, windows-latest)

Unreachable statement - code above always terminates.

Check failure on line 20 in tests/PHPStan/Analyser/NodeScopeResolverTest.php

View workflow job for this annotation

GitHub Actions / PHPStan (7.2, windows-latest)

Unreachable statement - code above always terminates.
yield from $this->gatherAssertTypes(__DIR__ . '/data/implode.php');

Expand Down Expand Up @@ -1431,6 +1433,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 9685155

Please sign in to comment.