mirror of https://github.com/rectorphp/rector.git
Updated Rector to commit 965b5f72045e3a94adf1eab83accafb52bfbe92a
965b5f7204
[CodeQuality] Exclude first class callable from IntvalToTypeCastRector (#7962) (#4040)
This commit is contained in:
parent
ed61663929
commit
8f92523b3a
|
@ -61,6 +61,9 @@ CODE_SAMPLE
|
|||
return null;
|
||||
}
|
||||
}
|
||||
if ($node->isFirstClassCallable()) {
|
||||
return null;
|
||||
}
|
||||
if (!isset($node->getArgs()[0])) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -19,12 +19,12 @@ final class VersionResolver
|
|||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const PACKAGE_VERSION = '1e4568bdae763335c904ecd3d03a79f1ac129d0f';
|
||||
public const PACKAGE_VERSION = '965b5f72045e3a94adf1eab83accafb52bfbe92a';
|
||||
/**
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const RELEASE_DATE = '2023-06-01 14:44:59';
|
||||
public const RELEASE_DATE = '2023-06-02 05:28:59';
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
|
|
|
@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) {
|
|||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInite64ea2605e4cf1002a60a3421b5e8329::getLoader();
|
||||
return ComposerAutoloaderInit01745356043e4be75950b3ce39d012e4::getLoader();
|
||||
|
|
|
@ -30,6 +30,11 @@ return array(
|
|||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagPropertyValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagPropertyValueNode.php',
|
||||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagValueNode.php',
|
||||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\DeprecatedTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php',
|
||||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineAnnotation' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php',
|
||||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArgument' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php',
|
||||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArray' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php',
|
||||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArrayItem' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php',
|
||||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php',
|
||||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ExtendsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.php',
|
||||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\GenericTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php',
|
||||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ImplementsTagValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.php',
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInite64ea2605e4cf1002a60a3421b5e8329
|
||||
class ComposerAutoloaderInit01745356043e4be75950b3ce39d012e4
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
|
@ -22,17 +22,17 @@ class ComposerAutoloaderInite64ea2605e4cf1002a60a3421b5e8329
|
|||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInite64ea2605e4cf1002a60a3421b5e8329', 'loadClassLoader'), true, true);
|
||||
spl_autoload_register(array('ComposerAutoloaderInit01745356043e4be75950b3ce39d012e4', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInite64ea2605e4cf1002a60a3421b5e8329', 'loadClassLoader'));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInit01745356043e4be75950b3ce39d012e4', 'loadClassLoader'));
|
||||
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInite64ea2605e4cf1002a60a3421b5e8329::getInitializer($loader));
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInit01745356043e4be75950b3ce39d012e4::getInitializer($loader));
|
||||
|
||||
$loader->setClassMapAuthoritative(true);
|
||||
$loader->register(true);
|
||||
|
||||
$filesToLoad = \Composer\Autoload\ComposerStaticInite64ea2605e4cf1002a60a3421b5e8329::$files;
|
||||
$filesToLoad = \Composer\Autoload\ComposerStaticInit01745356043e4be75950b3ce39d012e4::$files;
|
||||
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInite64ea2605e4cf1002a60a3421b5e8329
|
||||
class ComposerStaticInit01745356043e4be75950b3ce39d012e4
|
||||
{
|
||||
public static $files = array (
|
||||
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
|
||||
|
@ -272,6 +272,11 @@ class ComposerStaticInite64ea2605e4cf1002a60a3421b5e8329
|
|||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagPropertyValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagPropertyValueNode.php',
|
||||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagValueNode.php',
|
||||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\DeprecatedTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php',
|
||||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineAnnotation' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php',
|
||||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArgument' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php',
|
||||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArray' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php',
|
||||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineArrayItem' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php',
|
||||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\Doctrine\\DoctrineTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php',
|
||||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ExtendsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.php',
|
||||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\GenericTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php',
|
||||
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ImplementsTagValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.php',
|
||||
|
@ -3061,9 +3066,9 @@ class ComposerStaticInite64ea2605e4cf1002a60a3421b5e8329
|
|||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInite64ea2605e4cf1002a60a3421b5e8329::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInite64ea2605e4cf1002a60a3421b5e8329::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInite64ea2605e4cf1002a60a3421b5e8329::$classMap;
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInit01745356043e4be75950b3ce39d012e4::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInit01745356043e4be75950b3ce39d012e4::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInit01745356043e4be75950b3ce39d012e4::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
|
|
|
@ -821,23 +821,24 @@
|
|||
},
|
||||
{
|
||||
"name": "phpstan\/phpdoc-parser",
|
||||
"version": "1.21.3",
|
||||
"version_normalized": "1.21.3.0",
|
||||
"version": "1.22.0",
|
||||
"version_normalized": "1.22.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https:\/\/github.com\/phpstan\/phpdoc-parser.git",
|
||||
"reference": "b0c366dd2cea79407d635839d25423ba07c55dd6"
|
||||
"reference": "ec58baf7b3c7f1c81b3b00617c953249fb8cf30c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https:\/\/api.github.com\/repos\/phpstan\/phpdoc-parser\/zipball\/b0c366dd2cea79407d635839d25423ba07c55dd6",
|
||||
"reference": "b0c366dd2cea79407d635839d25423ba07c55dd6",
|
||||
"url": "https:\/\/api.github.com\/repos\/phpstan\/phpdoc-parser\/zipball\/ec58baf7b3c7f1c81b3b00617c953249fb8cf30c",
|
||||
"reference": "ec58baf7b3c7f1c81b3b00617c953249fb8cf30c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine\/annotations": "^2.0",
|
||||
"nikic\/php-parser": "^4.15",
|
||||
"php-parallel-lint\/php-parallel-lint": "^1.2",
|
||||
"phpstan\/extension-installer": "^1.0",
|
||||
|
@ -847,7 +848,7 @@
|
|||
"phpunit\/phpunit": "^9.5",
|
||||
"symfony\/process": "^5.2"
|
||||
},
|
||||
"time": "2023-05-29T19:31:28+00:00",
|
||||
"time": "2023-06-01T12:35:21+00:00",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
|
@ -864,7 +865,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.21.3"
|
||||
"source": "https:\/\/github.com\/phpstan\/phpdoc-parser\/tree\/1.22.0"
|
||||
},
|
||||
"install-path": "..\/phpstan\/phpdoc-parser"
|
||||
},
|
||||
|
@ -2059,12 +2060,12 @@
|
|||
"source": {
|
||||
"type": "git",
|
||||
"url": "https:\/\/github.com\/rectorphp\/rector-symfony.git",
|
||||
"reference": "fbd87013a48448fbc21df3c5f7fca49b2046ba40"
|
||||
"reference": "13f7cc4888f1e318766ceb2212a1dc0a31012b41"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-symfony\/zipball\/fbd87013a48448fbc21df3c5f7fca49b2046ba40",
|
||||
"reference": "fbd87013a48448fbc21df3c5f7fca49b2046ba40",
|
||||
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-symfony\/zipball\/13f7cc4888f1e318766ceb2212a1dc0a31012b41",
|
||||
"reference": "13f7cc4888f1e318766ceb2212a1dc0a31012b41",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2094,7 +2095,7 @@
|
|||
"tomasvotruba\/type-coverage": "^0.0.9",
|
||||
"tomasvotruba\/unused-public": "^0.0.34"
|
||||
},
|
||||
"time": "2023-06-01T16:00:18+00:00",
|
||||
"time": "2023-06-01T16:05:52+00:00",
|
||||
"default-branch": true,
|
||||
"type": "rector-extension",
|
||||
"extra": {
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -15,6 +15,8 @@ For the complete list of supported PHPDoc features check out PHPStan documentati
|
|||
* [PHPDoc Types](https://phpstan.org/writing-php-code/phpdoc-types) (list of PHPDoc types)
|
||||
* [phpdoc-parser API Reference](https://phpstan.github.io/phpdoc-parser/namespace-PHPStan.PhpDocParser.html) with all the AST node types etc.
|
||||
|
||||
This parser also supports parsing [Doctrine Annotations](https://github.com/doctrine/annotations). The AST nodes live in the [PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine namespace](https://phpstan.github.io/phpdoc-parser/namespace-PHPStan.PhpDocParser.Ast.PhpDoc.Doctrine.html). The support needs to be turned on by setting `bool $parseDoctrineAnnotations` to `true` in `Lexer` and `PhpDocParser` class constructors.
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
"php": "^7.2 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine\/annotations": "^2.0",
|
||||
"nikic\/php-parser": "^4.15",
|
||||
"php-parallel-lint\/php-parallel-lint": "^1.2",
|
||||
"phpstan\/extension-installer": "^1.0",
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
use PHPStan\PhpDocParser\Ast\NodeAttributes;
|
||||
use function implode;
|
||||
class DoctrineAnnotation implements Node
|
||||
{
|
||||
use NodeAttributes;
|
||||
/** @var string */
|
||||
public $name;
|
||||
/** @var list<DoctrineArgument> */
|
||||
public $arguments;
|
||||
/**
|
||||
* @param list<DoctrineArgument> $arguments
|
||||
*/
|
||||
public function __construct(string $name, array $arguments)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->arguments = $arguments;
|
||||
}
|
||||
public function __toString() : string
|
||||
{
|
||||
$arguments = implode(', ', $this->arguments);
|
||||
return $this->name . '(' . $arguments . ')';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprNode;
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
use PHPStan\PhpDocParser\Ast\NodeAttributes;
|
||||
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
|
||||
/**
|
||||
* @phpstan-type ValueType = DoctrineAnnotation|IdentifierTypeNode|DoctrineArray|ConstExprNode
|
||||
*/
|
||||
class DoctrineArgument implements Node
|
||||
{
|
||||
use NodeAttributes;
|
||||
/** @var IdentifierTypeNode|null */
|
||||
public $key;
|
||||
/** @var ValueType */
|
||||
public $value;
|
||||
/**
|
||||
* @param ValueType $value
|
||||
*/
|
||||
public function __construct(?IdentifierTypeNode $key, $value)
|
||||
{
|
||||
$this->key = $key;
|
||||
$this->value = $value;
|
||||
}
|
||||
public function __toString() : string
|
||||
{
|
||||
if ($this->key === null) {
|
||||
return (string) $this->value;
|
||||
}
|
||||
return $this->key . '=' . $this->value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
use PHPStan\PhpDocParser\Ast\NodeAttributes;
|
||||
use function implode;
|
||||
class DoctrineArray implements Node
|
||||
{
|
||||
use NodeAttributes;
|
||||
/** @var list<DoctrineArrayItem> */
|
||||
public $items;
|
||||
/**
|
||||
* @param list<DoctrineArrayItem> $items
|
||||
*/
|
||||
public function __construct(array $items)
|
||||
{
|
||||
$this->items = $items;
|
||||
}
|
||||
public function __toString() : string
|
||||
{
|
||||
$items = implode(', ', $this->items);
|
||||
return '{' . $items . '}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprIntegerNode;
|
||||
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprStringNode;
|
||||
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstFetchNode;
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
use PHPStan\PhpDocParser\Ast\NodeAttributes;
|
||||
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
|
||||
/**
|
||||
* @phpstan-import-type ValueType from DoctrineArgument
|
||||
* @phpstan-type KeyType = ConstExprIntegerNode|ConstExprStringNode|IdentifierTypeNode|ConstFetchNode|null
|
||||
*/
|
||||
class DoctrineArrayItem implements Node
|
||||
{
|
||||
use NodeAttributes;
|
||||
/** @var KeyType */
|
||||
public $key;
|
||||
/** @var ValueType */
|
||||
public $value;
|
||||
/**
|
||||
* @param KeyType $key
|
||||
* @param ValueType $value
|
||||
*/
|
||||
public function __construct($key, $value)
|
||||
{
|
||||
$this->key = $key;
|
||||
$this->value = $value;
|
||||
}
|
||||
public function __toString() : string
|
||||
{
|
||||
if ($this->key === null) {
|
||||
return (string) $this->value;
|
||||
}
|
||||
return $this->key . '=' . $this->value;
|
||||
}
|
||||
}
|
25
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php
vendored
Normal file
25
vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\NodeAttributes;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use function trim;
|
||||
class DoctrineTagValueNode implements PhpDocTagValueNode
|
||||
{
|
||||
use NodeAttributes;
|
||||
/** @var DoctrineAnnotation */
|
||||
public $annotation;
|
||||
/** @var string (may be empty) */
|
||||
public $description;
|
||||
public function __construct(\PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineAnnotation $annotation, string $description)
|
||||
{
|
||||
$this->annotation = $annotation;
|
||||
$this->description = $description;
|
||||
}
|
||||
public function __toString() : string
|
||||
{
|
||||
return trim("{$this->annotation} {$this->description}");
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ declare (strict_types=1);
|
|||
namespace PHPStan\PhpDocParser\Ast\PhpDoc;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\NodeAttributes;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineTagValueNode;
|
||||
use function trim;
|
||||
class PhpDocTagNode implements \PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocChildNode
|
||||
{
|
||||
|
@ -19,6 +20,9 @@ class PhpDocTagNode implements \PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocChildNode
|
|||
}
|
||||
public function __toString() : string
|
||||
{
|
||||
if ($this->value instanceof DoctrineTagValueNode) {
|
||||
return (string) $this->value;
|
||||
}
|
||||
return trim("{$this->name} {$this->value}");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,29 +29,36 @@ class Lexer
|
|||
public const TOKEN_OPEN_PHPDOC = 15;
|
||||
public const TOKEN_CLOSE_PHPDOC = 16;
|
||||
public const TOKEN_PHPDOC_TAG = 17;
|
||||
public const TOKEN_FLOAT = 18;
|
||||
public const TOKEN_INTEGER = 19;
|
||||
public const TOKEN_SINGLE_QUOTED_STRING = 20;
|
||||
public const TOKEN_DOUBLE_QUOTED_STRING = 21;
|
||||
public const TOKEN_IDENTIFIER = 22;
|
||||
public const TOKEN_THIS_VARIABLE = 23;
|
||||
public const TOKEN_VARIABLE = 24;
|
||||
public const TOKEN_HORIZONTAL_WS = 25;
|
||||
public const TOKEN_PHPDOC_EOL = 26;
|
||||
public const TOKEN_OTHER = 27;
|
||||
public const TOKEN_END = 28;
|
||||
public const TOKEN_COLON = 29;
|
||||
public const TOKEN_WILDCARD = 30;
|
||||
public const TOKEN_OPEN_CURLY_BRACKET = 31;
|
||||
public const TOKEN_CLOSE_CURLY_BRACKET = 32;
|
||||
public const TOKEN_NEGATED = 33;
|
||||
public const TOKEN_ARROW = 34;
|
||||
public const TOKEN_LABELS = [self::TOKEN_REFERENCE => '\'&\'', self::TOKEN_UNION => '\'|\'', self::TOKEN_INTERSECTION => '\'&\'', self::TOKEN_NULLABLE => '\'?\'', self::TOKEN_NEGATED => '\'!\'', self::TOKEN_OPEN_PARENTHESES => '\'(\'', self::TOKEN_CLOSE_PARENTHESES => '\')\'', self::TOKEN_OPEN_ANGLE_BRACKET => '\'<\'', self::TOKEN_CLOSE_ANGLE_BRACKET => '\'>\'', self::TOKEN_OPEN_SQUARE_BRACKET => '\'[\'', self::TOKEN_CLOSE_SQUARE_BRACKET => '\']\'', self::TOKEN_OPEN_CURLY_BRACKET => '\'{\'', self::TOKEN_CLOSE_CURLY_BRACKET => '\'}\'', self::TOKEN_COMMA => '\',\'', self::TOKEN_COLON => '\':\'', self::TOKEN_VARIADIC => '\'...\'', self::TOKEN_DOUBLE_COLON => '\'::\'', self::TOKEN_DOUBLE_ARROW => '\'=>\'', self::TOKEN_ARROW => '\'->\'', self::TOKEN_EQUAL => '\'=\'', self::TOKEN_OPEN_PHPDOC => '\'/**\'', self::TOKEN_CLOSE_PHPDOC => '\'*/\'', self::TOKEN_PHPDOC_TAG => 'TOKEN_PHPDOC_TAG', self::TOKEN_PHPDOC_EOL => 'TOKEN_PHPDOC_EOL', self::TOKEN_FLOAT => 'TOKEN_FLOAT', self::TOKEN_INTEGER => 'TOKEN_INTEGER', self::TOKEN_SINGLE_QUOTED_STRING => 'TOKEN_SINGLE_QUOTED_STRING', self::TOKEN_DOUBLE_QUOTED_STRING => 'TOKEN_DOUBLE_QUOTED_STRING', self::TOKEN_IDENTIFIER => 'type', self::TOKEN_THIS_VARIABLE => '\'$this\'', self::TOKEN_VARIABLE => 'variable', self::TOKEN_HORIZONTAL_WS => 'TOKEN_HORIZONTAL_WS', self::TOKEN_OTHER => 'TOKEN_OTHER', self::TOKEN_END => 'TOKEN_END', self::TOKEN_WILDCARD => '*'];
|
||||
public const TOKEN_DOCTRINE_TAG = 18;
|
||||
public const TOKEN_FLOAT = 19;
|
||||
public const TOKEN_INTEGER = 20;
|
||||
public const TOKEN_SINGLE_QUOTED_STRING = 21;
|
||||
public const TOKEN_DOUBLE_QUOTED_STRING = 22;
|
||||
public const TOKEN_IDENTIFIER = 23;
|
||||
public const TOKEN_THIS_VARIABLE = 24;
|
||||
public const TOKEN_VARIABLE = 25;
|
||||
public const TOKEN_HORIZONTAL_WS = 26;
|
||||
public const TOKEN_PHPDOC_EOL = 27;
|
||||
public const TOKEN_OTHER = 28;
|
||||
public const TOKEN_END = 29;
|
||||
public const TOKEN_COLON = 30;
|
||||
public const TOKEN_WILDCARD = 31;
|
||||
public const TOKEN_OPEN_CURLY_BRACKET = 32;
|
||||
public const TOKEN_CLOSE_CURLY_BRACKET = 33;
|
||||
public const TOKEN_NEGATED = 34;
|
||||
public const TOKEN_ARROW = 35;
|
||||
public const TOKEN_LABELS = [self::TOKEN_REFERENCE => '\'&\'', self::TOKEN_UNION => '\'|\'', self::TOKEN_INTERSECTION => '\'&\'', self::TOKEN_NULLABLE => '\'?\'', self::TOKEN_NEGATED => '\'!\'', self::TOKEN_OPEN_PARENTHESES => '\'(\'', self::TOKEN_CLOSE_PARENTHESES => '\')\'', self::TOKEN_OPEN_ANGLE_BRACKET => '\'<\'', self::TOKEN_CLOSE_ANGLE_BRACKET => '\'>\'', self::TOKEN_OPEN_SQUARE_BRACKET => '\'[\'', self::TOKEN_CLOSE_SQUARE_BRACKET => '\']\'', self::TOKEN_OPEN_CURLY_BRACKET => '\'{\'', self::TOKEN_CLOSE_CURLY_BRACKET => '\'}\'', self::TOKEN_COMMA => '\',\'', self::TOKEN_COLON => '\':\'', self::TOKEN_VARIADIC => '\'...\'', self::TOKEN_DOUBLE_COLON => '\'::\'', self::TOKEN_DOUBLE_ARROW => '\'=>\'', self::TOKEN_ARROW => '\'->\'', self::TOKEN_EQUAL => '\'=\'', self::TOKEN_OPEN_PHPDOC => '\'/**\'', self::TOKEN_CLOSE_PHPDOC => '\'*/\'', self::TOKEN_PHPDOC_TAG => 'TOKEN_PHPDOC_TAG', self::TOKEN_DOCTRINE_TAG => 'TOKEN_DOCTRINE_TAG', self::TOKEN_PHPDOC_EOL => 'TOKEN_PHPDOC_EOL', self::TOKEN_FLOAT => 'TOKEN_FLOAT', self::TOKEN_INTEGER => 'TOKEN_INTEGER', self::TOKEN_SINGLE_QUOTED_STRING => 'TOKEN_SINGLE_QUOTED_STRING', self::TOKEN_DOUBLE_QUOTED_STRING => 'TOKEN_DOUBLE_QUOTED_STRING', self::TOKEN_IDENTIFIER => 'type', self::TOKEN_THIS_VARIABLE => '\'$this\'', self::TOKEN_VARIABLE => 'variable', self::TOKEN_HORIZONTAL_WS => 'TOKEN_HORIZONTAL_WS', self::TOKEN_OTHER => 'TOKEN_OTHER', self::TOKEN_END => 'TOKEN_END', self::TOKEN_WILDCARD => '*'];
|
||||
public const VALUE_OFFSET = 0;
|
||||
public const TYPE_OFFSET = 1;
|
||||
public const LINE_OFFSET = 2;
|
||||
/** @var bool */
|
||||
private $parseDoctrineAnnotations;
|
||||
/** @var string|null */
|
||||
private $regexp;
|
||||
public function __construct(bool $parseDoctrineAnnotations = \false)
|
||||
{
|
||||
$this->parseDoctrineAnnotations = $parseDoctrineAnnotations;
|
||||
}
|
||||
/**
|
||||
* @return list<array{string, int, int}>
|
||||
*/
|
||||
|
@ -106,14 +113,17 @@ class Lexer
|
|||
self::TOKEN_CLOSE_PHPDOC => '\\*/',
|
||||
self::TOKEN_PHPDOC_TAG => '@(?:[a-z][a-z0-9-\\\\]+:)?[a-z][a-z0-9-\\\\]*+',
|
||||
self::TOKEN_PHPDOC_EOL => '\\r?+\\n[\\x09\\x20]*+(?:\\*(?!/)\\x20?+)?',
|
||||
self::TOKEN_FLOAT => '(?:-?[0-9]++(_[0-9]++)*\\.[0-9]*(_[0-9]++)*+(?:e-?[0-9]++(_[0-9]++)*)?)|(?:-?[0-9]*+(_[0-9]++)*\\.[0-9]++(_[0-9]++)*(?:e-?[0-9]++(_[0-9]++)*)?)|(?:-?[0-9]++(_[0-9]++)*e-?[0-9]++(_[0-9]++)*)',
|
||||
self::TOKEN_INTEGER => '-?(?:(?:0b[0-1]++(_[0-1]++)*)|(?:0o[0-7]++(_[0-7]++)*)|(?:0x[0-9a-f]++(_[0-9a-f]++)*)|(?:[0-9]++(_[0-9]++)*))',
|
||||
self::TOKEN_FLOAT => '[+\\-]?(?:(?:[0-9]++(_[0-9]++)*\\.[0-9]*+(_[0-9]++)*(?:e[+\\-]?[0-9]++(_[0-9]++)*)?)|(?:[0-9]*+(_[0-9]++)*\\.[0-9]++(_[0-9]++)*(?:e[+\\-]?[0-9]++(_[0-9]++)*)?)|(?:[0-9]++(_[0-9]++)*e[+\\-]?[0-9]++(_[0-9]++)*))',
|
||||
self::TOKEN_INTEGER => '[+\\-]?(?:(?:0b[0-1]++(_[0-1]++)*)|(?:0o[0-7]++(_[0-7]++)*)|(?:0x[0-9a-f]++(_[0-9a-f]++)*)|(?:[0-9]++(_[0-9]++)*))',
|
||||
self::TOKEN_SINGLE_QUOTED_STRING => '\'(?:\\\\[^\\r\\n]|[^\'\\r\\n\\\\])*+\'',
|
||||
self::TOKEN_DOUBLE_QUOTED_STRING => '"(?:\\\\[^\\r\\n]|[^"\\r\\n\\\\])*+"',
|
||||
self::TOKEN_WILDCARD => '\\*',
|
||||
// anything but TOKEN_CLOSE_PHPDOC or TOKEN_HORIZONTAL_WS or TOKEN_EOL
|
||||
self::TOKEN_OTHER => '(?:(?!\\*/)[^\\s])++',
|
||||
];
|
||||
if ($this->parseDoctrineAnnotations) {
|
||||
$patterns[self::TOKEN_DOCTRINE_TAG] = '@[a-z_\\\\][a-z0-9_\\:\\\\]*[a-z_][a-z0-9_]*';
|
||||
}
|
||||
// anything but TOKEN_CLOSE_PHPDOC or TOKEN_HORIZONTAL_WS or TOKEN_EOL
|
||||
$patterns[self::TOKEN_OTHER] = '(?:(?!\\*/)[^\\s])++';
|
||||
foreach ($patterns as $type => &$pattern) {
|
||||
$pattern = '(?:' . $pattern . ')(*MARK:' . $type . ')';
|
||||
}
|
||||
|
|
|
@ -136,20 +136,13 @@ class ConstExprParser
|
|||
*/
|
||||
private function enrichWithAttributes(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens, Ast\ConstExpr\ConstExprNode $node, int $startLine, int $startIndex) : Ast\ConstExpr\ConstExprNode
|
||||
{
|
||||
$endLine = $tokens->currentTokenLine();
|
||||
$endIndex = $tokens->currentTokenIndex();
|
||||
if ($this->useLinesAttributes) {
|
||||
$node->setAttribute(Ast\Attribute::START_LINE, $startLine);
|
||||
$node->setAttribute(Ast\Attribute::END_LINE, $endLine);
|
||||
$node->setAttribute(Ast\Attribute::END_LINE, $tokens->currentTokenLine());
|
||||
}
|
||||
if ($this->useIndexAttributes) {
|
||||
$tokensArray = $tokens->getTokens();
|
||||
$endIndex--;
|
||||
if ($tokensArray[$endIndex][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
|
||||
$endIndex--;
|
||||
}
|
||||
$node->setAttribute(Ast\Attribute::START_INDEX, $startIndex);
|
||||
$node->setAttribute(Ast\Attribute::END_INDEX, $endIndex);
|
||||
$node->setAttribute(Ast\Attribute::END_INDEX, $tokens->endIndexOfLastRelevantToken());
|
||||
}
|
||||
return $node;
|
||||
}
|
||||
|
|
|
@ -3,14 +3,23 @@
|
|||
declare (strict_types=1);
|
||||
namespace PHPStan\PhpDocParser\Parser;
|
||||
|
||||
use LogicException;
|
||||
use PHPStan\PhpDocParser\Ast;
|
||||
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprIntegerNode;
|
||||
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprStringNode;
|
||||
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstFetchNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine;
|
||||
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
|
||||
use PHPStan\PhpDocParser\Lexer\Lexer;
|
||||
use PHPStan\ShouldNotHappenException;
|
||||
use function array_key_exists;
|
||||
use function array_values;
|
||||
use function count;
|
||||
use function str_replace;
|
||||
use function trim;
|
||||
/**
|
||||
* @phpstan-import-type ValueType from Doctrine\DoctrineArgument as DoctrineValueType
|
||||
*/
|
||||
class PhpDocParser
|
||||
{
|
||||
private const DISALLOWED_DESCRIPTION_START_TOKENS = [Lexer::TOKEN_UNION, Lexer::TOKEN_INTERSECTION];
|
||||
|
@ -23,18 +32,21 @@ class PhpDocParser
|
|||
/** @var bool */
|
||||
private $preserveTypeAliasesWithInvalidTypes;
|
||||
/** @var bool */
|
||||
private $parseDoctrineAnnotations;
|
||||
/** @var bool */
|
||||
private $useLinesAttributes;
|
||||
/** @var bool */
|
||||
private $useIndexAttributes;
|
||||
/**
|
||||
* @param array{lines?: bool, indexes?: bool} $usedAttributes
|
||||
*/
|
||||
public function __construct(\PHPStan\PhpDocParser\Parser\TypeParser $typeParser, \PHPStan\PhpDocParser\Parser\ConstExprParser $constantExprParser, bool $requireWhitespaceBeforeDescription = \false, bool $preserveTypeAliasesWithInvalidTypes = \false, array $usedAttributes = [])
|
||||
public function __construct(\PHPStan\PhpDocParser\Parser\TypeParser $typeParser, \PHPStan\PhpDocParser\Parser\ConstExprParser $constantExprParser, bool $requireWhitespaceBeforeDescription = \false, bool $preserveTypeAliasesWithInvalidTypes = \false, array $usedAttributes = [], bool $parseDoctrineAnnotations = \false)
|
||||
{
|
||||
$this->typeParser = $typeParser;
|
||||
$this->constantExprParser = $constantExprParser;
|
||||
$this->requireWhitespaceBeforeDescription = $requireWhitespaceBeforeDescription;
|
||||
$this->preserveTypeAliasesWithInvalidTypes = $preserveTypeAliasesWithInvalidTypes;
|
||||
$this->parseDoctrineAnnotations = $parseDoctrineAnnotations;
|
||||
$this->useLinesAttributes = $usedAttributes['lines'] ?? \false;
|
||||
$this->useIndexAttributes = $usedAttributes['indexes'] ?? \false;
|
||||
}
|
||||
|
@ -43,10 +55,36 @@ class PhpDocParser
|
|||
$tokens->consumeTokenType(Lexer::TOKEN_OPEN_PHPDOC);
|
||||
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
|
||||
$children = [];
|
||||
if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
|
||||
$children[] = $this->parseChild($tokens);
|
||||
while ($tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL) && !$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
|
||||
if ($this->parseDoctrineAnnotations) {
|
||||
if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
|
||||
$lastChild = $this->parseChild($tokens);
|
||||
$children[] = $lastChild;
|
||||
while (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
|
||||
if ($lastChild instanceof Ast\PhpDoc\PhpDocTagNode && ($lastChild->value instanceof Doctrine\DoctrineTagValueNode || $lastChild->value instanceof Ast\PhpDoc\GenericTagValueNode)) {
|
||||
$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
|
||||
break;
|
||||
}
|
||||
$lastChild = $this->parseChild($tokens);
|
||||
$children[] = $lastChild;
|
||||
continue;
|
||||
}
|
||||
if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL)) {
|
||||
break;
|
||||
}
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
|
||||
break;
|
||||
}
|
||||
$lastChild = $this->parseChild($tokens);
|
||||
$children[] = $lastChild;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
|
||||
$children[] = $this->parseChild($tokens);
|
||||
while ($tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL) && !$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
|
||||
$children[] = $this->parseChild($tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
|
@ -69,6 +107,7 @@ class PhpDocParser
|
|||
}
|
||||
return $this->enrichWithAttributes($tokens, new Ast\PhpDoc\PhpDocNode(array_values($children)), 1, 0);
|
||||
}
|
||||
/** @phpstan-impure */
|
||||
private function parseChild(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens) : Ast\PhpDoc\PhpDocChildNode
|
||||
{
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG)) {
|
||||
|
@ -76,6 +115,15 @@ class PhpDocParser
|
|||
$startIndex = $tokens->currentTokenIndex();
|
||||
return $this->enrichWithAttributes($tokens, $this->parseTag($tokens), $startLine, $startIndex);
|
||||
}
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_DOCTRINE_TAG)) {
|
||||
$startLine = $tokens->currentTokenLine();
|
||||
$startIndex = $tokens->currentTokenIndex();
|
||||
$tag = $tokens->currentTokenValue();
|
||||
$tokens->next();
|
||||
$tagStartLine = $tokens->currentTokenLine();
|
||||
$tagStartIndex = $tokens->currentTokenIndex();
|
||||
return $this->enrichWithAttributes($tokens, new Ast\PhpDoc\PhpDocTagNode($tag, $this->enrichWithAttributes($tokens, $this->parseDoctrineTagValue($tokens, $tag), $tagStartLine, $tagStartIndex)), $startLine, $startIndex);
|
||||
}
|
||||
$startLine = $tokens->currentTokenLine();
|
||||
$startIndex = $tokens->currentTokenIndex();
|
||||
$text = $this->parseText($tokens);
|
||||
|
@ -88,20 +136,13 @@ class PhpDocParser
|
|||
*/
|
||||
private function enrichWithAttributes(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens, Ast\Node $tag, int $startLine, int $startIndex) : Ast\Node
|
||||
{
|
||||
$endLine = $tokens->currentTokenLine();
|
||||
$endIndex = $tokens->currentTokenIndex();
|
||||
if ($this->useLinesAttributes) {
|
||||
$tag->setAttribute(Ast\Attribute::START_LINE, $startLine);
|
||||
$tag->setAttribute(Ast\Attribute::END_LINE, $endLine);
|
||||
$tag->setAttribute(Ast\Attribute::END_LINE, $tokens->currentTokenLine());
|
||||
}
|
||||
if ($this->useIndexAttributes) {
|
||||
$tokensArray = $tokens->getTokens();
|
||||
$endIndex--;
|
||||
if ($tokensArray[$endIndex][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
|
||||
$endIndex--;
|
||||
}
|
||||
$tag->setAttribute(Ast\Attribute::START_INDEX, $startIndex);
|
||||
$tag->setAttribute(Ast\Attribute::END_INDEX, $endIndex);
|
||||
$tag->setAttribute(Ast\Attribute::END_INDEX, $tokens->endIndexOfLastRelevantToken());
|
||||
}
|
||||
return $tag;
|
||||
}
|
||||
|
@ -115,7 +156,7 @@ class PhpDocParser
|
|||
}
|
||||
$tokens->pushSavePoint();
|
||||
$tokens->next();
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END)) {
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_DOCTRINE_TAG, Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END)) {
|
||||
$tokens->rollback();
|
||||
break;
|
||||
}
|
||||
|
@ -124,6 +165,51 @@ class PhpDocParser
|
|||
}
|
||||
return new Ast\PhpDoc\PhpDocTextNode(trim($text, " \t"));
|
||||
}
|
||||
private function parseOptionalDescriptionAfterDoctrineTag(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens) : string
|
||||
{
|
||||
$text = '';
|
||||
while (!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL)) {
|
||||
$text .= $tokens->getSkippedHorizontalWhiteSpaceIfAny() . $tokens->joinUntil(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_DOCTRINE_TAG, Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END);
|
||||
if (!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL)) {
|
||||
if (!$tokens->isPrecededByHorizontalWhitespace()) {
|
||||
return trim($text . $this->parseText($tokens)->text, " \t");
|
||||
}
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG)) {
|
||||
$tokens->pushSavePoint();
|
||||
$child = $this->parseChild($tokens);
|
||||
if ($child instanceof Ast\PhpDoc\PhpDocTagNode) {
|
||||
if ($child->value instanceof Ast\PhpDoc\GenericTagValueNode || $child->value instanceof Doctrine\DoctrineTagValueNode) {
|
||||
$tokens->rollback();
|
||||
break;
|
||||
}
|
||||
if ($child->value instanceof Ast\PhpDoc\InvalidTagValueNode) {
|
||||
$tokens->rollback();
|
||||
$tokens->pushSavePoint();
|
||||
$tokens->next();
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
|
||||
$tokens->rollback();
|
||||
break;
|
||||
}
|
||||
$tokens->rollback();
|
||||
return trim($text . $this->parseText($tokens)->text, " \t");
|
||||
}
|
||||
}
|
||||
$tokens->rollback();
|
||||
return trim($text . $this->parseText($tokens)->text, " \t");
|
||||
}
|
||||
break;
|
||||
}
|
||||
$tokens->pushSavePoint();
|
||||
$tokens->next();
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_DOCTRINE_TAG, Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END)) {
|
||||
$tokens->rollback();
|
||||
break;
|
||||
}
|
||||
$tokens->dropSavePoint();
|
||||
$text .= "\n";
|
||||
}
|
||||
return trim($text, " \t");
|
||||
}
|
||||
public function parseTag(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens) : Ast\PhpDoc\PhpDocTagNode
|
||||
{
|
||||
$tag = $tokens->currentTokenValue();
|
||||
|
@ -233,6 +319,14 @@ class PhpDocParser
|
|||
$tagValue = $this->parseParamOutTagValue($tokens);
|
||||
break;
|
||||
default:
|
||||
if ($this->parseDoctrineAnnotations) {
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
|
||||
$tagValue = $this->parseDoctrineTagValue($tokens, $tag);
|
||||
} else {
|
||||
$tagValue = new Ast\PhpDoc\GenericTagValueNode($this->parseOptionalDescriptionAfterDoctrineTag($tokens));
|
||||
}
|
||||
break;
|
||||
}
|
||||
$tagValue = new Ast\PhpDoc\GenericTagValueNode($this->parseOptionalDescription($tokens));
|
||||
break;
|
||||
}
|
||||
|
@ -243,6 +337,170 @@ class PhpDocParser
|
|||
}
|
||||
return $this->enrichWithAttributes($tokens, $tagValue, $startLine, $startIndex);
|
||||
}
|
||||
private function parseDoctrineTagValue(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens, string $tag) : Ast\PhpDoc\PhpDocTagValueNode
|
||||
{
|
||||
$startLine = $tokens->currentTokenLine();
|
||||
$startIndex = $tokens->currentTokenIndex();
|
||||
return new Doctrine\DoctrineTagValueNode($this->enrichWithAttributes($tokens, new Doctrine\DoctrineAnnotation($tag, $this->parseDoctrineArguments($tokens, \false)), $startLine, $startIndex), $this->parseOptionalDescriptionAfterDoctrineTag($tokens));
|
||||
}
|
||||
/**
|
||||
* @return list<Doctrine\DoctrineArgument>
|
||||
*/
|
||||
private function parseDoctrineArguments(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens, bool $deep) : array
|
||||
{
|
||||
if (!$tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
|
||||
return [];
|
||||
}
|
||||
if (!$deep) {
|
||||
$tokens->addEndOfLineToSkippedTokens();
|
||||
}
|
||||
$arguments = [];
|
||||
try {
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES);
|
||||
do {
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) {
|
||||
break;
|
||||
}
|
||||
$arguments[] = $this->parseDoctrineArgument($tokens);
|
||||
} while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA));
|
||||
} finally {
|
||||
if (!$deep) {
|
||||
$tokens->removeEndOfLineFromSkippedTokens();
|
||||
}
|
||||
}
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);
|
||||
return $arguments;
|
||||
}
|
||||
private function parseDoctrineArgument(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens) : Doctrine\DoctrineArgument
|
||||
{
|
||||
if (!$tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) {
|
||||
$startLine = $tokens->currentTokenLine();
|
||||
$startIndex = $tokens->currentTokenIndex();
|
||||
return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineArgument(null, $this->parseDoctrineArgumentValue($tokens)), $startLine, $startIndex);
|
||||
}
|
||||
$startLine = $tokens->currentTokenLine();
|
||||
$startIndex = $tokens->currentTokenIndex();
|
||||
try {
|
||||
$tokens->pushSavePoint();
|
||||
$currentValue = $tokens->currentTokenValue();
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
|
||||
$key = $this->enrichWithAttributes($tokens, new IdentifierTypeNode($currentValue), $startLine, $startIndex);
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_EQUAL);
|
||||
$value = $this->parseDoctrineArgumentValue($tokens);
|
||||
$tokens->dropSavePoint();
|
||||
return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineArgument($key, $value), $startLine, $startIndex);
|
||||
} catch (\PHPStan\PhpDocParser\Parser\ParserException $e) {
|
||||
$tokens->rollback();
|
||||
return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineArgument(null, $this->parseDoctrineArgumentValue($tokens)), $startLine, $startIndex);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return DoctrineValueType
|
||||
*/
|
||||
private function parseDoctrineArgumentValue(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens)
|
||||
{
|
||||
$startLine = $tokens->currentTokenLine();
|
||||
$startIndex = $tokens->currentTokenIndex();
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG, Lexer::TOKEN_DOCTRINE_TAG)) {
|
||||
$name = $tokens->currentTokenValue();
|
||||
$tokens->next();
|
||||
return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineAnnotation($name, $this->parseDoctrineArguments($tokens, \true)), $startLine, $startIndex);
|
||||
}
|
||||
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET)) {
|
||||
$items = [];
|
||||
do {
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET)) {
|
||||
break;
|
||||
}
|
||||
$items[] = $this->parseDoctrineArrayItem($tokens);
|
||||
} while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA));
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET);
|
||||
return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineArray($items), $startLine, $startIndex);
|
||||
}
|
||||
$currentTokenValue = $tokens->currentTokenValue();
|
||||
$tokens->pushSavePoint();
|
||||
// because of ConstFetchNode
|
||||
if ($tokens->tryConsumeTokenType(Lexer::TOKEN_IDENTIFIER)) {
|
||||
$identifier = $this->enrichWithAttributes($tokens, new Ast\Type\IdentifierTypeNode($currentTokenValue), $startLine, $startIndex);
|
||||
if (!$tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_COLON)) {
|
||||
$tokens->dropSavePoint();
|
||||
return $identifier;
|
||||
}
|
||||
$tokens->rollback();
|
||||
// because of ConstFetchNode
|
||||
} else {
|
||||
$tokens->dropSavePoint();
|
||||
// because of ConstFetchNode
|
||||
}
|
||||
$exception = new \PHPStan\PhpDocParser\Parser\ParserException($tokens->currentTokenValue(), $tokens->currentTokenType(), $tokens->currentTokenOffset(), Lexer::TOKEN_IDENTIFIER, null, $tokens->currentTokenLine());
|
||||
try {
|
||||
$constExpr = $this->constantExprParser->parse($tokens, \true);
|
||||
if ($constExpr instanceof Ast\ConstExpr\ConstExprArrayNode) {
|
||||
throw $exception;
|
||||
}
|
||||
return $constExpr;
|
||||
} catch (LogicException $e) {
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
private function parseDoctrineArrayItem(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens) : Doctrine\DoctrineArrayItem
|
||||
{
|
||||
$startLine = $tokens->currentTokenLine();
|
||||
$startIndex = $tokens->currentTokenIndex();
|
||||
try {
|
||||
$tokens->pushSavePoint();
|
||||
$key = $this->parseDoctrineArrayKey($tokens);
|
||||
if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL)) {
|
||||
if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_COLON)) {
|
||||
$tokens->consumeTokenType(Lexer::TOKEN_EQUAL);
|
||||
// will throw exception
|
||||
}
|
||||
}
|
||||
$value = $this->parseDoctrineArgumentValue($tokens);
|
||||
$tokens->dropSavePoint();
|
||||
return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineArrayItem($key, $value), $startLine, $startIndex);
|
||||
} catch (\PHPStan\PhpDocParser\Parser\ParserException $e) {
|
||||
$tokens->rollback();
|
||||
return $this->enrichWithAttributes($tokens, new Doctrine\DoctrineArrayItem(null, $this->parseDoctrineArgumentValue($tokens)), $startLine, $startIndex);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return ConstExprIntegerNode|ConstExprStringNode|IdentifierTypeNode|ConstFetchNode
|
||||
*/
|
||||
private function parseDoctrineArrayKey(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens)
|
||||
{
|
||||
$startLine = $tokens->currentTokenLine();
|
||||
$startIndex = $tokens->currentTokenIndex();
|
||||
if ($tokens->isCurrentTokenType(Lexer::TOKEN_INTEGER)) {
|
||||
$key = new Ast\ConstExpr\ConstExprIntegerNode(str_replace('_', '', $tokens->currentTokenValue()));
|
||||
$tokens->next();
|
||||
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) {
|
||||
$key = new Ast\ConstExpr\QuoteAwareConstExprStringNode(\PHPStan\PhpDocParser\Parser\StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\QuoteAwareConstExprStringNode::SINGLE_QUOTED);
|
||||
$tokens->next();
|
||||
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING)) {
|
||||
$key = new Ast\ConstExpr\QuoteAwareConstExprStringNode(\PHPStan\PhpDocParser\Parser\StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\QuoteAwareConstExprStringNode::DOUBLE_QUOTED);
|
||||
$tokens->next();
|
||||
} else {
|
||||
$currentTokenValue = $tokens->currentTokenValue();
|
||||
$tokens->pushSavePoint();
|
||||
// because of ConstFetchNode
|
||||
if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_IDENTIFIER)) {
|
||||
$tokens->dropSavePoint();
|
||||
throw new \PHPStan\PhpDocParser\Parser\ParserException($tokens->currentTokenValue(), $tokens->currentTokenType(), $tokens->currentTokenOffset(), Lexer::TOKEN_IDENTIFIER, null, $tokens->currentTokenLine());
|
||||
}
|
||||
if (!$tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_COLON)) {
|
||||
$tokens->dropSavePoint();
|
||||
return $this->enrichWithAttributes($tokens, new IdentifierTypeNode($currentTokenValue), $startLine, $startIndex);
|
||||
}
|
||||
$tokens->rollback();
|
||||
$constExpr = $this->constantExprParser->parse($tokens, \true);
|
||||
if (!$constExpr instanceof Ast\ConstExpr\ConstFetchNode) {
|
||||
throw new \PHPStan\PhpDocParser\Parser\ParserException($tokens->currentTokenValue(), $tokens->currentTokenType(), $tokens->currentTokenOffset(), Lexer::TOKEN_IDENTIFIER, null, $tokens->currentTokenLine());
|
||||
}
|
||||
return $constExpr;
|
||||
}
|
||||
return $this->enrichWithAttributes($tokens, $key, $startLine, $startIndex);
|
||||
}
|
||||
/**
|
||||
* @return Ast\PhpDoc\ParamTagValueNode|Ast\PhpDoc\TypelessParamTagValueNode
|
||||
*/
|
||||
|
|
|
@ -18,6 +18,8 @@ class TokenIterator
|
|||
private $index;
|
||||
/** @var int[] */
|
||||
private $savePoints = [];
|
||||
/** @var list<int> */
|
||||
private $skippedTokenTypes = [Lexer::TOKEN_HORIZONTAL_WS];
|
||||
/**
|
||||
* @param list<array{string, int, int}> $tokens
|
||||
*/
|
||||
|
@ -25,10 +27,7 @@ class TokenIterator
|
|||
{
|
||||
$this->tokens = $tokens;
|
||||
$this->index = $index;
|
||||
if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== Lexer::TOKEN_HORIZONTAL_WS) {
|
||||
return;
|
||||
}
|
||||
$this->index++;
|
||||
$this->skipIrrelevantTokens();
|
||||
}
|
||||
/**
|
||||
* @return list<array{string, int, int}>
|
||||
|
@ -76,6 +75,18 @@ class TokenIterator
|
|||
{
|
||||
return $this->index;
|
||||
}
|
||||
public function endIndexOfLastRelevantToken() : int
|
||||
{
|
||||
$endIndex = $this->currentTokenIndex();
|
||||
$endIndex--;
|
||||
while (in_array($this->tokens[$endIndex][Lexer::TYPE_OFFSET], $this->skippedTokenTypes, \true)) {
|
||||
if (!isset($this->tokens[$endIndex - 1])) {
|
||||
break;
|
||||
}
|
||||
$endIndex--;
|
||||
}
|
||||
return $endIndex;
|
||||
}
|
||||
public function isCurrentTokenValue(string $tokenValue) : bool
|
||||
{
|
||||
return $this->tokens[$this->index][Lexer::VALUE_OFFSET] === $tokenValue;
|
||||
|
@ -97,10 +108,7 @@ class TokenIterator
|
|||
$this->throwError($tokenType);
|
||||
}
|
||||
$this->index++;
|
||||
if (($this->tokens[$this->index][Lexer::TYPE_OFFSET] ?? -1) !== Lexer::TOKEN_HORIZONTAL_WS) {
|
||||
return;
|
||||
}
|
||||
$this->index++;
|
||||
$this->skipIrrelevantTokens();
|
||||
}
|
||||
/**
|
||||
* @throws ParserException
|
||||
|
@ -111,10 +119,7 @@ class TokenIterator
|
|||
$this->throwError($tokenType, $tokenValue);
|
||||
}
|
||||
$this->index++;
|
||||
if (($this->tokens[$this->index][Lexer::TYPE_OFFSET] ?? -1) !== Lexer::TOKEN_HORIZONTAL_WS) {
|
||||
return;
|
||||
}
|
||||
$this->index++;
|
||||
$this->skipIrrelevantTokens();
|
||||
}
|
||||
/** @phpstan-impure */
|
||||
public function tryConsumeTokenValue(string $tokenValue) : bool
|
||||
|
@ -123,9 +128,7 @@ class TokenIterator
|
|||
return \false;
|
||||
}
|
||||
$this->index++;
|
||||
if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
|
||||
$this->index++;
|
||||
}
|
||||
$this->skipIrrelevantTokens();
|
||||
return \true;
|
||||
}
|
||||
/** @phpstan-impure */
|
||||
|
@ -135,9 +138,7 @@ class TokenIterator
|
|||
return \false;
|
||||
}
|
||||
$this->index++;
|
||||
if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
|
||||
$this->index++;
|
||||
}
|
||||
$this->skipIrrelevantTokens();
|
||||
return \true;
|
||||
}
|
||||
public function getSkippedHorizontalWhiteSpaceIfAny() : string
|
||||
|
@ -159,10 +160,27 @@ class TokenIterator
|
|||
public function next() : void
|
||||
{
|
||||
$this->index++;
|
||||
if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== Lexer::TOKEN_HORIZONTAL_WS) {
|
||||
$this->skipIrrelevantTokens();
|
||||
}
|
||||
private function skipIrrelevantTokens() : void
|
||||
{
|
||||
if (!isset($this->tokens[$this->index])) {
|
||||
return;
|
||||
}
|
||||
$this->index++;
|
||||
while (in_array($this->tokens[$this->index][Lexer::TYPE_OFFSET], $this->skippedTokenTypes, \true)) {
|
||||
if (!isset($this->tokens[$this->index + 1])) {
|
||||
break;
|
||||
}
|
||||
$this->index++;
|
||||
}
|
||||
}
|
||||
public function addEndOfLineToSkippedTokens() : void
|
||||
{
|
||||
$this->skippedTokenTypes = [Lexer::TOKEN_HORIZONTAL_WS, Lexer::TOKEN_PHPDOC_EOL];
|
||||
}
|
||||
public function removeEndOfLineFromSkippedTokens() : void
|
||||
{
|
||||
$this->skippedTokenTypes = [Lexer::TOKEN_HORIZONTAL_WS];
|
||||
}
|
||||
/** @phpstan-impure */
|
||||
public function forwardToTheEnd() : void
|
||||
|
|
|
@ -55,20 +55,13 @@ class TypeParser
|
|||
*/
|
||||
public function enrichWithAttributes(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens, Ast\Node $type, int $startLine, int $startIndex) : Ast\Node
|
||||
{
|
||||
$endLine = $tokens->currentTokenLine();
|
||||
$endIndex = $tokens->currentTokenIndex();
|
||||
if ($this->useLinesAttributes) {
|
||||
$type->setAttribute(Ast\Attribute::START_LINE, $startLine);
|
||||
$type->setAttribute(Ast\Attribute::END_LINE, $endLine);
|
||||
$type->setAttribute(Ast\Attribute::END_LINE, $tokens->currentTokenLine());
|
||||
}
|
||||
if ($this->useIndexAttributes) {
|
||||
$tokensArray = $tokens->getTokens();
|
||||
$endIndex--;
|
||||
if ($tokensArray[$endIndex][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
|
||||
$endIndex--;
|
||||
}
|
||||
$type->setAttribute(Ast\Attribute::START_INDEX, $startIndex);
|
||||
$type->setAttribute(Ast\Attribute::END_INDEX, $endIndex);
|
||||
$type->setAttribute(Ast\Attribute::END_INDEX, $tokens->endIndexOfLastRelevantToken());
|
||||
}
|
||||
return $type;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,11 @@ use PHPStan\PhpDocParser\Ast\Node;
|
|||
use PHPStan\PhpDocParser\Ast\PhpDoc\AssertTagMethodValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\AssertTagPropertyValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\AssertTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineAnnotation;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineArgument;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineArray;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineArrayItem;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\Doctrine\DoctrineTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ExtendsTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ImplementsTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\MethodTagValueNode;
|
||||
|
@ -83,13 +88,13 @@ final class Printer
|
|||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private $listInsertionMap = [PhpDocNode::class . '->children' => "\n * ", UnionTypeNode::class . '->types' => '|', IntersectionTypeNode::class . '->types' => '&', ArrayShapeNode::class . '->items' => ', ', ObjectShapeNode::class . '->items' => ', ', CallableTypeNode::class . '->parameters' => ', ', GenericTypeNode::class . '->genericTypes' => ', ', ConstExprArrayNode::class . '->items' => ', ', MethodTagValueNode::class . '->parameters' => ', '];
|
||||
private $listInsertionMap = [PhpDocNode::class . '->children' => "\n * ", UnionTypeNode::class . '->types' => '|', IntersectionTypeNode::class . '->types' => '&', ArrayShapeNode::class . '->items' => ', ', ObjectShapeNode::class . '->items' => ', ', CallableTypeNode::class . '->parameters' => ', ', GenericTypeNode::class . '->genericTypes' => ', ', ConstExprArrayNode::class . '->items' => ', ', MethodTagValueNode::class . '->parameters' => ', ', DoctrineArray::class . '->items' => ', ', DoctrineAnnotation::class . '->arguments' => ', '];
|
||||
/**
|
||||
* [$find, $extraLeft, $extraRight]
|
||||
*
|
||||
* @var array<string, array{string|null, string, string}>
|
||||
*/
|
||||
private $emptyListInsertionMap = [CallableTypeNode::class . '->parameters' => ['(', '', ''], ArrayShapeNode::class . '->items' => ['{', '', ''], ObjectShapeNode::class . '->items' => ['{', '', '']];
|
||||
private $emptyListInsertionMap = [CallableTypeNode::class . '->parameters' => ['(', '', ''], ArrayShapeNode::class . '->items' => ['{', '', ''], ObjectShapeNode::class . '->items' => ['{', '', ''], DoctrineArray::class . '->items' => ['{', '', ''], DoctrineAnnotation::class . '->arguments' => ['(', '', '']];
|
||||
/** @var array<string, list<class-string<TypeNode>>> */
|
||||
private $parenthesesMap = [CallableTypeNode::class . '->returnType' => [CallableTypeNode::class, UnionTypeNode::class, IntersectionTypeNode::class], ArrayTypeNode::class . '->type' => [CallableTypeNode::class, UnionTypeNode::class, IntersectionTypeNode::class, ConstTypeNode::class, NullableTypeNode::class], OffsetAccessTypeNode::class . '->type' => [CallableTypeNode::class, UnionTypeNode::class, IntersectionTypeNode::class, ConstTypeNode::class, NullableTypeNode::class]];
|
||||
/** @var array<string, list<class-string<TypeNode>>> */
|
||||
|
@ -121,6 +126,9 @@ final class Printer
|
|||
return $node->text;
|
||||
}
|
||||
if ($node instanceof PhpDocTagNode) {
|
||||
if ($node->value instanceof DoctrineTagValueNode) {
|
||||
return $this->print($node->value);
|
||||
}
|
||||
return trim(sprintf('%s %s', $node->name, $this->print($node->value)));
|
||||
}
|
||||
if ($node instanceof PhpDocTagValueNode) {
|
||||
|
@ -146,6 +154,18 @@ final class Printer
|
|||
$isOptional = $node->isOptional ? '=' : '';
|
||||
return trim("{$type}{$isReference}{$isVariadic}{$node->parameterName}") . $isOptional;
|
||||
}
|
||||
if ($node instanceof DoctrineAnnotation) {
|
||||
return (string) $node;
|
||||
}
|
||||
if ($node instanceof DoctrineArgument) {
|
||||
return (string) $node;
|
||||
}
|
||||
if ($node instanceof DoctrineArray) {
|
||||
return (string) $node;
|
||||
}
|
||||
if ($node instanceof DoctrineArrayItem) {
|
||||
return (string) $node;
|
||||
}
|
||||
throw new LogicException(sprintf('Unknown node type %s', get_class($node)));
|
||||
}
|
||||
private function printTagValue(PhpDocTagValueNode $node) : string
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace Rector\RectorInstaller;
|
|||
*/
|
||||
final class GeneratedConfig
|
||||
{
|
||||
public const EXTENSIONS = array('rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 7f0656f'), 'rector/rector-downgrade-php' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-downgrade-php', 'relative_install_path' => '../../rector-downgrade-php', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 60db9b4'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main e276dee'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main fbd8701'));
|
||||
public const EXTENSIONS = array('rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 7f0656f'), 'rector/rector-downgrade-php' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-downgrade-php', 'relative_install_path' => '../../rector-downgrade-php', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 60db9b4'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main e276dee'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'dev-main 13f7cc4'));
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -9,10 +9,10 @@ use PhpParser\Node\Stmt\Class_;
|
|||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\Symfony\NodeAnalyzer\ClassAnalyzer;
|
||||
use Rector\Symfony\NodeFactory\GetSubscribedEventsClassMethodFactory;
|
||||
use Rector\Symfony\NodeFactory\OnLogoutClassMethodFactory;
|
||||
use Rector\Symfony\NodeManipulator\ClassManipulator;
|
||||
use Rector\Symfony\ValueObject\EventReferenceToMethodName;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
@ -43,17 +43,11 @@ final class LogoutHandlerToLogoutEventSubscriberRector extends AbstractRector
|
|||
* @var \Rector\Symfony\NodeAnalyzer\ClassAnalyzer
|
||||
*/
|
||||
private $classAnalyzer;
|
||||
/**
|
||||
* @readonly
|
||||
* @var \Rector\Symfony\NodeManipulator\ClassManipulator
|
||||
*/
|
||||
private $classManipulator;
|
||||
public function __construct(OnLogoutClassMethodFactory $onLogoutClassMethodFactory, GetSubscribedEventsClassMethodFactory $getSubscribedEventsClassMethodFactory, ClassAnalyzer $classAnalyzer, ClassManipulator $classManipulator)
|
||||
public function __construct(OnLogoutClassMethodFactory $onLogoutClassMethodFactory, GetSubscribedEventsClassMethodFactory $getSubscribedEventsClassMethodFactory, ClassAnalyzer $classAnalyzer)
|
||||
{
|
||||
$this->onLogoutClassMethodFactory = $onLogoutClassMethodFactory;
|
||||
$this->getSubscribedEventsClassMethodFactory = $getSubscribedEventsClassMethodFactory;
|
||||
$this->classAnalyzer = $classAnalyzer;
|
||||
$this->classManipulator = $classManipulator;
|
||||
$this->logoutHandlerObjectType = new ObjectType('Symfony\\Component\\Security\\Http\\Logout\\LogoutHandlerInterface');
|
||||
}
|
||||
public function getRuleDefinition() : RuleDefinition
|
||||
|
@ -115,7 +109,11 @@ CODE_SAMPLE
|
|||
if (!$this->classAnalyzer->hasImplements($node, 'Symfony\\Component\\Security\\Http\\Logout\\LogoutHandlerInterface')) {
|
||||
return null;
|
||||
}
|
||||
$this->classManipulator->removeImplements($node, [$this->logoutHandlerObjectType->getClassName()]);
|
||||
foreach ($node->implements as $key => $implement) {
|
||||
if ($this->isName($implement, $this->logoutHandlerObjectType->getClassName())) {
|
||||
unset($node->implements[$key]);
|
||||
}
|
||||
}
|
||||
$node->implements[] = new FullyQualified('Symfony\\Component\\EventDispatcher\\EventSubscriberInterface');
|
||||
// 2. refactor logout() class method to onLogout()
|
||||
$logoutClassMethod = $node->getMethod('logout');
|
||||
|
@ -123,7 +121,8 @@ CODE_SAMPLE
|
|||
return null;
|
||||
}
|
||||
$node->stmts[] = $this->onLogoutClassMethodFactory->createFromLogoutClassMethod($logoutClassMethod);
|
||||
$this->removeNode($logoutClassMethod);
|
||||
$classMethodStmtKey = $logoutClassMethod->getAttribute(AttributeKey::STMT_KEY);
|
||||
unset($node->stmts[$classMethodStmtKey]);
|
||||
// 3. add getSubscribedEvents() class method
|
||||
$classConstFetch = $this->nodeFactory->createClassConstReference('Symfony\\Component\\Security\\Http\\Event\\LogoutEvent');
|
||||
$eventReferencesToMethodNames = [new EventReferenceToMethodName($classConstFetch, 'onLogout')];
|
||||
|
|
Loading…
Reference in New Issue