Skip to content

Commit

Permalink
get_defined_vars() return type contains know variables
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinMystikJonas committed Nov 11, 2024
1 parent 71d01d6 commit 5eea5cb
Show file tree
Hide file tree
Showing 3 changed files with 71 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 @@ -1427,6 +1427,11 @@ services:
tags:
- phpstan.broker.dynamicFunctionReturnTypeExtension

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

-
class: PHPStan\Type\Php\GetParentClassDynamicFunctionReturnTypeExtension
tags:
Expand Down
55 changes: 55 additions & 0 deletions src/Type/Php/GetDefinedVarsFunctionReturnTypeExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?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\ArrayType;
use PHPStan\Type\Constant\ConstantArrayType;
use PHPStan\Type\Constant\ConstantStringType;
use PHPStan\Type\DynamicFunctionReturnTypeExtension;
use PHPStan\Type\MixedType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use function array_filter;
use function array_map;
use function array_values;

// based on code by @ruudk
final class GetDefinedVarsFunctionReturnTypeExtension implements DynamicFunctionReturnTypeExtension
{

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

public function getTypeFromFunctionCall(FunctionReflection $functionReflection, FuncCall $functionCall, Scope $scope): Type
{
if ($scope->canAnyVariableExist()) {
return new ArrayType(
new StringType(),
new MixedType(),
);
}

$variables = array_values(array_filter(
$scope->getDefinedVariables(),
static fn ($variable) => $variable !== 'this',
));

$keys = array_map(
static fn ($variable) => new ConstantStringType($variable),
$variables,
);

$values = array_map(
static fn ($variable) => $scope->getVariableType($variable),
$variables,
);

return new ConstantArrayType($keys, $values);
}

}
11 changes: 11 additions & 0 deletions tests/PHPStan/Analyser/nsrt/get-defined-vars.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace GetDefinedVars;

use function PHPStan\Testing\assertType;

function doFoo(int $param) {
$local = "foo";
assertType('array{param: int, local: \'foo\'}', get_defined_vars());
assertType('array{\'param\', \'local\'}', array_keys(get_defined_vars()));
}

0 comments on commit 5eea5cb

Please sign in to comment.