Skip to content

Commit

Permalink
Variadic parameters in PHP8 can have int|string key
Browse files Browse the repository at this point in the history
  • Loading branch information
canvural committed Oct 20, 2021
1 parent 2c11075 commit e6514e7
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 6 deletions.
8 changes: 7 additions & 1 deletion src/Analyser/DirectScopeFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use PHPStan\DependencyInjection\Container;
use PHPStan\DependencyInjection\Type\DynamicReturnTypeExtensionRegistryProvider;
use PHPStan\DependencyInjection\Type\OperatorTypeSpecifyingExtensionRegistryProvider;
use PHPStan\Php\PhpVersion;
use PHPStan\Reflection\ParametersAcceptor;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Properties\PropertyReflectionFinder;
Expand Down Expand Up @@ -39,6 +40,8 @@ class DirectScopeFactory implements ScopeFactory
/** @var string[] */
private array $dynamicConstantNames;

private PhpVersion $phpVersion;

public function __construct(
string $scopeClass,
ReflectionProvider $reflectionProvider,
Expand All @@ -50,7 +53,8 @@ public function __construct(
\PHPStan\Parser\Parser $parser,
NodeScopeResolver $nodeScopeResolver,
bool $treatPhpDocTypesAsCertain,
Container $container
Container $container,
PhpVersion $phpVersion
)
{
$this->scopeClass = $scopeClass;
Expand All @@ -64,6 +68,7 @@ public function __construct(
$this->nodeScopeResolver = $nodeScopeResolver;
$this->treatPhpDocTypesAsCertain = $treatPhpDocTypesAsCertain;
$this->dynamicConstantNames = $container->getParameter('dynamicConstantNames');
$this->phpVersion = $phpVersion;
}

/**
Expand Down Expand Up @@ -121,6 +126,7 @@ public function create(
$this->parser,
$this->nodeScopeResolver,
$context,
$this->phpVersion,
$declareStrictTypes,
$constantTypes,
$function,
Expand Down
2 changes: 2 additions & 0 deletions src/Analyser/LazyScopeFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use PHPStan\DependencyInjection\Container;
use PHPStan\DependencyInjection\Type\DynamicReturnTypeExtensionRegistryProvider;
use PHPStan\DependencyInjection\Type\OperatorTypeSpecifyingExtensionRegistryProvider;
use PHPStan\Php\PhpVersion;
use PHPStan\Reflection\ParametersAcceptor;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Properties\PropertyReflectionFinder;
Expand Down Expand Up @@ -89,6 +90,7 @@ public function create(
$this->container->getService('currentPhpVersionSimpleParser'),
$this->container->getByType(NodeScopeResolver::class),
$context,
$this->container->getByType(PhpVersion::class),
$declareStrictTypes,
$constantTypes,
$function,
Expand Down
13 changes: 12 additions & 1 deletion src/Analyser/MutatingScope.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use PhpParser\NodeFinder;
use PHPStan\Node\ExecutionEndNode;
use PHPStan\Parser\Parser;
use PHPStan\Php\PhpVersion;
use PHPStan\Reflection\ClassConstantReflection;
use PHPStan\Reflection\ClassMemberReflection;
use PHPStan\Reflection\ClassReflection;
Expand Down Expand Up @@ -132,6 +133,8 @@ class MutatingScope implements Scope

private \PHPStan\Analyser\ScopeContext $context;

private PhpVersion $phpVersion;

/** @var \PHPStan\Type\Type[] */
private array $resolvedTypes = [];

Expand Down Expand Up @@ -189,6 +192,7 @@ class MutatingScope implements Scope
* @param Parser $parser
* @param NodeScopeResolver $nodeScopeResolver
* @param \PHPStan\Analyser\ScopeContext $context
* @param PhpVersion $phpVersion
* @param bool $declareStrictTypes
* @param array<string, Type> $constantTypes
* @param \PHPStan\Reflection\FunctionReflection|MethodReflection|null $function
Expand Down Expand Up @@ -218,6 +222,7 @@ public function __construct(
Parser $parser,
NodeScopeResolver $nodeScopeResolver,
ScopeContext $context,
PhpVersion $phpVersion,
bool $declareStrictTypes = false,
array $constantTypes = [],
$function = null,
Expand Down Expand Up @@ -251,6 +256,7 @@ public function __construct(
$this->parser = $parser;
$this->nodeScopeResolver = $nodeScopeResolver;
$this->context = $context;
$this->phpVersion = $phpVersion;
$this->declareStrictTypes = $declareStrictTypes;
$this->constantTypes = $constantTypes;
$this->function = $function;
Expand Down Expand Up @@ -2384,6 +2390,7 @@ public function doNotTreatPhpDocTypesAsCertain(): Scope
$this->parser,
$this->nodeScopeResolver,
$this->context,
$this->phpVersion,
$this->declareStrictTypes,
$this->constantTypes,
$this->function,
Expand Down Expand Up @@ -2954,7 +2961,11 @@ private function enterFunctionLike(
foreach (ParametersAcceptorSelector::selectSingle($functionReflection->getVariants())->getParameters() as $parameter) {
$parameterType = $parameter->getType();
if ($parameter->isVariadic()) {
$parameterType = new ArrayType(new IntegerType(), $parameterType);
if ($this->phpVersion->supportsNamedArguments()) {
$parameterType = new ArrayType(new BenevolentUnionType([new IntegerType(), new StringType()]), $parameterType);
} else {
$parameterType = new ArrayType(new IntegerType(), $parameterType);
}
}
$variableTypes[$parameter->getName()] = VariableTypeHolder::createYes($parameterType);
$nativeExpressionTypes[sprintf('$%s', $parameter->getName())] = $parameter->getNativeType();
Expand Down
4 changes: 3 additions & 1 deletion src/Testing/PHPStanTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use PHPStan\DependencyInjection\Type\OperatorTypeSpecifyingExtensionRegistryProvider;
use PHPStan\File\FileHelper;
use PHPStan\Parser\Parser;
use PHPStan\Php\PhpVersion;
use PHPStan\PhpDoc\TypeNodeResolver;
use PHPStan\PhpDoc\TypeStringResolver;
use PHPStan\Reflection\ReflectionProvider;
Expand Down Expand Up @@ -131,7 +132,8 @@ public function createScopeFactory(ReflectionProvider $reflectionProvider, TypeS
$this->getParser(),
self::getContainer()->getByType(NodeScopeResolver::class),
$this->shouldTreatPhpDocTypesAsCertain(),
$container
$container,
$container->getByType(PhpVersion::class)
);
}

Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/LegacyNodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1284,7 +1284,7 @@ public function dataParameterTypes(): array
'$callable',
],
[
'array<int, string>',
PHP_VERSION_ID < 80000 ? 'array<int, string>' : 'array<string>',
'$variadicStrings',
],
[
Expand Down
12 changes: 10 additions & 2 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/data/catch-without-variable.php');
}
yield from $this->gatherAssertTypes(__DIR__ . '/data/mixed-typehint.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-2600.php');
if (PHP_VERSION_ID < 80000) {
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-2600.php');
}
yield from $this->gatherAssertTypes(__DIR__ . '/data/array-typehint-without-null-in-phpdoc.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/override-root-scope-variable.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bitwise-not.php');
Expand Down Expand Up @@ -427,7 +429,9 @@ public function dataFileAsserts(): iterable

if (self::$useStaticReflectionProvider || PHP_VERSION_ID >= 70400) {
yield from $this->gatherAssertTypes(__DIR__ . '/data/arrow-function-types.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-4902.php');
if (PHP_VERSION_ID < 80000) {
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-4902.php');
}
}

yield from $this->gatherAssertTypes(__DIR__ . '/data/closure-types.php');
Expand Down Expand Up @@ -508,6 +512,10 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-4741.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/more-type-strings.php');

if (PHP_VERSION_ID >= 80000) {
yield from $this->gatherAssertTypes(__DIR__ . '/data/variadic-parameter-php8.php');
}

yield from $this->gatherAssertTypes(__DIR__ . '/data/eval-implicit-throw.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-5628.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-5501.php');
Expand Down
18 changes: 18 additions & 0 deletions tests/PHPStan/Analyser/data/variadic-parameter-php8.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace VariadicParameterPHP8;

use function PHPStan\Testing\assertType;

function foo(...$args)
{
assertType('array', $args);
assertType('mixed', $args['foo']);
assertType('mixed', $args['bar']);
}

function bar(string ...$args)
{
assertType('array<string>', $args);
}

0 comments on commit e6514e7

Please sign in to comment.