1
0
mirror of https://github.com/rectorphp/rector.git synced 2025-04-24 17:36:02 +02:00

Updated Rector to commit 0dfc92f16f7d3d21a21ae5e6f6abb21467fb48da

0dfc92f16f Add declare strict_types rule, finally 🥳 (
This commit is contained in:
Tomas Votruba 2023-04-17 15:47:09 +00:00
parent 03e48b83b1
commit f924c3de30
20 changed files with 276 additions and 101 deletions

@ -68,6 +68,9 @@ CODE_SAMPLE
*/
public function refactor(Node $node) : ?Node
{
if ($node->stmts === null) {
return null;
}
$variableAndPropertyFetchAssign = $this->justPropertyFetchVariableAssignMatcher->match($node);
if (!$variableAndPropertyFetchAssign instanceof VariableAndPropertyFetchAssign) {
return null;

@ -0,0 +1,68 @@
<?php
declare (strict_types=1);
namespace Rector\TypeDeclaration\Rector\StmtsAwareInterface;
use PhpParser\Node;
use PhpParser\Node\Identifier;
use PhpParser\Node\Scalar\LNumber;
use PhpParser\Node\Stmt\Declare_;
use PhpParser\Node\Stmt\DeclareDeclare;
use PhpParser\Node\Stmt\Nop;
use Rector\Core\Contract\PhpParser\Node\StmtsAwareInterface;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\TypeDeclaration\Rector\StmtsAwareInterface\DeclareStrictTypesRector\DeclareStrictTypesRectorTest
*/
final class DeclareStrictTypesRector extends AbstractRector
{
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Add declare(strict_types=1) if missing', [new CodeSample(<<<'CODE_SAMPLE'
function someFunction()
{
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
declare(strict_types=1);
function someFunction()
{
}
CODE_SAMPLE
)]);
}
/**
* @param Node[] $nodes
* @return Node[]|null
*/
public function beforeTraverse(array $nodes) : ?array
{
parent::beforeTraverse($nodes);
// has declare already?
$declare = $this->betterNodeFinder->findFirstInstanceOf($nodes, Declare_::class);
if ($declare instanceof Declare_) {
return $nodes;
}
$declareDeclare = new DeclareDeclare(new Identifier('strict_types'), new LNumber(1));
$strictTypesDeclare = new Declare_([$declareDeclare]);
return \array_merge([$strictTypesDeclare, new Nop()], $nodes);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [StmtsAwareInterface::class];
}
/**
* @param StmtsAwareInterface $node
*/
public function refactor(Node $node) : ?Node
{
// workaroudn, as Rector now only hooks to specific nodes, not arrays
return null;
}
}

@ -19,12 +19,12 @@ final class VersionResolver
* @api
* @var string
*/
public const PACKAGE_VERSION = 'fbb472feb11f34bb94a1e6869e93b505103fa27f';
public const PACKAGE_VERSION = '0dfc92f16f7d3d21a21ae5e6f6abb21467fb48da';
/**
* @api
* @var string
*/
public const RELEASE_DATE = '2023-04-17 13:54:27';
public const RELEASE_DATE = '2023-04-17 16:41:14';
/**
* @var int
*/

2
vendor/autoload.php vendored

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

@ -18,6 +18,7 @@ return array(
'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprStringNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php',
'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprTrueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php',
'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstFetchNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.php',
'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\QuoteAwareConstExprStringNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/QuoteAwareConstExprStringNode.php',
'PHPStan\\PhpDocParser\\Ast\\Node' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/Node.php',
'PHPStan\\PhpDocParser\\Ast\\NodeAttributes' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/NodeAttributes.php',
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagMethodValueNode' => $vendorDir . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagMethodValueNode.php',
@ -71,6 +72,7 @@ return array(
'PHPStan\\PhpDocParser\\Parser\\ConstExprParser' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php',
'PHPStan\\PhpDocParser\\Parser\\ParserException' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/ParserException.php',
'PHPStan\\PhpDocParser\\Parser\\PhpDocParser' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php',
'PHPStan\\PhpDocParser\\Parser\\StringUnescaper' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php',
'PHPStan\\PhpDocParser\\Parser\\TokenIterator' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/TokenIterator.php',
'PHPStan\\PhpDocParser\\Parser\\TypeParser' => $vendorDir . '/phpstan/phpdoc-parser/src/Parser/TypeParser.php',
'PHPStan\\PhpDoc\\PHPUnit\\MockObjectTypeNodeResolverExtension' => $vendorDir . '/phpstan/phpstan-phpunit/src/PhpDoc/PHPUnit/MockObjectTypeNodeResolverExtension.php',
@ -2837,6 +2839,7 @@ return array(
'Rector\\TypeDeclaration\\Rector\\Property\\TypedPropertyFromStrictGetterMethodReturnTypeRector' => $baseDir . '/rules/TypeDeclaration/Rector/Property/TypedPropertyFromStrictGetterMethodReturnTypeRector.php',
'Rector\\TypeDeclaration\\Rector\\Property\\TypedPropertyFromStrictSetUpRector' => $baseDir . '/rules/TypeDeclaration/Rector/Property/TypedPropertyFromStrictSetUpRector.php',
'Rector\\TypeDeclaration\\Rector\\Property\\VarAnnotationIncorrectNullableRector' => $baseDir . '/rules/TypeDeclaration/Rector/Property/VarAnnotationIncorrectNullableRector.php',
'Rector\\TypeDeclaration\\Rector\\StmtsAwareInterface\\DeclareStrictTypesRector' => $baseDir . '/rules/TypeDeclaration/Rector/StmtsAwareInterface/DeclareStrictTypesRector.php',
'Rector\\TypeDeclaration\\Rector\\Ternary\\FlipNegatedTernaryInstanceofRector' => $baseDir . '/rules/TypeDeclaration/Rector/Ternary/FlipNegatedTernaryInstanceofRector.php',
'Rector\\TypeDeclaration\\TypeAnalyzer\\AlwaysStrictBoolExprAnalyzer' => $baseDir . '/rules/TypeDeclaration/TypeAnalyzer/AlwaysStrictBoolExprAnalyzer.php',
'Rector\\TypeDeclaration\\TypeAnalyzer\\AlwaysStrictScalarExprAnalyzer' => $baseDir . '/rules/TypeDeclaration/TypeAnalyzer/AlwaysStrictScalarExprAnalyzer.php',

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit2d4e91d23c53ce21a77e085e22a4a0ac
class ComposerAutoloaderInit67a0cab39c3e159fe58270f60be93d3e
{
private static $loader;
@ -22,17 +22,17 @@ class ComposerAutoloaderInit2d4e91d23c53ce21a77e085e22a4a0ac
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit2d4e91d23c53ce21a77e085e22a4a0ac', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit67a0cab39c3e159fe58270f60be93d3e', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInit2d4e91d23c53ce21a77e085e22a4a0ac', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit67a0cab39c3e159fe58270f60be93d3e', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit2d4e91d23c53ce21a77e085e22a4a0ac::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInit67a0cab39c3e159fe58270f60be93d3e::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
$filesToLoad = \Composer\Autoload\ComposerStaticInit2d4e91d23c53ce21a77e085e22a4a0ac::$files;
$filesToLoad = \Composer\Autoload\ComposerStaticInit67a0cab39c3e159fe58270f60be93d3e::$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 ComposerStaticInit2d4e91d23c53ce21a77e085e22a4a0ac
class ComposerStaticInit67a0cab39c3e159fe58270f60be93d3e
{
public static $files = array (
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
@ -265,6 +265,7 @@ class ComposerStaticInit2d4e91d23c53ce21a77e085e22a4a0ac
'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprStringNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php',
'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprTrueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php',
'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstFetchNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.php',
'PHPStan\\PhpDocParser\\Ast\\ConstExpr\\QuoteAwareConstExprStringNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/ConstExpr/QuoteAwareConstExprStringNode.php',
'PHPStan\\PhpDocParser\\Ast\\Node' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/Node.php',
'PHPStan\\PhpDocParser\\Ast\\NodeAttributes' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/NodeAttributes.php',
'PHPStan\\PhpDocParser\\Ast\\PhpDoc\\AssertTagMethodValueNode' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagMethodValueNode.php',
@ -318,6 +319,7 @@ class ComposerStaticInit2d4e91d23c53ce21a77e085e22a4a0ac
'PHPStan\\PhpDocParser\\Parser\\ConstExprParser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php',
'PHPStan\\PhpDocParser\\Parser\\ParserException' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/ParserException.php',
'PHPStan\\PhpDocParser\\Parser\\PhpDocParser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php',
'PHPStan\\PhpDocParser\\Parser\\StringUnescaper' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php',
'PHPStan\\PhpDocParser\\Parser\\TokenIterator' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/TokenIterator.php',
'PHPStan\\PhpDocParser\\Parser\\TypeParser' => __DIR__ . '/..' . '/phpstan/phpdoc-parser/src/Parser/TypeParser.php',
'PHPStan\\PhpDoc\\PHPUnit\\MockObjectTypeNodeResolverExtension' => __DIR__ . '/..' . '/phpstan/phpstan-phpunit/src/PhpDoc/PHPUnit/MockObjectTypeNodeResolverExtension.php',
@ -3084,6 +3086,7 @@ class ComposerStaticInit2d4e91d23c53ce21a77e085e22a4a0ac
'Rector\\TypeDeclaration\\Rector\\Property\\TypedPropertyFromStrictGetterMethodReturnTypeRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/Property/TypedPropertyFromStrictGetterMethodReturnTypeRector.php',
'Rector\\TypeDeclaration\\Rector\\Property\\TypedPropertyFromStrictSetUpRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/Property/TypedPropertyFromStrictSetUpRector.php',
'Rector\\TypeDeclaration\\Rector\\Property\\VarAnnotationIncorrectNullableRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/Property/VarAnnotationIncorrectNullableRector.php',
'Rector\\TypeDeclaration\\Rector\\StmtsAwareInterface\\DeclareStrictTypesRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/StmtsAwareInterface/DeclareStrictTypesRector.php',
'Rector\\TypeDeclaration\\Rector\\Ternary\\FlipNegatedTernaryInstanceofRector' => __DIR__ . '/../..' . '/rules/TypeDeclaration/Rector/Ternary/FlipNegatedTernaryInstanceofRector.php',
'Rector\\TypeDeclaration\\TypeAnalyzer\\AlwaysStrictBoolExprAnalyzer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/TypeAnalyzer/AlwaysStrictBoolExprAnalyzer.php',
'Rector\\TypeDeclaration\\TypeAnalyzer\\AlwaysStrictScalarExprAnalyzer' => __DIR__ . '/../..' . '/rules/TypeDeclaration/TypeAnalyzer/AlwaysStrictScalarExprAnalyzer.php',
@ -3139,9 +3142,9 @@ class ComposerStaticInit2d4e91d23c53ce21a77e085e22a4a0ac
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit2d4e91d23c53ce21a77e085e22a4a0ac::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit2d4e91d23c53ce21a77e085e22a4a0ac::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit2d4e91d23c53ce21a77e085e22a4a0ac::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInit67a0cab39c3e159fe58270f60be93d3e::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit67a0cab39c3e159fe58270f60be93d3e::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit67a0cab39c3e159fe58270f60be93d3e::$classMap;
}, null, ClassLoader::class);
}

@ -821,17 +821,17 @@
},
{
"name": "phpstan\/phpdoc-parser",
"version": "1.18.1",
"version_normalized": "1.18.1.0",
"version": "1.19.0",
"version_normalized": "1.19.0.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/phpstan\/phpdoc-parser.git",
"reference": "22dcdfd725ddf99583bfe398fc624ad6c5004a0f"
"reference": "178b33aa1c8b8d7725f0abee618ef47337e607ce"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/phpstan\/phpdoc-parser\/zipball\/22dcdfd725ddf99583bfe398fc624ad6c5004a0f",
"reference": "22dcdfd725ddf99583bfe398fc624ad6c5004a0f",
"url": "https:\/\/api.github.com\/repos\/phpstan\/phpdoc-parser\/zipball\/178b33aa1c8b8d7725f0abee618ef47337e607ce",
"reference": "178b33aa1c8b8d7725f0abee618ef47337e607ce",
"shasum": ""
},
"require": {
@ -846,7 +846,7 @@
"phpunit\/phpunit": "^9.5",
"symfony\/process": "^5.2"
},
"time": "2023-04-07T11:51:11+00:00",
"time": "2023-04-17T13:16:52+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -863,7 +863,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.18.1"
"source": "https:\/\/github.com\/phpstan\/phpdoc-parser\/tree\/1.19.0"
},
"install-path": "..\/phpstan\/phpdoc-parser"
},
@ -1919,12 +1919,12 @@
"source": {
"type": "git",
"url": "https:\/\/github.com\/rectorphp\/rector-doctrine.git",
"reference": "b88c766bfa958d04cf778203a41c3e8b469557be"
"reference": "040c091692d6a455363cbb2a61435d5dfd1477d0"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-doctrine\/zipball\/b88c766bfa958d04cf778203a41c3e8b469557be",
"reference": "b88c766bfa958d04cf778203a41c3e8b469557be",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-doctrine\/zipball\/040c091692d6a455363cbb2a61435d5dfd1477d0",
"reference": "040c091692d6a455363cbb2a61435d5dfd1477d0",
"shasum": ""
},
"require": {
@ -1936,7 +1936,7 @@
"require-dev": {
"doctrine\/orm": "^2.10",
"phpstan\/extension-installer": "^1.1",
"phpstan\/phpstan": "^1.8.2",
"phpstan\/phpstan": "^1.10",
"phpstan\/phpstan-strict-rules": "^1.1",
"phpstan\/phpstan-webmozart-assert": "^1.0",
"phpunit\/phpunit": "^10.0",
@ -1951,7 +1951,7 @@
"symplify\/rule-doc-generator": "^11.1",
"symplify\/vendor-patches": "^11.1"
},
"time": "2023-04-03T08:35:29+00:00",
"time": "2023-04-17T15:34:51+00:00",
"default-branch": true,
"type": "rector-extension",
"extra": {
@ -1978,7 +1978,7 @@
"description": "Rector upgrades rules for Doctrine",
"support": {
"issues": "https:\/\/github.com\/rectorphp\/rector-doctrine\/issues",
"source": "https:\/\/github.com\/rectorphp\/rector-doctrine\/tree\/main"
"source": "https:\/\/github.com\/rectorphp\/rector-doctrine\/tree\/0.14.2"
},
"install-path": "..\/rector\/rector-doctrine"
},

File diff suppressed because one or more lines are too long

@ -0,0 +1,67 @@
<?php
declare (strict_types=1);
namespace PHPStan\PhpDocParser\Ast\ConstExpr;
use PHPStan\PhpDocParser\Ast\NodeAttributes;
use function addcslashes;
use function assert;
use function dechex;
use function ord;
use function preg_replace_callback;
use function sprintf;
use function str_pad;
use function strlen;
use const STR_PAD_LEFT;
class QuoteAwareConstExprStringNode extends \PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprStringNode implements \PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprNode
{
public const SINGLE_QUOTED = 1;
public const DOUBLE_QUOTED = 2;
use NodeAttributes;
/** @var self::SINGLE_QUOTED|self::DOUBLE_QUOTED */
public $quoteType;
/**
* @param self::SINGLE_QUOTED|self::DOUBLE_QUOTED $quoteType
*/
public function __construct(string $value, int $quoteType)
{
parent::__construct($value);
$this->quoteType = $quoteType;
}
public function __toString() : string
{
if ($this->quoteType === self::SINGLE_QUOTED) {
// from https://github.com/nikic/PHP-Parser/blob/0ffddce52d816f72d0efc4d9b02e276d3309ef01/lib/PhpParser/PrettyPrinter/Standard.php#L1007
return sprintf("'%s'", addcslashes($this->value, '\'\\'));
}
// from https://github.com/nikic/PHP-Parser/blob/0ffddce52d816f72d0efc4d9b02e276d3309ef01/lib/PhpParser/PrettyPrinter/Standard.php#L1010-L1040
return sprintf('"%s"', $this->escapeDoubleQuotedString());
}
private function escapeDoubleQuotedString()
{
$quote = '"';
$escaped = addcslashes($this->value, "\n\r\t\f\v\$" . $quote . '\\');
// Escape control characters and non-UTF-8 characters.
// Regex based on https://stackoverflow.com/a/11709412/385378.
$regex = '/(
[\\x00-\\x08\\x0E-\\x1F] # Control characters
| [\\xC0-\\xC1] # Invalid UTF-8 Bytes
| [\\xF5-\\xFF] # Invalid UTF-8 Bytes
| \\xE0(?=[\\x80-\\x9F]) # Overlong encoding of prior code point
| \\xF0(?=[\\x80-\\x8F]) # Overlong encoding of prior code point
| [\\xC2-\\xDF](?![\\x80-\\xBF]) # Invalid UTF-8 Sequence Start
| [\\xE0-\\xEF](?![\\x80-\\xBF]{2}) # Invalid UTF-8 Sequence Start
| [\\xF0-\\xF4](?![\\x80-\\xBF]{3}) # Invalid UTF-8 Sequence Start
| (?<=[\\x00-\\x7F\\xF5-\\xFF])[\\x80-\\xBF] # Invalid UTF-8 Sequence Middle
| (?<![\\xC2-\\xDF]|[\\xE0-\\xEF]|[\\xE0-\\xEF][\\x80-\\xBF]|[\\xF0-\\xF4]|[\\xF0-\\xF4][\\x80-\\xBF]|[\\xF0-\\xF4][\\x80-\\xBF]{2})[\\x80-\\xBF] # Overlong Sequence
| (?<=[\\xE0-\\xEF])[\\x80-\\xBF](?![\\x80-\\xBF]) # Short 3 byte sequence
| (?<=[\\xF0-\\xF4])[\\x80-\\xBF](?![\\x80-\\xBF]{2}) # Short 4 byte sequence
| (?<=[\\xF0-\\xF4][\\x80-\\xBF])[\\x80-\\xBF](?![\\x80-\\xBF]) # Short 4 byte sequence (2)
)/x';
return preg_replace_callback($regex, static function ($matches) {
assert(strlen($matches[0]) === 1);
$hex = dechex(ord($matches[0]));
return '\\x' . str_pad($hex, 2, '0', STR_PAD_LEFT);
}, $escaped);
}
}

@ -32,7 +32,7 @@ class CallableTypeParameterNode implements Node
$type = "{$this->type} ";
$isReference = $this->isReference ? '&' : '';
$isVariadic = $this->isVariadic ? '...' : '';
$default = $this->isOptional ? ' = default' : '';
return trim("{$type}{$isReference}{$isVariadic}{$this->parameterName}") . $default;
$isOptional = $this->isOptional ? '=' : '';
return trim("{$type}{$isReference}{$isVariadic}{$this->parameterName}") . $isOptional;
}
}

@ -5,21 +5,18 @@ namespace PHPStan\PhpDocParser\Parser;
use PHPStan\PhpDocParser\Ast;
use PHPStan\PhpDocParser\Lexer\Lexer;
use function chr;
use function hexdec;
use function octdec;
use function preg_replace_callback;
use function str_replace;
use function strtolower;
use function substr;
class ConstExprParser
{
private const REPLACEMENTS = ['\\' => '\\', 'n' => "\n", 'r' => "\r", 't' => "\t", 'f' => "\f", 'v' => "\v", 'e' => "\x1b"];
/** @var bool */
private $unescapeStrings;
public function __construct(bool $unescapeStrings = \false)
/** @var bool */
private $quoteAwareConstExprString;
public function __construct(bool $unescapeStrings = \false, bool $quoteAwareConstExprString = \false)
{
$this->unescapeStrings = $unescapeStrings;
$this->quoteAwareConstExprString = $quoteAwareConstExprString;
}
public function parse(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens, bool $trimStrings = \false) : Ast\ConstExpr\ConstExprNode
{
@ -35,14 +32,18 @@ class ConstExprParser
}
if ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING, Lexer::TOKEN_DOUBLE_QUOTED_STRING)) {
$value = $tokens->currentTokenValue();
$type = $tokens->currentTokenType();
if ($trimStrings) {
if ($this->unescapeStrings) {
$value = self::unescapeString($value);
$value = \PHPStan\PhpDocParser\Parser\StringUnescaper::unescapeString($value);
} else {
$value = substr($value, 1, -1);
}
}
$tokens->next();
if ($this->quoteAwareConstExprString) {
return new Ast\ConstExpr\QuoteAwareConstExprStringNode($value, $type === Lexer::TOKEN_SINGLE_QUOTED_STRING ? Ast\ConstExpr\QuoteAwareConstExprStringNode::SINGLE_QUOTED : Ast\ConstExpr\QuoteAwareConstExprStringNode::DOUBLE_QUOTED);
}
return new Ast\ConstExpr\ConstExprStringNode($value);
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) {
$identifier = $tokens->currentTokenValue();
@ -113,52 +114,4 @@ class ConstExprParser
}
return new Ast\ConstExpr\ConstExprArrayItemNode($key, $value);
}
private static function unescapeString(string $string) : string
{
$quote = $string[0];
if ($quote === '\'') {
return str_replace(['\\\\', '\\\''], ['\\', '\''], substr($string, 1, -1));
}
return self::parseEscapeSequences(substr($string, 1, -1), '"');
}
/**
* Implementation based on https://github.com/nikic/PHP-Parser/blob/b0edd4c41111042d43bb45c6c657b2e0db367d9e/lib/PhpParser/Node/Scalar/String_.php#L90-L130
*/
private static function parseEscapeSequences(string $str, string $quote) : string
{
$str = str_replace('\\' . $quote, $quote, $str);
return preg_replace_callback('~\\\\([\\\\nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}|u\\{([0-9a-fA-F]+)\\})~', static function ($matches) {
$str = $matches[1];
if (isset(self::REPLACEMENTS[$str])) {
return self::REPLACEMENTS[$str];
}
if ($str[0] === 'x' || $str[0] === 'X') {
return chr(hexdec(substr($str, 1)));
}
if ($str[0] === 'u') {
return self::codePointToUtf8(hexdec($matches[2]));
}
return chr(octdec($str));
}, $str);
}
/**
* Implementation based on https://github.com/nikic/PHP-Parser/blob/b0edd4c41111042d43bb45c6c657b2e0db367d9e/lib/PhpParser/Node/Scalar/String_.php#L132-L154
*/
private static function codePointToUtf8(int $num) : string
{
if ($num <= 0x7f) {
return chr($num);
}
if ($num <= 0x7ff) {
return chr(($num >> 6) + 0xc0) . chr(($num & 0x3f) + 0x80);
}
if ($num <= 0xffff) {
return chr(($num >> 12) + 0xe0) . chr(($num >> 6 & 0x3f) + 0x80) . chr(($num & 0x3f) + 0x80);
}
if ($num <= 0x1fffff) {
return chr(($num >> 18) + 0xf0) . chr(($num >> 12 & 0x3f) + 0x80) . chr(($num >> 6 & 0x3f) + 0x80) . chr(($num & 0x3f) + 0x80);
}
// Invalid UTF-8 codepoint escape sequence: Codepoint too large
return "<EFBFBD>";
}
}

@ -0,0 +1,63 @@
<?php
declare (strict_types=1);
namespace PHPStan\PhpDocParser\Parser;
use function chr;
use function hexdec;
use function octdec;
use function preg_replace_callback;
use function str_replace;
use function substr;
class StringUnescaper
{
private const REPLACEMENTS = ['\\' => '\\', 'n' => "\n", 'r' => "\r", 't' => "\t", 'f' => "\f", 'v' => "\v", 'e' => "\x1b"];
public static function unescapeString(string $string) : string
{
$quote = $string[0];
if ($quote === '\'') {
return str_replace(['\\\\', '\\\''], ['\\', '\''], substr($string, 1, -1));
}
return self::parseEscapeSequences(substr($string, 1, -1), '"');
}
/**
* Implementation based on https://github.com/nikic/PHP-Parser/blob/b0edd4c41111042d43bb45c6c657b2e0db367d9e/lib/PhpParser/Node/Scalar/String_.php#L90-L130
*/
private static function parseEscapeSequences(string $str, string $quote) : string
{
$str = str_replace('\\' . $quote, $quote, $str);
return preg_replace_callback('~\\\\([\\\\nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}|u\\{([0-9a-fA-F]+)\\})~', static function ($matches) {
$str = $matches[1];
if (isset(self::REPLACEMENTS[$str])) {
return self::REPLACEMENTS[$str];
}
if ($str[0] === 'x' || $str[0] === 'X') {
return chr(hexdec(substr($str, 1)));
}
if ($str[0] === 'u') {
return self::codePointToUtf8(hexdec($matches[2]));
}
return chr(octdec($str));
}, $str);
}
/**
* Implementation based on https://github.com/nikic/PHP-Parser/blob/b0edd4c41111042d43bb45c6c657b2e0db367d9e/lib/PhpParser/Node/Scalar/String_.php#L132-L154
*/
private static function codePointToUtf8(int $num) : string
{
if ($num <= 0x7f) {
return chr($num);
}
if ($num <= 0x7ff) {
return chr(($num >> 6) + 0xc0) . chr(($num & 0x3f) + 0x80);
}
if ($num <= 0xffff) {
return chr(($num >> 12) + 0xe0) . chr(($num >> 6 & 0x3f) + 0x80) . chr(($num & 0x3f) + 0x80);
}
if ($num <= 0x1fffff) {
return chr(($num >> 18) + 0xf0) . chr(($num >> 12 & 0x3f) + 0x80) . chr(($num >> 6 & 0x3f) + 0x80) . chr(($num & 0x3f) + 0x80);
}
// Invalid UTF-8 codepoint escape sequence: Codepoint too large
return "<EFBFBD>";
}
}

@ -13,9 +13,12 @@ class TypeParser
{
/** @var ConstExprParser|null */
private $constExprParser;
public function __construct(?\PHPStan\PhpDocParser\Parser\ConstExprParser $constExprParser = null)
/** @var bool */
private $quoteAwareConstExprString;
public function __construct(?\PHPStan\PhpDocParser\Parser\ConstExprParser $constExprParser = null, bool $quoteAwareConstExprString = \false)
{
$this->constExprParser = $constExprParser;
$this->quoteAwareConstExprString = $quoteAwareConstExprString;
}
/** @phpstan-impure */
public function parse(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens) : Ast\Type\TypeNode
@ -429,10 +432,18 @@ class TypeParser
$key = new Ast\ConstExpr\ConstExprIntegerNode($tokens->currentTokenValue());
$tokens->next();
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) {
$key = new Ast\ConstExpr\ConstExprStringNode(trim($tokens->currentTokenValue(), "'"));
if ($this->quoteAwareConstExprString) {
$key = new Ast\ConstExpr\QuoteAwareConstExprStringNode(\PHPStan\PhpDocParser\Parser\StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\QuoteAwareConstExprStringNode::SINGLE_QUOTED);
} else {
$key = new Ast\ConstExpr\ConstExprStringNode(trim($tokens->currentTokenValue(), "'"));
}
$tokens->next();
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING)) {
$key = new Ast\ConstExpr\ConstExprStringNode(trim($tokens->currentTokenValue(), '"'));
if ($this->quoteAwareConstExprString) {
$key = new Ast\ConstExpr\QuoteAwareConstExprStringNode(\PHPStan\PhpDocParser\Parser\StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\QuoteAwareConstExprStringNode::DOUBLE_QUOTED);
} else {
$key = new Ast\ConstExpr\ConstExprStringNode(trim($tokens->currentTokenValue(), '"'));
}
$tokens->next();
} else {
$key = new Ast\Type\IdentifierTypeNode($tokens->currentTokenValue());
@ -475,10 +486,18 @@ class TypeParser
private function parseObjectShapeKey(\PHPStan\PhpDocParser\Parser\TokenIterator $tokens)
{
if ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) {
$key = new Ast\ConstExpr\ConstExprStringNode(trim($tokens->currentTokenValue(), "'"));
if ($this->quoteAwareConstExprString) {
$key = new Ast\ConstExpr\QuoteAwareConstExprStringNode(\PHPStan\PhpDocParser\Parser\StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\QuoteAwareConstExprStringNode::SINGLE_QUOTED);
} else {
$key = new Ast\ConstExpr\ConstExprStringNode(trim($tokens->currentTokenValue(), "'"));
}
$tokens->next();
} elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING)) {
$key = new Ast\ConstExpr\ConstExprStringNode(trim($tokens->currentTokenValue(), '"'));
if ($this->quoteAwareConstExprString) {
$key = new Ast\ConstExpr\QuoteAwareConstExprStringNode(\PHPStan\PhpDocParser\Parser\StringUnescaper::unescapeString($tokens->currentTokenValue()), Ast\ConstExpr\QuoteAwareConstExprStringNode::DOUBLE_QUOTED);
} else {
$key = new Ast\ConstExpr\ConstExprStringNode(trim($tokens->currentTokenValue(), '"'));
}
$tokens->next();
} else {
$key = new Ast\Type\IdentifierTypeNode($tokens->currentTokenValue());

@ -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 b88c766'), '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 23e55c6'), '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 cd55a1a'), '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 d1e6641'));
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 040c091'), '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 23e55c6'), '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 cd55a1a'), '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 d1e6641'));
private function __construct()
{
}

@ -9,7 +9,7 @@
"require-dev": {
"phpstan\/extension-installer": "^1.1",
"rector\/phpstan-rules": "^0.6",
"phpstan\/phpstan": "^1.8.2",
"phpstan\/phpstan": "^1.10",
"phpunit\/phpunit": "^10.0",
"symplify\/phpstan-rules": "^11.1",
"symplify\/phpstan-extensions": "^11.1",

@ -36,6 +36,10 @@ return static function (RectorConfig $rectorConfig) : void {
// @see https://github.com/doctrine/dbal/blob/4.0.x/UPGRADE.md#bc-break-removed-connectionparam__array-constants
new RenameClassAndConstFetch('Doctrine\\DBAL\\Connection', 'PARAM_STR_ARRAY', 'Doctrine\\DBAL\\ArrayParameterType', 'STRING'),
]);
$rectorConfig->ruleWithConfiguration(RenameClassConstFetchRector::class, [
// @see https://github.com/doctrine/dbal/blob/4.0.x/UPGRADE.md#bc-break-removed-connectionparam__array-constants
new RenameClassAndConstFetch('Doctrine\\DBAL\\Connection', 'PARAM_INT_ARRAY', 'Doctrine\\DBAL\\ArrayParameterType', 'INTEGER'),
]);
$rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [
// @see https://github.com/doctrine/dbal/blob/4.0.x/UPGRADE.md#bc-break-removed-connection_schemamanager-and-connectiongetschemamanager
new MethodCallRename('Doctrine\\DBAL\\Connection', 'getSchemaManager', 'createSchemaManager'),

@ -1,8 +0,0 @@
<?xml version="1.0"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="vendor/autoload.php" colors="true" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd" cacheDirectory=".phpunit.cache">
<testsuites>
<testsuite name="main">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>

@ -17,6 +17,6 @@ return static function (RectorConfig $rectorConfig) : void {
'*/Source/*',
'*/Fixture/*',
]);
$rectorConfig->sets([LevelSetList::UP_TO_PHP_81, PHPUnitSetList::PHPUNIT_100, SetList::DEAD_CODE, SetList::CODE_QUALITY, SetList::NAMING, SetList::TYPE_DECLARATION, SetList::PRIVATIZATION]);
$rectorConfig->sets([LevelSetList::UP_TO_PHP_81, PHPUnitSetList::PHPUNIT_100, SetList::DEAD_CODE, SetList::CODE_QUALITY, SetList::CODING_STYLE, SetList::NAMING, SetList::TYPE_DECLARATION, SetList::PRIVATIZATION]);
$rectorConfig->ruleWithConfiguration(StringClassNameToClassConstantRector::class, ['Doctrine\\*', 'Gedmo\\*', 'Knp\\*', 'DateTime', 'DateTimeInterface']);
};

@ -15,7 +15,7 @@ final class RemoveEmptyTableAttributeRector extends AbstractRector
{
public function getRuleDefinition() : RuleDefinition
{
return new RuleDefinition('Remove empty Table attribute on entities because it\'s useless', [new CodeSample(<<<'CODE_SAMPLE'
return new RuleDefinition("Remove empty Table attribute on entities because it's useless", [new CodeSample(<<<'CODE_SAMPLE'
use Doctrine\ORM\Mapping as ORM;
#[ORM\Table]