Updated Rector to commit 10c76b3d85cc21a8834cd8952ff47a6bbcbf5915

10c76b3d85 [TypeDeclaration] Add AddParamTypeSplFixedArrayRector (#3105)
This commit is contained in:
Tomas Votruba 2022-11-27 21:07:35 +00:00
parent b492db7306
commit f0d81253f6
13 changed files with 213 additions and 69 deletions

View File

@ -9,6 +9,7 @@ use Rector\TypeDeclaration\Rector\ArrowFunction\AddArrowFunctionReturnTypeRector
use Rector\TypeDeclaration\Rector\ClassMethod\AddArrayParamDocTypeRector;
use Rector\TypeDeclaration\Rector\ClassMethod\AddArrayReturnDocTypeRector;
use Rector\TypeDeclaration\Rector\ClassMethod\AddMethodCallBasedStrictParamTypeRector;
use Rector\TypeDeclaration\Rector\ClassMethod\AddParamTypeBasedOnPHPUnitDataProviderRector;
use Rector\TypeDeclaration\Rector\ClassMethod\AddReturnTypeDeclarationBasedOnParentClassMethodRector;
use Rector\TypeDeclaration\Rector\ClassMethod\AddVoidReturnTypeWhereNoReturnRector;
use Rector\TypeDeclaration\Rector\ClassMethod\ArrayShapeFromConstantArrayReturnRector;
@ -22,6 +23,7 @@ use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNativeCallRect
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictNewArrayRector;
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnTypeFromStrictTypedPropertyRector;
use Rector\TypeDeclaration\Rector\Closure\AddClosureReturnTypeRector;
use Rector\TypeDeclaration\Rector\FunctionLike\AddParamTypeSplFixedArrayRector;
use Rector\TypeDeclaration\Rector\FunctionLike\ParamTypeDeclarationRector;
use Rector\TypeDeclaration\Rector\FunctionLike\ReturnTypeDeclarationRector;
use Rector\TypeDeclaration\Rector\Param\ParamTypeFromStrictTypedPropertyRector;

View File

@ -1,4 +1,4 @@
# 403 Rules Overview
# 404 Rules Overview
<br>
@ -64,7 +64,7 @@
- [Transform](#transform) (34)
- [TypeDeclaration](#typedeclaration) (31)
- [TypeDeclaration](#typedeclaration) (32)
- [Visibility](#visibility) (3)
@ -8869,6 +8869,29 @@ return static function (RectorConfig $rectorConfig): void {
<br>
### AddParamTypeSplFixedArrayRector
Add exact fixed array type in known cases
- class: [`Rector\TypeDeclaration\Rector\FunctionLike\AddParamTypeSplFixedArrayRector`](../rules/TypeDeclaration/Rector/FunctionLike/AddParamTypeSplFixedArrayRector.php)
```diff
+use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;
class SomeClass
{
+ /**
+ * @param Tokens<Token>
+ */
public function run(Tokens $tokens)
{
}
}
```
<br>
### AddPropertyTypeDeclarationRector
Add type to property by added rules, mostly public/property by parent type

View File

@ -0,0 +1,116 @@
<?php
declare (strict_types=1);
namespace Rector\TypeDeclaration\Rector\FunctionLike;
use PhpParser\Node;
use PhpParser\Node\FunctionLike;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
use PHPStan\Type\Generic\GenericObjectType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeWithClassName;
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\TypeDeclaration\Rector\FunctionLike\AddParamTypeSplFixedArrayRector\AddParamTypeSplFixedArrayRectorTest
*/
final class AddParamTypeSplFixedArrayRector extends AbstractRector
{
/**
* @var array<string, string>
*/
private const SPL_FIXED_ARRAY_TO_SINGLE = ['PhpCsFixer\\Tokenizer\\Tokens' => 'PhpCsFixer\\Tokenizer\\Token', 'PhpCsFixer\\Doctrine\\Annotation\\Tokens' => 'PhpCsFixer\\Doctrine\\Annotation\\Token'];
/**
* @readonly
* @var \Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger
*/
private $phpDocTypeChanger;
public function __construct(PhpDocTypeChanger $phpDocTypeChanger)
{
$this->phpDocTypeChanger = $phpDocTypeChanger;
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [Function_::class, ClassMethod::class];
}
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Add exact fixed array type in known cases', [new CodeSample(<<<'CODE_SAMPLE'
use PhpCsFixer\Tokenizer\Tokens;
class SomeClass
{
public function run(Tokens $tokens)
{
}
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;
class SomeClass
{
/**
* @param Tokens<Token>
*/
public function run(Tokens $tokens)
{
}
}
CODE_SAMPLE
)]);
}
/**
* @param FunctionLike $node
*/
public function refactor(Node $node) : ?Node
{
if ($node->getParams() === []) {
return null;
}
$functionLikePhpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node);
foreach ($node->getParams() as $param) {
if ($param->type === null) {
continue;
}
$paramType = $this->nodeTypeResolver->getType($param->type);
if ($paramType->isSuperTypeOf(new ObjectType('SplFixedArray'))->no()) {
continue;
}
if (!$paramType instanceof TypeWithClassName) {
continue;
}
if ($paramType instanceof GenericObjectType) {
continue;
}
$genericParamType = $this->resolveGenericType($paramType);
if (!$genericParamType instanceof Type) {
continue;
}
$paramName = $this->getName($param);
$this->phpDocTypeChanger->changeParamType($functionLikePhpDocInfo, $genericParamType, $param, $paramName);
}
if ($functionLikePhpDocInfo->hasChanged()) {
return $node;
}
return null;
}
private function resolveGenericType(TypeWithClassName $typeWithClassName) : ?\PHPStan\Type\Generic\GenericObjectType
{
foreach (self::SPL_FIXED_ARRAY_TO_SINGLE as $fixedArrayClass => $singleClass) {
if ($typeWithClassName->getClassName() === $fixedArrayClass) {
$genericObjectType = new ObjectType($singleClass);
return new GenericObjectType($typeWithClassName->getClassName(), [$genericObjectType]);
}
}
return null;
}
}

View File

@ -1,37 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\TypeDeclaration\TypeInferer\ParamTypeInferer;
use PhpParser\Node\Param;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
use Rector\NodeTypeResolver\NodeTypeResolver;
use Rector\TypeDeclaration\Contract\TypeInferer\ParamTypeInfererInterface;
use Rector\TypeDeclaration\TypeInferer\SplArrayFixedTypeNarrower;
final class SplFixedArrayParamTypeInferer implements ParamTypeInfererInterface
{
/**
* @readonly
* @var \Rector\TypeDeclaration\TypeInferer\SplArrayFixedTypeNarrower
*/
private $splArrayFixedTypeNarrower;
/**
* @readonly
* @var \Rector\NodeTypeResolver\NodeTypeResolver
*/
private $nodeTypeResolver;
public function __construct(SplArrayFixedTypeNarrower $splArrayFixedTypeNarrower, NodeTypeResolver $nodeTypeResolver)
{
$this->splArrayFixedTypeNarrower = $splArrayFixedTypeNarrower;
$this->nodeTypeResolver = $nodeTypeResolver;
}
public function inferParam(Param $param) : Type
{
if ($param->type === null) {
return new MixedType();
}
$paramType = $this->nodeTypeResolver->getType($param->type);
return $this->splArrayFixedTypeNarrower->narrow($paramType);
}
}

View File

@ -17,12 +17,12 @@ final class VersionResolver
* @api
* @var string
*/
public const PACKAGE_VERSION = '48febdb978201ffdd2d62ccb970ede09c3160134';
public const PACKAGE_VERSION = '10c76b3d85cc21a8834cd8952ff47a6bbcbf5915';
/**
* @api
* @var string
*/
public const RELEASE_DATE = '2022-11-27 18:51:10';
public const RELEASE_DATE = '2022-11-27 22:03:08';
/**
* @var int
*/

2
vendor/autoload.php vendored
View File

@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) {
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitd188a1b0ebfa55c965020711b53facfb::getLoader();
return ComposerAutoloaderInit2e612febddb637cfcb0d9394c970d0b9::getLoader();

View File

@ -2715,6 +2715,7 @@ return array(
'Rector\\TypeDeclaration\\Rector\\ClassMethod\\ReturnTypeFromStrictNewArrayRector' => $baseDir . '/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictNewArrayRector.php',
'Rector\\TypeDeclaration\\Rector\\ClassMethod\\ReturnTypeFromStrictTypedPropertyRector' => $baseDir . '/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictTypedPropertyRector.php',
'Rector\\TypeDeclaration\\Rector\\Closure\\AddClosureReturnTypeRector' => $baseDir . '/rules/TypeDeclaration/Rector/Closure/AddClosureReturnTypeRector.php',
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddParamTypeSplFixedArrayRector' => $baseDir . '/rules/TypeDeclaration/Rector/FunctionLike/AddParamTypeSplFixedArrayRector.php',
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\ParamTypeDeclarationRector' => $baseDir . '/rules/TypeDeclaration/Rector/FunctionLike/ParamTypeDeclarationRector.php',
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\ReturnTypeDeclarationRector' => $baseDir . '/rules/TypeDeclaration/Rector/FunctionLike/ReturnTypeDeclarationRector.php',
'Rector\\TypeDeclaration\\Rector\\Param\\ParamTypeFromStrictTypedPropertyRector' => $baseDir . '/rules/TypeDeclaration/Rector/Param/ParamTypeFromStrictTypedPropertyRector.php',
@ -2738,7 +2739,6 @@ return array(
'Rector\\TypeDeclaration\\TypeInferer\\ParamTypeInferer\\FunctionLikeDocParamTypeInferer' => $baseDir . '/rules/TypeDeclaration/TypeInferer/ParamTypeInferer/FunctionLikeDocParamTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\ParamTypeInferer\\GetterNodeParamTypeInferer' => $baseDir . '/rules/TypeDeclaration/TypeInferer/ParamTypeInferer/GetterNodeParamTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\ParamTypeInferer\\PropertyNodeParamTypeInferer' => $baseDir . '/rules/TypeDeclaration/TypeInferer/ParamTypeInferer/PropertyNodeParamTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\ParamTypeInferer\\SplFixedArrayParamTypeInferer' => $baseDir . '/rules/TypeDeclaration/TypeInferer/ParamTypeInferer/SplFixedArrayParamTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\PropertyTypeInferer\\AllAssignNodePropertyTypeInferer' => $baseDir . '/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer/AllAssignNodePropertyTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\PropertyTypeInferer\\DefaultValuePropertyTypeInferer' => $baseDir . '/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer/DefaultValuePropertyTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\PropertyTypeInferer\\GetterTypeDeclarationPropertyTypeInferer' => $baseDir . '/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer/GetterTypeDeclarationPropertyTypeInferer.php',

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInitd188a1b0ebfa55c965020711b53facfb
class ComposerAutoloaderInit2e612febddb637cfcb0d9394c970d0b9
{
private static $loader;
@ -22,19 +22,19 @@ class ComposerAutoloaderInitd188a1b0ebfa55c965020711b53facfb
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInitd188a1b0ebfa55c965020711b53facfb', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit2e612febddb637cfcb0d9394c970d0b9', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInitd188a1b0ebfa55c965020711b53facfb', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit2e612febddb637cfcb0d9394c970d0b9', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInitd188a1b0ebfa55c965020711b53facfb::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInit2e612febddb637cfcb0d9394c970d0b9::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
$includeFiles = \Composer\Autoload\ComposerStaticInitd188a1b0ebfa55c965020711b53facfb::$files;
$includeFiles = \Composer\Autoload\ComposerStaticInit2e612febddb637cfcb0d9394c970d0b9::$files;
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequired188a1b0ebfa55c965020711b53facfb($fileIdentifier, $file);
composerRequire2e612febddb637cfcb0d9394c970d0b9($fileIdentifier, $file);
}
return $loader;
@ -46,7 +46,7 @@ class ComposerAutoloaderInitd188a1b0ebfa55c965020711b53facfb
* @param string $file
* @return void
*/
function composerRequired188a1b0ebfa55c965020711b53facfb($fileIdentifier, $file)
function composerRequire2e612febddb637cfcb0d9394c970d0b9($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;

View File

@ -4,7 +4,7 @@
namespace Composer\Autoload;
class ComposerStaticInitd188a1b0ebfa55c965020711b53facfb
class ComposerStaticInit2e612febddb637cfcb0d9394c970d0b9
{
public static $files = array (
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
@ -2960,6 +2960,7 @@ class ComposerStaticInitd188a1b0ebfa55c965020711b53facfb
'Rector\\TypeDeclaration\\Rector\\ClassMethod\\ReturnTypeFromStrictNewArrayRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictNewArrayRector.php',
'Rector\\TypeDeclaration\\Rector\\ClassMethod\\ReturnTypeFromStrictTypedPropertyRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/ClassMethod/ReturnTypeFromStrictTypedPropertyRector.php',
'Rector\\TypeDeclaration\\Rector\\Closure\\AddClosureReturnTypeRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/Closure/AddClosureReturnTypeRector.php',
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\AddParamTypeSplFixedArrayRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/FunctionLike/AddParamTypeSplFixedArrayRector.php',
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\ParamTypeDeclarationRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/FunctionLike/ParamTypeDeclarationRector.php',
'Rector\\TypeDeclaration\\Rector\\FunctionLike\\ReturnTypeDeclarationRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/FunctionLike/ReturnTypeDeclarationRector.php',
'Rector\\TypeDeclaration\\Rector\\Param\\ParamTypeFromStrictTypedPropertyRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/Param/ParamTypeFromStrictTypedPropertyRector.php',
@ -2983,7 +2984,6 @@ class ComposerStaticInitd188a1b0ebfa55c965020711b53facfb
'Rector\\TypeDeclaration\\TypeInferer\\ParamTypeInferer\\FunctionLikeDocParamTypeInferer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/TypeInferer/ParamTypeInferer/FunctionLikeDocParamTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\ParamTypeInferer\\GetterNodeParamTypeInferer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/TypeInferer/ParamTypeInferer/GetterNodeParamTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\ParamTypeInferer\\PropertyNodeParamTypeInferer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/TypeInferer/ParamTypeInferer/PropertyNodeParamTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\ParamTypeInferer\\SplFixedArrayParamTypeInferer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/TypeInferer/ParamTypeInferer/SplFixedArrayParamTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\PropertyTypeInferer\\AllAssignNodePropertyTypeInferer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer/AllAssignNodePropertyTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\PropertyTypeInferer\\DefaultValuePropertyTypeInferer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer/DefaultValuePropertyTypeInferer.php',
'Rector\\TypeDeclaration\\TypeInferer\\PropertyTypeInferer\\GetterTypeDeclarationPropertyTypeInferer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/TypeInferer/PropertyTypeInferer/GetterTypeDeclarationPropertyTypeInferer.php',
@ -3037,9 +3037,9 @@ class ComposerStaticInitd188a1b0ebfa55c965020711b53facfb
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInitd188a1b0ebfa55c965020711b53facfb::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInitd188a1b0ebfa55c965020711b53facfb::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInitd188a1b0ebfa55c965020711b53facfb::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInit2e612febddb637cfcb0d9394c970d0b9::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit2e612febddb637cfcb0d9394c970d0b9::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit2e612febddb637cfcb0d9394c970d0b9::$classMap;
}, null, ClassLoader::class);
}

View File

@ -685,17 +685,17 @@
},
{
"name": "phpstan\/phpdoc-parser",
"version": "1.13.1",
"version_normalized": "1.13.1.0",
"version": "1.14.0",
"version_normalized": "1.14.0.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/phpstan\/phpdoc-parser.git",
"reference": "aac44118344d197e6d5f7c6cee91885f0a89acdd"
"reference": "df1a79430e14e30cd192fe6c05842133d076e58d"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/phpstan\/phpdoc-parser\/zipball\/aac44118344d197e6d5f7c6cee91885f0a89acdd",
"reference": "aac44118344d197e6d5f7c6cee91885f0a89acdd",
"url": "https:\/\/api.github.com\/repos\/phpstan\/phpdoc-parser\/zipball\/df1a79430e14e30cd192fe6c05842133d076e58d",
"reference": "df1a79430e14e30cd192fe6c05842133d076e58d",
"shasum": ""
},
"require": {
@ -710,7 +710,7 @@
"phpunit\/phpunit": "^9.5",
"symfony\/process": "^5.2"
},
"time": "2022-11-20T08:52:26+00:00",
"time": "2022-11-27T19:09:16+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -727,7 +727,7 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https:\/\/github.com\/phpstan\/phpdoc-parser\/issues",
"source": "https:\/\/github.com\/phpstan\/phpdoc-parser\/tree\/1.13.1"
"source": "https:\/\/github.com\/phpstan\/phpdoc-parser\/tree\/1.14.0"
},
"install-path": "..\/phpstan\/phpdoc-parser"
},

File diff suppressed because one or more lines are too long

View File

@ -5,20 +5,39 @@ namespace PHPStan\PhpDocParser\Ast\Type;
use PHPStan\PhpDocParser\Ast\NodeAttributes;
use function implode;
use function sprintf;
class GenericTypeNode implements \PHPStan\PhpDocParser\Ast\Type\TypeNode
{
public const VARIANCE_INVARIANT = 'invariant';
public const VARIANCE_COVARIANT = 'covariant';
public const VARIANCE_CONTRAVARIANT = 'contravariant';
public const VARIANCE_BIVARIANT = 'bivariant';
use NodeAttributes;
/** @var IdentifierTypeNode */
public $type;
/** @var TypeNode[] */
public $genericTypes;
public function __construct(\PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode $type, array $genericTypes)
/** @var (self::VARIANCE_*)[] */
public $variances;
public function __construct(\PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode $type, array $genericTypes, array $variances = [])
{
$this->type = $type;
$this->genericTypes = $genericTypes;
$this->variances = $variances;
}
public function __toString() : string
{
return $this->type . '<' . implode(', ', $this->genericTypes) . '>';
$genericTypes = [];
foreach ($this->genericTypes as $index => $type) {
$variance = $this->variances[$index] ?? self::VARIANCE_INVARIANT;
if ($variance === self::VARIANCE_INVARIANT) {
$genericTypes[] = (string) $type;
} elseif ($variance === self::VARIANCE_BIVARIANT) {
$genericTypes[] = '*';
} else {
$genericTypes[] = sprintf('%s %s', $variance, $type);
}
}
return $this->type . '<' . implode(', ', $genericTypes) . '>';
}
}

View File

@ -238,20 +238,41 @@ class TypeParser
{
$tokens->consumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET);
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
$genericTypes = [$this->parse($tokens)];
$genericTypes = [];
$variances = [];
[$genericTypes[], $variances[]] = $this->parseGenericTypeArgument($tokens);
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) {
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET)) {
// trailing comma case
return new Ast\Type\GenericTypeNode($baseType, $genericTypes);
return new Ast\Type\GenericTypeNode($baseType, $genericTypes, $variances);
}
$genericTypes[] = $this->parse($tokens);
[$genericTypes[], $variances[]] = $this->parseGenericTypeArgument($tokens);
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
}
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET);
return new Ast\Type\GenericTypeNode($baseType, $genericTypes);
return new Ast\Type\GenericTypeNode($baseType, $genericTypes, $variances);
}
/**
* @phpstan-impure
* @return array{Ast\Type\TypeNode, Ast\Type\GenericTypeNode::VARIANCE_*}
*/
public function parseGenericTypeArgument(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens) : array
{
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_WILDCARD)) {
return [new Ast\Type\IdentifierTypeNode('mixed'), Ast\Type\GenericTypeNode::VARIANCE_BIVARIANT];
}
if ($tokens->tryConsumeTokenValue('contravariant')) {
$variance = Ast\Type\GenericTypeNode::VARIANCE_CONTRAVARIANT;
} elseif ($tokens->tryConsumeTokenValue('covariant')) {
$variance = Ast\Type\GenericTypeNode::VARIANCE_COVARIANT;
} else {
$variance = Ast\Type\GenericTypeNode::VARIANCE_INVARIANT;
}
$type = $this->parse($tokens);
return [$type, $variance];
}
/** @phpstan-impure */
private function parseCallable(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens, Ast\Type\IdentifierTypeNode $identifier) : Ast\Type\TypeNode