* [misc] Remove the rector library and phpstan library.

This commit is contained in:
liugang
2025-12-02 16:43:20 +08:00
committed by sunhao
parent 224d9160d5
commit 997815e803
3427 changed files with 2 additions and 310393 deletions
+1 -2
View File
@@ -34,8 +34,7 @@
}
},
"require-dev": {
"cweagans/composer-patches": "^1.7",
"rector/rector": "^2.2"
"cweagans/composer-patches": "^1.7"
},
"extra": {
"patches": {
-113
View File
@@ -1678,119 +1678,6 @@
"source": "https://github.com/cweagans/composer-patches/tree/1.7.3"
},
"time": "2022-12-20T22:53:13+00:00"
},
{
"name": "phpstan/phpstan",
"version": "2.1.31",
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/ead89849d879fe203ce9292c6ef5e7e76f867b96",
"reference": "ead89849d879fe203ce9292c6ef5e7e76f867b96",
"shasum": ""
},
"require": {
"php": "^7.4|^8.0"
},
"conflict": {
"phpstan/phpstan-shim": "*"
},
"bin": [
"phpstan",
"phpstan.phar"
],
"type": "library",
"autoload": {
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPStan - PHP Static Analysis Tool",
"keywords": [
"dev",
"static analysis"
],
"support": {
"docs": "https://phpstan.org/user-guide/getting-started",
"forum": "https://github.com/phpstan/phpstan/discussions",
"issues": "https://github.com/phpstan/phpstan/issues",
"security": "https://github.com/phpstan/phpstan/security/policy",
"source": "https://github.com/phpstan/phpstan-src"
},
"funding": [
{
"url": "https://github.com/ondrejmirtes",
"type": "github"
},
{
"url": "https://github.com/phpstan",
"type": "github"
}
],
"time": "2025-10-10T14:14:11+00:00"
},
{
"name": "rector/rector",
"version": "2.2.7",
"source": {
"type": "git",
"url": "https://github.com/rectorphp/rector.git",
"reference": "022038537838bc8a4e526af86c2d6e38eaeff7ef"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/rectorphp/rector/zipball/022038537838bc8a4e526af86c2d6e38eaeff7ef",
"reference": "022038537838bc8a4e526af86c2d6e38eaeff7ef",
"shasum": ""
},
"require": {
"php": "^7.4|^8.0",
"phpstan/phpstan": "^2.1.26"
},
"conflict": {
"rector/rector-doctrine": "*",
"rector/rector-downgrade-php": "*",
"rector/rector-phpunit": "*",
"rector/rector-symfony": "*"
},
"suggest": {
"ext-dom": "To manipulate phpunit.xml via the custom-rule command"
},
"bin": [
"bin/rector"
],
"type": "library",
"autoload": {
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Instant Upgrade and Automated Refactoring of any PHP code",
"homepage": "https://getrector.com/",
"keywords": [
"automation",
"dev",
"migration",
"refactoring"
],
"support": {
"issues": "https://github.com/rectorphp/rector/issues",
"source": "https://github.com/rectorphp/rector/tree/2.2.7"
},
"funding": [
{
"url": "https://github.com/tomasvotruba",
"type": "github"
}
],
"time": "2025-10-29T15:46:12+00:00"
}
],
"aliases": [],
-119
View File
@@ -1,119 +0,0 @@
#!/usr/bin/env php
<?php
/**
* Proxy PHP file generated by Composer
*
* This file includes the referenced bin path (../phpstan/phpstan/phpstan)
* using a stream wrapper to prevent the shebang from being output on PHP<8
*
* @generated
*/
namespace Composer;
$GLOBALS['_composer_bin_dir'] = __DIR__;
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
if (PHP_VERSION_ID < 80000) {
if (!class_exists('Composer\BinProxyWrapper')) {
/**
* @internal
*/
final class BinProxyWrapper
{
private $handle;
private $position;
private $realpath;
public function stream_open($path, $mode, $options, &$opened_path)
{
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
$opened_path = substr($path, 17);
$this->realpath = realpath($opened_path) ?: $opened_path;
$opened_path = $this->realpath;
$this->handle = fopen($this->realpath, $mode);
$this->position = 0;
return (bool) $this->handle;
}
public function stream_read($count)
{
$data = fread($this->handle, $count);
if ($this->position === 0) {
$data = preg_replace('{^#!.*\r?\n}', '', $data);
}
$this->position += strlen($data);
return $data;
}
public function stream_cast($castAs)
{
return $this->handle;
}
public function stream_close()
{
fclose($this->handle);
}
public function stream_lock($operation)
{
return $operation ? flock($this->handle, $operation) : true;
}
public function stream_seek($offset, $whence)
{
if (0 === fseek($this->handle, $offset, $whence)) {
$this->position = ftell($this->handle);
return true;
}
return false;
}
public function stream_tell()
{
return $this->position;
}
public function stream_eof()
{
return feof($this->handle);
}
public function stream_stat()
{
return array();
}
public function stream_set_option($option, $arg1, $arg2)
{
return true;
}
public function url_stat($path, $flags)
{
$path = substr($path, 17);
if (file_exists($path)) {
return stat($path);
}
return false;
}
}
}
if (
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
) {
return include("phpvfscomposer://" . __DIR__ . '/..'.'/phpstan/phpstan/phpstan');
}
}
return include __DIR__ . '/..'.'/phpstan/phpstan/phpstan';
-119
View File
@@ -1,119 +0,0 @@
#!/usr/bin/env php
<?php
/**
* Proxy PHP file generated by Composer
*
* This file includes the referenced bin path (../phpstan/phpstan/phpstan.phar)
* using a stream wrapper to prevent the shebang from being output on PHP<8
*
* @generated
*/
namespace Composer;
$GLOBALS['_composer_bin_dir'] = __DIR__;
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
if (PHP_VERSION_ID < 80000) {
if (!class_exists('Composer\BinProxyWrapper')) {
/**
* @internal
*/
final class BinProxyWrapper
{
private $handle;
private $position;
private $realpath;
public function stream_open($path, $mode, $options, &$opened_path)
{
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
$opened_path = substr($path, 17);
$this->realpath = realpath($opened_path) ?: $opened_path;
$opened_path = $this->realpath;
$this->handle = fopen($this->realpath, $mode);
$this->position = 0;
return (bool) $this->handle;
}
public function stream_read($count)
{
$data = fread($this->handle, $count);
if ($this->position === 0) {
$data = preg_replace('{^#!.*\r?\n}', '', $data);
}
$this->position += strlen($data);
return $data;
}
public function stream_cast($castAs)
{
return $this->handle;
}
public function stream_close()
{
fclose($this->handle);
}
public function stream_lock($operation)
{
return $operation ? flock($this->handle, $operation) : true;
}
public function stream_seek($offset, $whence)
{
if (0 === fseek($this->handle, $offset, $whence)) {
$this->position = ftell($this->handle);
return true;
}
return false;
}
public function stream_tell()
{
return $this->position;
}
public function stream_eof()
{
return feof($this->handle);
}
public function stream_stat()
{
return array();
}
public function stream_set_option($option, $arg1, $arg2)
{
return true;
}
public function url_stat($path, $flags)
{
$path = substr($path, 17);
if (file_exists($path)) {
return stat($path);
}
return false;
}
}
}
if (
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
) {
return include("phpvfscomposer://" . __DIR__ . '/..'.'/phpstan/phpstan/phpstan.phar');
}
}
return include __DIR__ . '/..'.'/phpstan/phpstan/phpstan.phar';
-119
View File
@@ -1,119 +0,0 @@
#!/usr/bin/env php
<?php
/**
* Proxy PHP file generated by Composer
*
* This file includes the referenced bin path (../rector/rector/bin/rector)
* using a stream wrapper to prevent the shebang from being output on PHP<8
*
* @generated
*/
namespace Composer;
$GLOBALS['_composer_bin_dir'] = __DIR__;
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
if (PHP_VERSION_ID < 80000) {
if (!class_exists('Composer\BinProxyWrapper')) {
/**
* @internal
*/
final class BinProxyWrapper
{
private $handle;
private $position;
private $realpath;
public function stream_open($path, $mode, $options, &$opened_path)
{
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
$opened_path = substr($path, 17);
$this->realpath = realpath($opened_path) ?: $opened_path;
$opened_path = $this->realpath;
$this->handle = fopen($this->realpath, $mode);
$this->position = 0;
return (bool) $this->handle;
}
public function stream_read($count)
{
$data = fread($this->handle, $count);
if ($this->position === 0) {
$data = preg_replace('{^#!.*\r?\n}', '', $data);
}
$this->position += strlen($data);
return $data;
}
public function stream_cast($castAs)
{
return $this->handle;
}
public function stream_close()
{
fclose($this->handle);
}
public function stream_lock($operation)
{
return $operation ? flock($this->handle, $operation) : true;
}
public function stream_seek($offset, $whence)
{
if (0 === fseek($this->handle, $offset, $whence)) {
$this->position = ftell($this->handle);
return true;
}
return false;
}
public function stream_tell()
{
return $this->position;
}
public function stream_eof()
{
return feof($this->handle);
}
public function stream_stat()
{
return array();
}
public function stream_set_option($option, $arg1, $arg2)
{
return true;
}
public function url_stat($path, $flags)
{
$path = substr($path, 17);
if (file_exists($path)) {
return stat($path);
}
return false;
}
}
}
if (
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
) {
return include("phpvfscomposer://" . __DIR__ . '/..'.'/rector/rector/bin/rector');
}
}
return include __DIR__ . '/..'.'/rector/rector/bin/rector';
-2
View File
@@ -65,11 +65,9 @@ return array(
'8d37dad4703fab45bfec9dd0bbf3278e' => $vendorDir . '/markbaker/matrix/classes/src/Operations/multiply.php',
'4888a6f58c08148ebe17682f9ce9b2a8' => $vendorDir . '/markbaker/matrix/classes/src/Operations/divideby.php',
'eef6fa3879d3efa347cd24d5eb348f85' => $vendorDir . '/markbaker/matrix/classes/src/Operations/divideinto.php',
'9b38cf48e83f5d8f60375221cd213eee' => $vendorDir . '/phpstan/phpstan/bootstrap.php',
'2cffec82183ee1cea088009cef9a6fc3' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
'04c6c5c2f7095ccf6c481d3e53e1776f' => $vendorDir . '/mustangostang/spyc/Spyc.php',
'dc1275c308c5b416beb314b6317daca2' => $vendorDir . '/overtrue/pinyin/src/const.php',
'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
'38143a9afc50997d55e4815db8489d1c' => $vendorDir . '/rector/rector/bootstrap.php',
'941748b3c8cae4466c827dfb5ca9602a' => $vendorDir . '/rmccue/requests/library/Deprecated.php',
);
-2
View File
@@ -66,12 +66,10 @@ class ComposerStaticInitd8f5ceb6dd2b1c87f9f3c117b97ef46e
'8d37dad4703fab45bfec9dd0bbf3278e' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/Operations/multiply.php',
'4888a6f58c08148ebe17682f9ce9b2a8' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/Operations/divideby.php',
'eef6fa3879d3efa347cd24d5eb348f85' => __DIR__ . '/..' . '/markbaker/matrix/classes/src/Operations/divideinto.php',
'9b38cf48e83f5d8f60375221cd213eee' => __DIR__ . '/..' . '/phpstan/phpstan/bootstrap.php',
'2cffec82183ee1cea088009cef9a6fc3' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
'04c6c5c2f7095ccf6c481d3e53e1776f' => __DIR__ . '/..' . '/mustangostang/spyc/Spyc.php',
'dc1275c308c5b416beb314b6317daca2' => __DIR__ . '/..' . '/overtrue/pinyin/src/const.php',
'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
'38143a9afc50997d55e4815db8489d1c' => __DIR__ . '/..' . '/rector/rector/bootstrap.php',
'941748b3c8cae4466c827dfb5ca9602a' => __DIR__ . '/..' . '/rmccue/requests/library/Deprecated.php',
);
+1 -122
View File
@@ -1576,62 +1576,6 @@
],
"install-path": "../phpseclib/phpseclib"
},
{
"name": "phpstan/phpstan",
"version": "2.1.31",
"version_normalized": "2.1.31.0",
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/ead89849d879fe203ce9292c6ef5e7e76f867b96",
"reference": "ead89849d879fe203ce9292c6ef5e7e76f867b96",
"shasum": ""
},
"require": {
"php": "^7.4|^8.0"
},
"conflict": {
"phpstan/phpstan-shim": "*"
},
"time": "2025-10-10T14:14:11+00:00",
"bin": [
"phpstan",
"phpstan.phar"
],
"type": "library",
"installation-source": "dist",
"autoload": {
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPStan - PHP Static Analysis Tool",
"keywords": [
"dev",
"static analysis"
],
"support": {
"docs": "https://phpstan.org/user-guide/getting-started",
"forum": "https://github.com/phpstan/phpstan/discussions",
"issues": "https://github.com/phpstan/phpstan/issues",
"security": "https://github.com/phpstan/phpstan/security/policy",
"source": "https://github.com/phpstan/phpstan-src"
},
"funding": [
{
"url": "https://github.com/ondrejmirtes",
"type": "github"
},
{
"url": "https://github.com/phpstan",
"type": "github"
}
],
"install-path": "../phpstan/phpstan"
},
{
"name": "psr/simple-cache",
"version": "1.0.1",
@@ -1686,69 +1630,6 @@
},
"install-path": "../psr/simple-cache"
},
{
"name": "rector/rector",
"version": "2.2.7",
"version_normalized": "2.2.7.0",
"source": {
"type": "git",
"url": "https://github.com/rectorphp/rector.git",
"reference": "022038537838bc8a4e526af86c2d6e38eaeff7ef"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/rectorphp/rector/zipball/022038537838bc8a4e526af86c2d6e38eaeff7ef",
"reference": "022038537838bc8a4e526af86c2d6e38eaeff7ef",
"shasum": ""
},
"require": {
"php": "^7.4|^8.0",
"phpstan/phpstan": "^2.1.26"
},
"conflict": {
"rector/rector-doctrine": "*",
"rector/rector-downgrade-php": "*",
"rector/rector-phpunit": "*",
"rector/rector-symfony": "*"
},
"suggest": {
"ext-dom": "To manipulate phpunit.xml via the custom-rule command"
},
"time": "2025-10-29T15:46:12+00:00",
"bin": [
"bin/rector"
],
"type": "library",
"installation-source": "dist",
"autoload": {
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "Instant Upgrade and Automated Refactoring of any PHP code",
"homepage": "https://getrector.com/",
"keywords": [
"automation",
"dev",
"migration",
"refactoring"
],
"support": {
"issues": "https://github.com/rectorphp/rector/issues",
"source": "https://github.com/rectorphp/rector/tree/2.2.7"
},
"funding": [
{
"url": "https://github.com/tomasvotruba",
"type": "github"
}
],
"install-path": "../rector/rector"
},
{
"name": "rmccue/requests",
"version": "v2.0.15",
@@ -1906,8 +1787,6 @@
],
"dev": true,
"dev-package-names": [
"cweagans/composer-patches",
"phpstan/phpstan",
"rector/rector"
"cweagans/composer-patches"
]
}
-18
View File
@@ -217,15 +217,6 @@
'reference' => '9d6ca36a6c2dd434765b1071b2644a1c683b385d',
'dev_requirement' => false,
),
'phpstan/phpstan' => array(
'pretty_version' => '2.1.31',
'version' => '2.1.31.0',
'type' => 'library',
'install_path' => __DIR__ . '/../phpstan/phpstan',
'aliases' => array(),
'reference' => 'ead89849d879fe203ce9292c6ef5e7e76f867b96',
'dev_requirement' => true,
),
'psr/simple-cache' => array(
'pretty_version' => '1.0.1',
'version' => '1.0.1.0',
@@ -235,15 +226,6 @@
'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
'dev_requirement' => false,
),
'rector/rector' => array(
'pretty_version' => '2.2.7',
'version' => '2.2.7.0',
'type' => 'library',
'install_path' => __DIR__ . '/../rector/rector',
'aliases' => array(),
'reference' => '022038537838bc8a4e526af86c2d6e38eaeff7ef',
'dev_requirement' => true,
),
'rmccue/requests' => array(
'pretty_version' => 'v2.0.15',
'version' => '2.0.15.0',
-22
View File
@@ -1,22 +0,0 @@
MIT License
Copyright (c) 2016 Ondřej Mirtes
Copyright (c) 2025 PHPStan s.r.o.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-118
View File
@@ -1,118 +0,0 @@
<h1 align="center">PHPStan - PHP Static Analysis Tool</h1>
<p align="center">
<img src="https://i.imgur.com/WaRKPlC.png" alt="PHPStan" width="300" height="300">
</p>
<p align="center">
<a href="https://github.com/phpstan/phpstan/actions"><img src="https://github.com/phpstan/phpstan/workflows/Tests/badge.svg" alt="Build Status"></a>
<a href="https://packagist.org/packages/phpstan/phpstan"><img src="https://poser.pugx.org/phpstan/phpstan/v/stable" alt="Latest Stable Version"></a>
<a href="https://packagist.org/packages/phpstan/phpstan/stats"><img src="https://poser.pugx.org/phpstan/phpstan/downloads" alt="Total Downloads"></a>
<a href="https://choosealicense.com/licenses/mit/"><img src="https://poser.pugx.org/phpstan/phpstan/license" alt="License"></a>
<a href="https://phpstan.org/"><img src="https://img.shields.io/badge/PHPStan-enabled-brightgreen.svg?style=flat" alt="PHPStan Enabled"></a>
</p>
------
PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs
even before you write tests for the code. It moves PHP closer to compiled languages in the sense that the correctness of each line of the code
can be checked before you run the actual line.
**[Read more about PHPStan »](https://phpstan.org/)**
**[Try out PHPStan on the on-line playground! »](https://phpstan.org/try)**
## Sponsors
Want your logo here? [Learn more »](https://phpstan.org/sponsor)
### Gold Sponsors
<a href="https://ma.tt/"><img src="website/src/images/sponsor/matt.png" alt="Matt Mullenweg" width="290" height="64"></a>
<a href="https://mojam.co/"><img src="website/src/images/sponsor/mojam.png" alt="Mojam" width="290" height="64"></a>
<br><br>
### Silver Sponsors
<a href="https://www.startupjobs.cz/startup/shipmonk"><img src="website/src/images/sponsor/shipmonk.jpg" alt="ShipMonk" width="290" height="64"></a>
<a href="https://www.shopware.com/en/"><img src="website/src/images/sponsor/shopware.png" alt="Shopware" width="284" height="64"></a>
<br><br>
### Bronze Sponsors
<a href="https://coders.thecodingmachine.com/phpstan"><img src="website/src/images/sponsor/tcm.png" alt="TheCodingMachine" width="247" height="64"></a>
&nbsp;&nbsp;&nbsp;
<a href="https://packagist.com/?utm_source=phpstan&utm_medium=readme&utm_campaign=sponsorlogo"><img src="website/src/images/sponsor/packagist.png" alt="Private Packagist" width="283" height="64"></a>
<br>
<a href="https://www.cdn77.com/"><img src="website/src/images/sponsor/cdn77.png" alt="CDN77" width="290" height="64"></a>
&nbsp;&nbsp;&nbsp;
<a href="https://blackfire.io/docs/introduction?utm_source=phpstan&utm_medium=github_readme&utm_campaign=logo"><img src="website/src/images/sponsor/blackfire.png" alt="Blackfire.io" width="254" height="64"></a>
<br>
<a href="https://www.iodigital.com/"><img src="website/src/images/sponsor/io.png" alt="iO" width="254" height="65"></a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.fame.fi/"><img src="website/src/images/sponsor/fame.png" alt="Fame Helsinki" width="283" height="64"></a>
<br>
<a href="https://werkenbijbelsimpel.nl/en/about-us/"><img src="website/src/images/sponsor/belsimpel.png" alt="Belsimpel" width="284" height="64"></a>
&nbsp;&nbsp;&nbsp;
<a href="https://togetter.com/"><img src="website/src/images/sponsor/togetter.png" alt="Togetter" width="283" height="64"></a>
<br>
<a href="https://join.rightcapital.com/?utm_source=phpstan&utm_medium=github&utm_campaign=sponsorship"><img src="website/src/images/sponsor/rightcapital.png" alt="RightCapital" width="283" height="64"></a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.shoptet.cz/"><img src="website/src/images/sponsor/shoptet.png" alt="Shoptet" width="283" height="64"></a>
<br>
<a href="https://zol.fr?utm_source=phpstan"><img src="website/src/images/sponsor/zol.png" alt="ZOL" width="283" height="64"></a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.edgenext.com/"><img src="website/src/images/sponsor/edgenext.png" alt="EdgeNext" width="283" height="64"></a>
<br>
<a href="https://route4me.com/"><img src="website/src/images/sponsor/route4me.png" alt="Route4Me: Route Optimizer and Route Planner Software" width="283" height="64"></a>
&nbsp;&nbsp;&nbsp;
<a href="https://craftcms.com/"><img src="website/src/images/sponsor/craftcms.png" alt="Craft CMS" width="283" height="64"></a>
<br>
<a href="https://jobs.ticketswap.com/"><img src="website/src/images/sponsor/ticketswap.png" alt="TicketSwap" width="269" height="64"></a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.campoint.net/"><img src="website/src/images/sponsor/campoint.png" alt="campoint AG" width="283" height="64"></a>
<br>
<a href="https://www.crisp.nl/"><img src="website/src/images/sponsor/crisp.png" alt="Crisp.nl" width="283" height="64"></a>
&nbsp;&nbsp;&nbsp;
<a href="https://inviqa.com/"><img src="website/src/images/sponsor/inviqa.png" alt="Inviqa" width="254" height="65"></a>
<br>
[**You can sponsor my open-source work on PHPStan through GitHub Sponsors and also directly.**](https://phpstan.org/sponsor)
One-time donations [through Revolut.me](https://revolut.me/ondrejmirtes) are also accepted. To request an invoice, [contact me](mailto:ondrej@mirtes.cz) through e-mail.
## Documentation
All the documentation lives on the [phpstan.org website](https://phpstan.org/):
* [Getting Started & User Guide](https://phpstan.org/user-guide/getting-started)
* [Config Reference](https://phpstan.org/config-reference)
* [PHPDocs Basics](https://phpstan.org/writing-php-code/phpdocs-basics) & [PHPDoc Types](https://phpstan.org/writing-php-code/phpdoc-types)
* [Extension Library](https://phpstan.org/user-guide/extension-library)
* [Developing Extensions](https://phpstan.org/developing-extensions/extension-types)
* [API Reference](https://apiref.phpstan.org/)
## PHPStan Pro
PHPStan Pro is a paid add-on on top of open-source PHPStan Static Analysis Tool with these premium features:
* Web UI for browsing found errors, you can click and open your editor of choice on the offending line.
* Continuous analysis (watch mode): scans changed files in the background, refreshes the UI automatically.
Try it on PHPStan 0.12.45 or later by running it with the `--pro` option. You can create an account either by following the on-screen instructions, or by visiting [account.phpstan.com](https://account.phpstan.com/).
After 30-day free trial period it costs 7 EUR for individuals monthly, 70 EUR for teams (up to 25 members). By paying for PHPStan Pro, you're supporting the development of open-source PHPStan.
You can read more about it on [PHPStan's website](https://phpstan.org/blog/introducing-phpstan-pro).
## Code of Conduct
This project adheres to a [Contributor Code of Conduct](https://github.com/phpstan/phpstan/blob/master/CODE_OF_CONDUCT.md). By participating in this project and its community, you are expected to uphold this code.
## Contributing
Any contributions are welcome. PHPStan's source code open to pull requests lives at [`phpstan/phpstan-src`](https://github.com/phpstan/phpstan-src).
-338
View File
@@ -1,338 +0,0 @@
Upgrading from PHPStan 1.x to 2.0
=================================
## PHP version requirements
PHPStan now requires PHP 7.4 or newer to run.
## Upgrading guide for end users
The best way to get ready for upgrade to PHPStan 2.0 is to update to the **latest PHPStan 1.12 release**
and enable [**Bleeding Edge**](https://phpstan.org/blog/what-is-bleeding-edge). This will enable the new rules and behaviours that 2.0 turns on for all users.
Also make sure to install and enable [`phpstan/phpstan-deprecation-rules`](https://github.com/phpstan/phpstan-deprecation-rules).
Once you get to a green build with no deprecations showed on latest PHPStan 1.12.x with Bleeding Edge enabled, you can update all your related PHPStan dependencies to 2.0 in `composer.json`:
```json
"require-dev": {
"phpstan/phpstan": "^2.0",
"phpstan/phpstan-deprecation-rules": "^2.0",
"phpstan/phpstan-doctrine": "^2.0",
"phpstan/phpstan-nette": "^2.0",
"phpstan/phpstan-phpunit": "^2.0",
"phpstan/phpstan-strict-rules": "^2.0",
"phpstan/phpstan-symfony": "^2.0",
"phpstan/phpstan-webmozart-assert": "^2.0",
...
}
```
Don't forget to update [3rd party PHPStan extensions](https://phpstan.org/user-guide/extension-library) as well.
After changing your `composer.json`, run `composer update 'phpstan/*' -W`.
It's up to you whether you go through the new reported errors or if you just put them all to the [baseline](https://phpstan.org/user-guide/baseline) ;) Everyone who's on PHPStan 1.12 should be able to upgrade to PHPStan 2.0.
### Noteworthy changes to code analysis
* [**Enhancements in handling parameters passed by reference**](https://phpstan.org/blog/enhancements-in-handling-parameters-passed-by-reference)
* [**Validate inline PHPDoc `@var` tag type**](https://phpstan.org/blog/phpstan-1-10-comes-with-lie-detector#validate-inline-phpdoc-%40var-tag-type)
* [**List type enforced**](https://phpstan.org/blog/phpstan-1-9-0-with-phpdoc-asserts-list-type#list-type)
* **Always `true` conditions always reported**: previously reported only with phpstan-strict-rules, this is now always reported.
### Removed option `checkMissingIterableValueType`
It's strongly recommended to add the missing array typehints.
If you want to continue ignoring missing typehints from arrays, add `missingType.iterableValue` error identifier to your `ignoreErrors`:
```neon
parameters:
ignoreErrors:
-
identifier: missingType.iterableValue
```
### Removed option `checkGenericClassInNonGenericObjectType`
It's strongly recommended to add the missing generic typehints.
If you want to continue ignoring missing typehints from generics, add `missingType.generics` error identifier to your `ignoreErrors`:
```neon
parameters:
ignoreErrors:
-
identifier: missingType.generics
```
### Removed `checkAlwaysTrue*` options
These options have been removed because PHPStan now always behaves as if these were set to `true`:
* `checkAlwaysTrueCheckTypeFunctionCall`
* `checkAlwaysTrueInstanceof`
* `checkAlwaysTrueStrictComparison`
* `checkAlwaysTrueLooseComparison`
### Removed option `excludes_analyse`
It has been replaced with [`excludePaths`](https://phpstan.org/user-guide/ignoring-errors#excluding-whole-files).
### Paths in `excludePaths` and `ignoreErrors` have to be a valid file path or a fnmatch pattern
If you are excluding a file path that might not exist but you still want to have it in `excludePaths`, append `(?)`:
```neon
parameters:
excludePaths:
- tests/*/data/*
- src/broken
- node_modules (?) # optional path, might not exist
```
If you have the same situation in `ignoreErrors` (ignoring an error in a path that might not exist), use `reportUnmatchedIgnoredErrors: false`.
```neon
parameters:
reportUnmatchedIgnoredErrors: false
```
Appending `(?)` in `ignoreErrors` is not supported.
### Changes in 1st party PHPStan extensions
* [phpstan-doctrine](https://github.com/phpstan/phpstan-doctrine)
* Removed config parameter `searchOtherMethodsForQueryBuilderBeginning` (extension now behaves as when this was set to `true`)
* Removed config parameter `queryBuilderFastAlgorithm` (extension now behaves as when this was set to `false`)
* [phpstan-symfony](https://github.com/phpstan/phpstan-symfony)
* Removed legacy options with `_` in the name
* `container_xml_path` -> use `containerXmlPath`
* `constant_hassers` -> use `constantHassers`
* `console_application_loader` -> use `consoleApplicationLoader`
### Minor backward compatibility breaks
* Removed unused config parameter `cache.nodesByFileCountMax`
* Removed unused config parameter `memoryLimitFile`
* Removed unused feature toggle `disableRuntimeReflectionProvider`
* Removed unused config parameter `staticReflectionClassNamePatterns`
* Remove `fixerTmpDir` config parameter, use `pro.tmpDir` instead
* Remove `tempResultCachePath` config parameter, use `resultCachePath` instead
* `additionalConfigFiles` config parameter must be a list
## Upgrading guide for extension developers
> [!NOTE]
> Please switch to PHPStan 2.0 in a new major version of your extension. It's not feasible to try to support both PHPStan 1.x and PHPStan 2.x with the same extension code.
>
> You can definitely get closer to supporting PHPStan 2.0 without increasing major version by solving reported deprecations and other issues by analysing your extension code with PHPStan & phpstan-deprecation-rules & Bleeding Edge, but the final leap and solving backward incompatibilities should be done by requiring `"phpstan/phpstan": "^2.0"` in your `composer.json`, and releasing a new major version.
### PHPStan now uses nikic/php-parser v5
See [UPGRADING](https://github.com/nikic/PHP-Parser/blob/master/UPGRADE-5.0.md) guide for PHP-Parser.
The most notable change is how `throw` statement is represented. Previously, `throw` statements like `throw $e;` were represented using the `Stmt\Throw_` class, while uses inside other expressions (such as `$x ?? throw $e`) used the `Expr\Throw_` class.
Now, `throw $e;` is represented as a `Stmt\Expression` that contains an `Expr\Throw_`. The
`Stmt\Throw_` class has been removed.
### PHPStan now uses phpstan/phpdoc-parser v2
See [UPGRADING](https://github.com/phpstan/phpdoc-parser/blob/2.0.x/UPGRADING.md) guide for phpstan/phpdoc-parser.
### Returning plain strings as errors no longer supported, use RuleErrorBuilder
Identifiers are also required in custom rules.
Learn more: [Using RuleErrorBuilder to enrich reported errors in custom rules](https://phpstan.org/blog/using-rule-error-builder)
**Before**:
```php
return ['My error'];
```
**After**:
```php
return [
RuleErrorBuilder::message('My error')
->identifier('my.error')
->build(),
];
```
### Deprecate various `instanceof *Type` in favour of new methods on `Type` interface
Learn more: [Why Is instanceof *Type Wrong and Getting Deprecated?](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated)
### Removed deprecated `ParametersAcceptorSelector::selectSingle()`
Use [`ParametersAcceptorSelector::selectFromArgs()`](https://apiref.phpstan.org/2.0.x/PHPStan.Reflection.ParametersAcceptorSelector.html#_selectFromArgs) instead. It should be used in most places where `selectSingle()` was previously used, like dynamic return type extensions.
**Before**:
```php
$defaultReturnType = ParametersAcceptorSelector::selectSingle($functionReflection->getVariants())->getReturnType();
```
**After**:
```php
$defaultReturnType = ParametersAcceptorSelector::selectFromArgs(
$scope,
$functionCall->getArgs(),
$functionReflection->getVariants()
)->getReturnType();
```
If you're analysing function or method body itself and you're using one of the following methods, ask for `getParameters()` and `getReturnType()` directly on the reflection object:
* [InClassMethodNode::getMethodReflection()](https://apiref.phpstan.org/2.0.x/PHPStan.Node.InClassMethodNode.html)
* [InFunctionNode::getFunctionReflection()](https://apiref.phpstan.org/2.0.x/PHPStan.Node.InFunctionNode.html)
* [FunctionReturnStatementsNode::getFunctionReflection()](https://apiref.phpstan.org/2.0.x/PHPStan.Node.FunctionReturnStatementsNode.html)
* [MethodReturnStatementsNode::getMethodReflection()](https://apiref.phpstan.org/2.0.x/PHPStan.Node.MethodReturnStatementsNode.html)
* [Scope::getFunction()](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.Scope.html#_getFunction)
**Before**:
```php
$function = $node->getFunctionReflection();
$returnType = ParametersAcceptorSelector::selectSingle($function->getVariants())->getReturnType();
```
**After**:
```php
$returnType = $node->getFunctionReflection()->getReturnType();
```
### Changed `TypeSpecifier::create()` and `SpecifiedTypes` constructor parameters
[`PHPStan\Analyser\TypeSpecifier::create()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.TypeSpecifier.html#_create) now accepts (all parameters are required):
* `Expr $expr`
* `Type $type`
* `TypeSpecifierContext $context`
* `Scope $scope`
If you want to change `$overwrite` or `$rootExpr` (previous parameters also used to be accepted by this method), call `setAlwaysOverwriteTypes()` and `setRootExpr()` on [`SpecifiedTypes`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.SpecifiedTypes.html) (object returned by `TypeSpecifier::create()`). These methods return a new object (SpecifiedTypes is immutable).
[`SpecifiedTypes`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.SpecifiedTypes.html) constructor now accepts:
* `array $sureTypes`
* `array $sureNotTypes`
If you want to change `$overwrite` or `$rootExpr` (previous parameters also used to be accepted by the constructor), call `setAlwaysOverwriteTypes()` and `setRootExpr()`. These methods return a new object (SpecifiedTypes is immutable).
### `ConstantArrayType` no longer extends `ArrayType`
`Type::getArrays()` now returns `list<ArrayType|ConstantArrayType>`.
Using `$type instanceof ArrayType` is [being deprecated anyway](https://phpstan.org/blog/why-is-instanceof-type-wrong-and-getting-deprecated) so the impact of this change should be minimal.
### Changed `TypeSpecifier::specifyTypesInCondition()`
This method no longer accepts `Expr $rootExpr`. If you want to change it, call `setRootExpr()` on [`SpecifiedTypes`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.SpecifiedTypes.html) (object returned by `TypeSpecifier::specifyTypesInCondition()`). `setRootExpr()` method returns a new object (SpecifiedTypes is immutable).
### Node attributes `parent`, `previous`, `next` are no longer available
Learn more: https://phpstan.org/blog/preprocessing-ast-for-custom-rules
### Removed config parameter `scopeClass`
As a replacement you can implement [`PHPStan\Type\ExpressionTypeResolverExtension`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.ExpressionTypeResolverExtension.html) interface instead and register it as a service.
### Removed `PHPStan\Broker\Broker`
Use [`PHPStan\Reflection\ReflectionProvider`](https://apiref.phpstan.org/2.0.x/PHPStan.Reflection.ReflectionProvider.html) instead.
`BrokerAwareExtension` was also removed. Ask for `ReflectionProvider` in the extension constructor instead.
Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createReflectionProvider()`.
### List type is enabled for everyone
Removed static methods from `AccessoryArrayListType` class:
* `isListTypeEnabled()`
* `setListTypeEnabled()`
* `intersectWith()`
Instead of `AccessoryArrayListType::intersectWith($type)`, do `TypeCombinator::intersect($type, new AccessoryArrayListType())`.
### Minor backward compatibility breaks
* Classes that were previously `@final` were made `final`
* Parameter `$callableParameters` of [`MutatingScope::enterAnonymousFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterAnonymousFunction) and [`enterArrowFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterArrowFunction) made required
* Parameter `StatementContext $context` of [`NodeScopeResolver::processStmtNodes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.NodeScopeResolver.html#_processStmtNodes) made required
* ClassPropertiesNode - remove `$extensions` parameter from [`getUninitializedProperties()`](https://apiref.phpstan.org/2.0.x/PHPStan.Node.ClassPropertiesNode.html#_getUninitializedProperties)
* `Type::getSmallerType()`, `Type::getSmallerOrEqualType()`, `Type::getGreaterType()`, `Type::getGreaterOrEqualType()`, `Type::isSmallerThan()`, `Type::isSmallerThanOrEqual()` now require [`PhpVersion`](https://apiref.phpstan.org/2.0.x/PHPStan.Php.PhpVersion.html) as argument.
* `CompoundType::isGreaterThan()`, `CompoundType::isGreaterThanOrEqual()` now require [`PhpVersion`](https://apiref.phpstan.org/2.0.x/PHPStan.Php.PhpVersion.html) as argument.
* Removed `ReflectionProvider::supportsAnonymousClasses()` (all reflection providers support anonymous classes)
* Remove `ArrayType::generalizeKeys()`
* Remove `ArrayType::count()`, use `Type::getArraySize()` instead
* Remove `ArrayType::castToArrayKeyType()`, `Type::toArrayKey()` instead
* Remove `UnionType::pickTypes()`, use `pickFromTypes()` instead
* Remove `RegexArrayShapeMatcher::matchType()`, use `matchExpr()` instead
* Remove unused `PHPStanTestCase::$useStaticReflectionProvider`
* Remove `PHPStanTestCase::getReflectors()`, use `getReflector()` instead
* Remove `ClassReflection::getFileNameWithPhpDocs()`, use `getFileName()` instead
* Remove `AnalysisResult::getInternalErrors()`, use `getInternalErrorObjects()` instead
* Remove `ConstantReflection::getValue()`, use `getValueExpr()` instead. To get `Type` from `Expr`, use `Scope::getType()` or `InitializerExprTypeResolver::getType()`
* Remove `PropertyTag::getType()`, use `getReadableType()` / `getWritableType()` instead
* Remove `GenericTypeVariableResolver`, use [`Type::getTemplateType()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getTemplateType) instead
* Rename `Type::isClassStringType()` to `Type::isClassString()`
* Remove `Scope::isSpecified()`, use `hasExpressionType()` instead
* Remove `ConstantArrayType::isEmpty()`, use `isIterableAtLeastOnce()->no()` instead
* Remove `ConstantArrayType::getNextAutoIndex()`
* Removed methods from `ConstantArrayType` - `getFirst*Type` and `getLast*Type`
* Use `getFirstIterable*Type` and `getLastIterable*Type` instead
* Remove `ConstantArrayType::generalizeToArray()`
* Remove `ConstantArrayType::findTypeAndMethodName()`, use `findTypeAndMethodNames()` instead
* Remove `ConstantArrayType::removeLast()`, use [`Type::popArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_popArray) instead
* Remove `ConstantArrayType::removeFirst()`, use [`Type::shiftArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_shiftArray) instead
* Remove `ConstantArrayType::reverse()`, use [`Type::reverseArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_reverseArray) instead
* Remove `ConstantArrayType::chunk()`, use [`Type::chunkArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_chunkArray) instead
* Remove `ConstantArrayType::slice()`, use [`Type::sliceArray()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_sliceArray) instead
* Made `TypeUtils` thinner by removing methods:
* Remove `TypeUtils::getArrays()` and `getAnyArrays()`, use [`Type::getArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getArrays) instead
* Remove `TypeUtils::getConstantArrays()` and `getOldConstantArrays()`, use [`Type::getConstantArrays()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantArrays) instead
* Remove `TypeUtils::getConstantStrings()`, use [`Type::getConstantStrings()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantStrings) instead
* Remove `TypeUtils::getConstantTypes()` and `getAnyConstantTypes()`, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) or [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize)
* Remove `TypeUtils::generalizeType()`, use [`Type::generalize()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_generalize) instead
* Remove `TypeUtils::getDirectClassNames()`, use [`Type::getObjectClassNames()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getObjectClassNames) instead
* Remove `TypeUtils::getConstantScalars()`, use [`Type::isConstantScalarValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantScalarValue) or [`Type::getConstantScalarTypes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getConstantScalarTypes) instead
* Remove `TypeUtils::getEnumCaseObjects()`, use [`Type::getEnumCases()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getEnumCases) instead
* Remove `TypeUtils::containsCallable()`, use [`Type::isCallable()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isCallable) instead
* Removed `Scope::doNotTreatPhpDocTypesAsCertain()`, use `getNativeType()` instead
* Parameter `$isList` in `ConstantArrayType` constructor can only be `TrinaryLogic`, no longer `bool`
* Parameter `$nextAutoIndexes` in `ConstantArrayType` constructor can only be `non-empty-list<int>`, no longer `int`
* Remove `ConstantType` interface, use [`Type::isConstantValue()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_isConstantValue) instead
* `acceptsNamedArguments()` in `FunctionReflection`, `ExtendedMethodReflection` and `CallableParametersAcceptor` interfaces returns `TrinaryLogic` instead of `bool`
* Remove `FunctionReflection::isFinal()`
* [`Type::getProperty()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.Type.html#_getProperty) now returns [`ExtendedPropertyReflection`](https://apiref.phpstan.org/2.0.x/PHPStan.Reflection.ExtendedPropertyReflection.html)
* Remove `__set_state()` on objects that should not be serialized in cache
* Parameter `$selfClass` of [`TypehintHelper::decideTypeFromReflection()`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.TypehintHelper.html#_decideTypeFromReflection) no longer accepts `string`
* `LevelsTestCase::dataTopics()` data provider made static
* `PHPStan\Node\Printer\Printer` no longer autowired as `PhpParser\PrettyPrinter\Standard`, use `PHPStan\Node\Printer\Printer` in the typehint
* Remove `Type::acceptsWithReason()`, `Type:accepts()` return type changed from `TrinaryLogic` to [`AcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html)
* Remove `CompoundType::isAcceptedWithReasonBy()`, `CompoundType::isAcceptedBy()` return type changed from `TrinaryLogic` to [`AcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html)
Remove `Type::isSuperTypeOfWithReason()`, `Type:isSuperTypeOf()` return type changed from `TrinaryLogic` to [`IsSuperTypeOfResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.IsSuperTypeOfResult.html)
* Remove `CompoundType::isSubTypeOfWithReasonBy()`, `CompoundType::isSubTypeOf()` return type changed from `TrinaryLogic` to [`IsSuperTypeOfResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.IsSuperTypeOfResult.html)
* Remove `TemplateType::isValidVarianceWithReason()`, changed `TemplateType::isValidVariance()` return type to [`IsSuperTypeOfResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.IsSuperTypeOfResult.html)
* `RuleLevelHelper::accepts()` return type changed from `bool` to [`RuleLevelHelperAcceptsResult`](https://apiref.phpstan.org/2.0.x/PHPStan.Type.AcceptsResult.html)
* Changes around `ClassConstantReflection`
* Class `ClassConstantReflection` removed from BC promise, renamed to `RealClassConstantReflection`
* Interface `ConstantReflection` renamed to `ClassConstantReflection`
* Added more methods around PHPDoc types and native types to the (new) `ClassConstantReflection`
* Interface `GlobalConstantReflection` renamed to `ConstantReflection`
* Renamed interfaces and classes from `*WithPhpDocs` to `Extended*`
* `ParametersAcceptorWithPhpDocs` -> `ExtendedParametersAcceptor`
* `ParameterReflectionWithPhpDocs` -> `ExtendedParameterReflection`
* `FunctionVariantWithPhpDocs` -> `ExtendedFunctionVariant`
* `ClassPropertyNode::getNativeType()` return type changed from AST node to `Type|null`
* Class `PHPStan\Node\ClassMethod` (accessible from `ClassMethodsNode`) is no longer an AST node
* Call `PHPStan\Node\ClassMethod::getNode()` to access the original AST node
-124
View File
@@ -1,124 +0,0 @@
<?php declare(strict_types = 1);
namespace PHPStan;
use Composer\Autoload\ClassLoader;
use function class_exists;
use const PHP_VERSION_ID;
final class PharAutoloader
{
/** @var ClassLoader */
private static $composerAutoloader;
/** @var bool */
private static $polyfillsLoaded = false;
final public static function loadClass(string $class): void {
if (!extension_loaded('phar') || defined('__PHPSTAN_RUNNING__')) {
return;
}
if (strpos($class, '_PHPStan_') === 0) {
if (!in_array('phar', stream_get_wrappers(), true)) {
throw new \Exception('Phar wrapper is not registered. Please review your php.ini settings.');
}
if (self::$composerAutoloader === null) {
self::$composerAutoloader = require 'phar://' . __DIR__ . '/phpstan.phar/vendor/autoload.php';
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/jetbrains/phpstorm-stubs/PhpStormStubsMap.php';
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/react/async/src/functions_include.php';
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/react/promise/src/functions_include.php';
}
self::$composerAutoloader->loadClass($class);
return;
}
if (strpos($class, 'PHPStan\\') !== 0 || strpos($class, 'PHPStan\\PhpDocParser\\') === 0) {
return;
}
if (!in_array('phar', stream_get_wrappers(), true)) {
throw new \Exception('Phar wrapper is not registered. Please review your php.ini settings.');
}
if (!self::$polyfillsLoaded) {
self::$polyfillsLoaded = true;
if (
PHP_VERSION_ID < 80000
&& empty($GLOBALS['__composer_autoload_files']['a4a119a56e50fbb293281d9a48007e0e'])
&& !class_exists(\Symfony\Polyfill\Php80\Php80::class, false)
) {
$GLOBALS['__composer_autoload_files']['a4a119a56e50fbb293281d9a48007e0e'] = true;
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php80/Php80.php';
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php80/bootstrap.php';
}
if (
empty($GLOBALS['__composer_autoload_files']['0e6d7bf4a5811bfa5cf40c5ccd6fae6a'])
&& !class_exists(\Symfony\Polyfill\Mbstring\Mbstring::class, false)
) {
$GLOBALS['__composer_autoload_files']['0e6d7bf4a5811bfa5cf40c5ccd6fae6a'] = true;
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-mbstring/Mbstring.php';
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-mbstring/bootstrap.php';
}
if (
empty($GLOBALS['__composer_autoload_files']['e69f7f6ee287b969198c3c9d6777bd38'])
&& !class_exists(\Symfony\Polyfill\Intl\Normalizer\Normalizer::class, false)
) {
$GLOBALS['__composer_autoload_files']['e69f7f6ee287b969198c3c9d6777bd38'] = true;
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-intl-normalizer/Normalizer.php';
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-intl-normalizer/bootstrap.php';
}
if (
!extension_loaded('intl')
&& empty($GLOBALS['__composer_autoload_files']['8825ede83f2f289127722d4e842cf7e8'])
&& !class_exists(\Symfony\Polyfill\Intl\Grapheme\Grapheme::class, false)
) {
$GLOBALS['__composer_autoload_files']['8825ede83f2f289127722d4e842cf7e8'] = true;
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-intl-grapheme/Grapheme.php';
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-intl-grapheme/bootstrap.php';
}
if (
PHP_VERSION_ID < 80100
&& empty ($GLOBALS['__composer_autoload_files']['23c18046f52bef3eea034657bafda50f'])
&& !class_exists(\Symfony\Polyfill\Php81\Php81::class, false)
) {
$GLOBALS['__composer_autoload_files']['23c18046f52bef3eea034657bafda50f'] = true;
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php81/Php81.php';
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php81/bootstrap.php';
}
if (
PHP_VERSION_ID < 80300
&& empty ($GLOBALS['__composer_autoload_files']['662a729f963d39afe703c9d9b7ab4a8c'])
&& !class_exists(\Symfony\Polyfill\Php83\Php83::class, false)
) {
$GLOBALS['__composer_autoload_files']['662a729f963d39afe703c9d9b7ab4a8c'] = true;
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php83/Php83.php';
require_once 'phar://' . __DIR__ . '/phpstan.phar/vendor/symfony/polyfill-php83/bootstrap.php';
}
}
$filename = str_replace('\\', DIRECTORY_SEPARATOR, $class);
if (strpos($class, 'PHPStan\\BetterReflection\\') === 0) {
$filename = substr($filename, strlen('PHPStan\\BetterReflection\\'));
$filepath = 'phar://' . __DIR__ . '/phpstan.phar/vendor/ondrejmirtes/better-reflection/src/' . $filename . '.php';
} else {
$filename = substr($filename, strlen('PHPStan\\'));
$filepath = 'phar://' . __DIR__ . '/phpstan.phar/src/' . $filename . '.php';
}
if (!file_exists($filepath)) {
return;
}
require $filepath;
}
}
spl_autoload_register([PharAutoloader::class, 'loadClass']);
-31
View File
@@ -1,31 +0,0 @@
{
"name": "phpstan/phpstan",
"description": "PHPStan - PHP Static Analysis Tool",
"license": ["MIT"],
"keywords": ["dev", "static analysis"],
"require": {
"php": "^7.4|^8.0"
},
"conflict": {
"phpstan/phpstan-shim": "*"
},
"bin": [
"phpstan",
"phpstan.phar"
],
"autoload": {
"files": ["bootstrap.php"]
},
"source": {
"type": "",
"url": "",
"reference": ""
},
"support": {
"issues": "https://github.com/phpstan/phpstan/issues",
"forum": "https://github.com/phpstan/phpstan/discussions",
"source": "https://github.com/phpstan/phpstan-src",
"docs": "https://phpstan.org/user-guide/getting-started",
"security": "https://github.com/phpstan/phpstan/security/policy"
}
}
-2
View File
@@ -1,2 +0,0 @@
includes:
- phar://phpstan.phar/conf/bleedingEdge.neon
-8
View File
@@ -1,8 +0,0 @@
#!/usr/bin/env php
<?php
declare (strict_types=1);
Phar::loadPhar(__DIR__ . '/phpstan.phar', 'phpstan.phar');
require 'phar://phpstan.phar/bin/phpstan';
Binary file not shown.
-16
View File
@@ -1,16 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEynwsejDI6OEnSoR2UcZzBf/C5cAFAmjpFJAACgkQUcZzBf/C
5cBX9w/+Madphjrc81G2k9OtvthicE1g55EdRCLDTuEyzGeKqYTap72EhoQbTUMQ
0D41PmY56TIygKhnboV56cWik30rquU4nQi8e+rasc/ABLAG3/z/ZEJiTt0OLQ86
xe81K4nUI/jHSZQwngGYnW+ex+C8yGspdVDuXyJHMtRgqCT7LBxZoSG+51Q85bZE
+o2hPut0O1iGli9golrbcUMUzRNcnbm5vV+1tgv3LBqZA0bOZntSTm1qpgVaZ1/V
hgp0HbTj4WAxYY7kd/MUnD73M1CVqv0/h4xtCnyqU3qlLIyxs/HyUp2igA1eV7Ju
W7B1NFEfqinf8LLKV7IUO2n63fkesD/yQcBYA6q9h9NVqBqKnTsH6Pg27e6pbkJD
dUqJbVRjo8T61nmHgItb8CHMBrLmKcPt8T8eTPNOCNAakLEr2bOsuqooM6taSBSI
wtxOrBgDj4P2+wTlCEBjdUWMnAFpvrhBU/IMfgI06GKUvnIZqCAxe8jyhwZVAXUu
Ag7nPZhjTPBGLSqPsfJGJ4CnnMit57Art6g3C1r7upOkbmu4TRf9sV2jlLzVIWVa
xpUwoxGrU77QM6NkcsFbVLn6qXl6zF4WeYeQf0iAPnrJPjOQh3aIpmtonRO/GLwb
yrl04HzXtr/tid+fhNUV67ocUvRX6CzYL4FWPj16qTTN1PVXrNM=
=Q/DA
-----END PGP SIGNATURE-----
-25
View File
@@ -1,25 +0,0 @@
The MIT License
---------------
Copyright (c) 2017-present Tomáš Votruba (https://tomasvotruba.cz)
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
-166
View File
@@ -1,166 +0,0 @@
# Rector - Instant Upgrades and Automated Refactoring
[![Downloads](https://img.shields.io/packagist/dt/rector/rector.svg?style=flat-square)](https://packagist.org/packages/rector/rector)
<br>
Rector instantly upgrades and refactors the PHP code of your application. It can help you in 2 major areas:
### 1. Instant Upgrades
Rector now supports upgrades from PHP 5.3 to 8.4 and major open-source projects like [Symfony](https://github.com/rectorphp/rector-symfony), [PHPUnit](https://github.com/rectorphp/rector-phpunit), and [Doctrine](https://github.com/rectorphp/rector-doctrine). Do you want to **be constantly on the latest PHP and Framework without effort**?
Use Rector to handle **instant upgrades** for you.
### 2. Automated Refactoring
Do you have code quality you need, but struggle to keep it with new developers in your team? Do you want to see smart code-reviews even when every senior developers sleeps?
Add Rector to your CI and let it **continuously refactor your code** and keep the code quality high.
Read our [blogpost](https://getrector.com/blog/new-setup-ci-command-to-let-rector-work-for-you) to see how to set up automated refactoring.
## Install
```bash
composer require rector/rector --dev
```
## Running Rector
There are 2 main ways to use Rector:
- a *single rule*, to have the change under control
- or group of rules called *sets*
To use them, create a `rector.php` in your root directory:
```bash
vendor/bin/rector
```
And modify it:
```php
use Rector\Config\RectorConfig;
use Rector\TypeDeclaration\Rector\Property\TypedPropertyFromStrictConstructorRector;
return RectorConfig::configure()
// register single rule
->withRules([
TypedPropertyFromStrictConstructorRector::class
])
// here we can define, what prepared sets of rules will be applied
->withPreparedSets(
deadCode: true,
codeQuality: true
);
```
Then dry run Rector:
```bash
vendor/bin/rector src --dry-run
```
Rector will show you diff of files that it *would* change. To *make* the changes, drop `--dry-run`:
```bash
vendor/bin/rector src
```
## Documentation
* Find [full documentation here](https://getrector.com/documentation/).
* [Explore Rector Rules](https://getrector.com/find-rule)
<br>
## Learn Faster with a Book
Are you curious, how Rector works internally, how to create your own rules and test them and why Rector was born?
Read [Rector - The Power of Automated Refactoring](https://leanpub.com/rector-the-power-of-automated-refactoring) that will take you step by step through the Rector setup and how to create your own rules.
<br>
## Empowered by Community :heart:
The Rector community is powerful thanks to active maintainers who take care of Rector sets for particular projects.
Among there projects belong:
* [palantirnet/drupal-rector](https://github.com/palantirnet/drupal-rector)
* [craftcms/rector](https://github.com/craftcms/rector)
* [FriendsOfShopware/shopware-rector](https://github.com/FriendsOfShopware/shopware-rector)
* [sabbelasichon/typo3-rector](https://github.com/sabbelasichon/typo3-rector)
* [sulu/sulu-rector](https://github.com/sulu/sulu-rector)
* [efabrica-team/rector-nette](https://github.com/efabrica-team/rector-nette)
* [Sylius/SyliusRector](https://github.com/Sylius/SyliusRector)
* [CoditoNet/rector-money](https://github.com/CoditoNet/rector-money)
* [laminas/laminas-servicemanager-migration](https://github.com/laminas/laminas-servicemanager-migration)
* [cakephp/upgrade](https://github.com/cakephp/upgrade)
* [driftingly/rector-laravel](https://github.com/driftingly/rector-laravel)
* [contao/contao-rector](https://github.com/contao/contao-rector)
* [php-static-analysis/rector-rule](https://github.com/php-static-analysis/rector-rule)
* [ibexa/rector](https://github.com/ibexa/rector)
<br>
## Hire us to get Job Done :muscle:
Rector is a tool that [we develop](https://getrector.com/) and share for free, so anyone can automate their refactoring. But not everyone has dozens of hours to understand complexity of abstract-syntax-tree in their own time. **That's why we provide commercial support - to save your time**.
Would you like to apply Rector on your code base but don't have time for the struggle with your project? [Hire us](https://getrector.com/contact) to get there faster.
<br>
## How to Contribute
See [the contribution guide](/CONTRIBUTING.md) or go to development repository [rector/rector-src](https://github.com/rectorphp/rector-src).
<br>
## Debugging
You can use `--debug` option, that will print nested exceptions output:
```bash
vendor/bin/rector src/Controller --dry-run --debug
```
Or with Xdebug:
1. Make sure [Xdebug](https://xdebug.org/) is installed and configured
2. Add `--xdebug` option when running Rector
```bash
vendor/bin/rector src/Controller --dry-run --xdebug
```
To assist with simple debugging Rector provides 2 helpers to pretty-print AST-nodes:
```php
use PhpParser\Node\Scalar\String_;
$node = new String_('hello world!');
// prints node to string, as PHP code displays it
print_node($node);
```
<br>
## Known Drawbacks
* Rector uses [nikic/php-parser](https://github.com/nikic/PHP-Parser/), built on technology called an *abstract syntax tree* (AST). An AST doesn't know about spaces and when written to a file it produces poorly formatted code in both PHP and docblock annotations.
* Rector in parallel mode will work most of the times for most OS. On Windows, you may encounter issues unresolvable despite of following the [Troubleshooting Parallel](https://getrector.com/documentation/troubleshooting-parallel) guide. In such case, check if you are using Powershell 7 (pwsh). Change your terminal to command prompt (cmd) or bash for Windows.
### How to Apply Coding Standards?
**Your project needs to have a coding standard tool** and a set of formatting rules, so it can make Rector's output code nice and shiny again.
We're using [ECS](https://github.com/symplify/easy-coding-standard) with [this setup](https://github.com/rectorphp/rector-src/blob/main/ecs.php).
### May cause unexpected output on File with mixed PHP+HTML content
When you apply changes to files with PHP + HTML content, you may need to manually verify the changed file after apply the changes.
-106
View File
@@ -1,106 +0,0 @@
# Upgrading from Rector 1.x to 2.0
## PHP version requirements
Rector now uses PHP 7.4 or newer to run.
<br>
## Rector now uses PHP-Parser 5
See [upgrading guide](https://github.com/nikic/PHP-Parser/blob/master/UPGRADE-5.0.md) for PHP-Parser.
<br>
## Rector now uses PHPStan 2
See [upgrading guide](https://github.com/phpstan/phpstan-src/blob/2.0.x/UPGRADING.md) for PHPStan.
<br>
## Upgrade for custom Rules writers
### 1. `AbstractScopeAwareRector` is removed, use `AbstractRector` instead
The `Rector\Rector\AbstractScopeAwareRector` was too granular to fetch single helper object. It made creating new custom rules ambiguous, one layer more complex and confusing. This class has been removed in favor of standard `AbstractRector`. The `Scope` object can be fetched via `ScopeFetcher`.
**Before**
```php
use Rector\Rector\AbstractScopeAwareRector;
final class SimpleRector extends AbstractScopeAwareRector
{
public function refactorWithScope(Node $node, Scope $scope): ?Node
{
// ...
}
}
```
**After**
```php
use Rector\Rector\AbstractRector;
use Rector\PHPStan\ScopeFetcher;
final class SimpleRector extends AbstractRector
{
public function refactor(Node $node): ?Node
{
if (...) {
// this allow to fetch scope only when needed
$scope = ScopeFetcher::fetch($node);
}
// ...
}
}
```
### 2. `AbstractRector` get focused on code, the `getRuleDefinition()` is no longer required
Core rules need documentation, so people can read their feature and [search through](https://getrector.com/find-rule) them. Yet for writing custom rules and local rules, its not necessary. People often filled it empty, just to make Rector happy.
This is no longer needed. Now The `getRuleDefinition()` method has been removed:
```diff
use Rector\Rector\AbstractRector;
-use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
-use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
final class SimpleRector extends AbstractRector
{
- public function getRuleDefinition(): RuleDefinition
- {
- return new RuleDefinition('// @todo fill the description', [
- new CodeSample(
- <<<'CODE_SAMPLE'
-// @todo fill code before
-CODE_SAMPLE
- ,
- <<<'CODE_SAMPLE'
-// @todo fill code after
-CODE_SAMPLE
- ),
- ]);
- }
// valuable code here
}
```
If you need description yourself to understand rule after many months, use the common place for documentation - docblock above class.
### 3. `SetListInterface` was removed
The deprecated `SetListInterface` was removed, if you created your own list just remove the Interface from it:
```diff
-use Rector\Set\Contract\SetListInterface;
-final class YourSetList implements SetListInterface
+final class YourSetList
```
-88
View File
@@ -1,88 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use RectorPrefix202510\Nette\Loaders\RobotLoader;
use Rector\Bridge\SetRectorsResolver;
use RectorPrefix202510\Symfony\Component\Console\Input\ArrayInput;
use RectorPrefix202510\Symfony\Component\Console\Output\ConsoleOutput;
use RectorPrefix202510\Symfony\Component\Console\Style\SymfonyStyle;
use RectorPrefix202510\Symfony\Component\Finder\Finder;
use RectorPrefix202510\Symfony\Component\Finder\SplFileInfo;
use RectorPrefix202510\Webmozart\Assert\Assert;
require __DIR__ . '/../vendor/autoload.php';
// 1. find all rector rules in here and in all vendor/rector dirs
$rectorClassFinder = new RectorClassFinder();
$rectorClasses = $rectorClassFinder->find([__DIR__ . '/../rules', __DIR__ . '/../vendor/rector/rector-doctrine', __DIR__ . '/../vendor/rector/rector-phpunit', __DIR__ . '/../vendor/rector/rector-symfony', __DIR__ . '/../vendor/rector/rector-downgrade-php']);
$symfonyStyle = new SymfonyStyle(new ArrayInput([]), new ConsoleOutput());
$symfonyStyle->writeln(\sprintf('<fg=green>Found Rector %d rules</>', \count($rectorClasses)));
$rectorSeFinder = new RectorSetFinder();
$rectorSetFiles = $rectorSeFinder->find([__DIR__ . '/../config/set', __DIR__ . '/../vendor/rector/rector-symfony/config/sets', __DIR__ . '/../vendor/rector/rector-doctrine/config/sets', __DIR__ . '/../vendor/rector/rector-phpunit/config/sets', __DIR__ . '/../vendor/rector/rector-downgrade-php/config/set']);
$symfonyStyle->writeln(\sprintf('<fg=green>Found %d sets</>', \count($rectorSetFiles)));
$usedRectorClassResolver = new UsedRectorClassResolver();
$usedRectorRules = $usedRectorClassResolver->resolve($rectorSetFiles);
$symfonyStyle->newLine();
$symfonyStyle->writeln(\sprintf('<fg=yellow>Found %d used Rector rules in sets</>', \count($usedRectorRules)));
$unusedRectorRules = \array_diff($rectorClasses, $usedRectorRules);
$symfonyStyle->writeln(\sprintf('<fg=yellow;options=bold>Found %d Rector rules not in any set</>', \count($unusedRectorRules)));
$symfonyStyle->newLine();
$symfonyStyle->listing($unusedRectorRules);
final class RectorClassFinder
{
/**
* @param string[] $dirs
* @return string[]
*/
public function find(array $dirs): array
{
$robotLoader = new RobotLoader();
$robotLoader->acceptFiles = ['*Rector.php'];
$robotLoader->addDirectory(...$dirs);
$robotLoader->setTempDirectory(\sys_get_temp_dir() . '/rector-rules');
$robotLoader->refresh();
return \array_keys($robotLoader->getIndexedClasses());
}
}
\class_alias('RectorClassFinder', 'RectorClassFinder', \false);
final class RectorSetFinder
{
/**
* @param string[] $configDirs
* @return string[]
*/
public function find(array $configDirs): array
{
Assert::allString($configDirs);
Assert::allDirectory($configDirs);
// find set files
$finder = (new Finder())->in($configDirs)->files()->name('*.php');
/** @var SplFileInfo[] $setFileInfos */
$setFileInfos = \iterator_to_array($finder->getIterator());
$setFiles = [];
foreach ($setFileInfos as $setFileInfo) {
$setFiles[] = $setFileInfo->getRealPath();
}
return $setFiles;
}
}
\class_alias('RectorSetFinder', 'RectorSetFinder', \false);
final class UsedRectorClassResolver
{
/**
* @param string[] $rectorSetFiles
* @return string[]
*/
public function resolve(array $rectorSetFiles): array
{
$setRectorsResolver = new SetRectorsResolver();
$rulesConfiguration = $setRectorsResolver->resolveFromFilePathsIncludingConfiguration($rectorSetFiles);
$usedRectorRules = [];
foreach ($rulesConfiguration as $ruleConfiguration) {
$usedRectorRules[] = \is_string($ruleConfiguration) ? $ruleConfiguration : \array_keys($ruleConfiguration)[0];
}
\sort($usedRectorRules);
return \array_unique($usedRectorRules);
}
}
\class_alias('UsedRectorClassResolver', 'UsedRectorClassResolver', \false);
-5
View File
@@ -1,5 +0,0 @@
#!/usr/bin/env php
<?php
namespace RectorPrefix202510;
require_once __DIR__ . '/rector.php';
-130
View File
@@ -1,130 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use RectorPrefix202510\Nette\Utils\Json;
use Rector\Bootstrap\RectorConfigsResolver;
use Rector\ChangesReporting\Output\JsonOutputFormatter;
use Rector\Configuration\Option;
use Rector\Console\Style\SymfonyStyleFactory;
use Rector\DependencyInjection\LazyContainerFactory;
use Rector\DependencyInjection\RectorContainerFactory;
use Rector\Util\Reflection\PrivatesAccessor;
use RectorPrefix202510\Symfony\Component\Console\Application;
use RectorPrefix202510\Symfony\Component\Console\Command\Command;
use RectorPrefix202510\Symfony\Component\Console\Input\ArgvInput;
// @ intentionally: continue anyway
@\ini_set('memory_limit', '-1');
// Performance boost
\error_reporting(\E_ALL);
\ini_set('display_errors', 'stderr');
\gc_disable();
\define('__RECTOR_RUNNING__', \true);
// Require Composer autoload.php
$autoloadIncluder = new AutoloadIncluder();
$autoloadIncluder->includeDependencyOrRepositoryVendorAutoloadIfExists();
final class AutoloadIncluder
{
/**
* @var string[]
*/
private array $alreadyLoadedAutoloadFiles = [];
public function includeDependencyOrRepositoryVendorAutoloadIfExists(): void
{
// Rector's vendor is already loaded
if (\class_exists(LazyContainerFactory::class)) {
return;
}
// in Rector develop repository
$this->loadIfExistsAndNotLoadedYet(__DIR__ . '/../vendor/autoload.php');
}
/**
* In case Rector is installed as vendor dependency,
* this autoloads the project vendor/autoload.php, including Rector
*/
public function autoloadProjectAutoloaderFile(): void
{
$this->loadIfExistsAndNotLoadedYet(__DIR__ . '/../../../autoload.php');
}
/**
* In case Rector is installed as global dependency
*/
public function autoloadRectorInstalledAsGlobalDependency(): void
{
if (\dirname(__DIR__) === \dirname(\getcwd(), 2)) {
return;
}
if (\is_dir('vendor/rector/rector')) {
return;
}
$this->loadIfExistsAndNotLoadedYet('vendor/autoload.php');
}
public function autoloadFromCommandLine(): void
{
$cliArgs = $_SERVER['argv'];
$aOptionPosition = \array_search('-a', $cliArgs, \true);
$autoloadFileOptionPosition = \array_search('--autoload-file', $cliArgs, \true);
if (\is_int($aOptionPosition)) {
$autoloadOptionPosition = $aOptionPosition;
} elseif (\is_int($autoloadFileOptionPosition)) {
$autoloadOptionPosition = $autoloadFileOptionPosition;
} else {
return;
}
$autoloadFileValuePosition = $autoloadOptionPosition + 1;
$fileToAutoload = $cliArgs[$autoloadFileValuePosition] ?? null;
if ($fileToAutoload === null) {
return;
}
$this->loadIfExistsAndNotLoadedYet($fileToAutoload);
}
public function loadIfExistsAndNotLoadedYet(string $filePath): void
{
if (!\file_exists($filePath)) {
return;
}
if (\in_array($filePath, $this->alreadyLoadedAutoloadFiles, \true)) {
return;
}
/** @var non-empty-string $realPath always string after file_exists() check */
$realPath = \realpath($filePath);
$this->alreadyLoadedAutoloadFiles[] = $realPath;
require_once $filePath;
}
}
\class_alias('RectorPrefix202510\AutoloadIncluder', 'AutoloadIncluder', \false);
if (\file_exists(__DIR__ . '/../preload.php') && \is_dir(__DIR__ . '/../vendor')) {
require_once __DIR__ . '/../preload.php';
}
// require rector-src on split packages
if (\file_exists(__DIR__ . '/../preload-split-package.php') && \is_dir(__DIR__ . '/../../../../vendor')) {
require_once __DIR__ . '/../preload-split-package.php';
}
$autoloadIncluder->loadIfExistsAndNotLoadedYet(__DIR__ . '/../vendor/scoper-autoload.php');
$autoloadIncluder->autoloadProjectAutoloaderFile();
$autoloadIncluder->autoloadRectorInstalledAsGlobalDependency();
$autoloadIncluder->autoloadFromCommandLine();
$rectorConfigsResolver = new RectorConfigsResolver();
try {
$bootstrapConfigs = $rectorConfigsResolver->provide();
$rectorContainerFactory = new RectorContainerFactory();
$container = $rectorContainerFactory->createFromBootstrapConfigs($bootstrapConfigs);
} catch (\Throwable $throwable) {
// for json output
$argvInput = new ArgvInput();
$outputFormat = $argvInput->getParameterOption('--' . Option::OUTPUT_FORMAT);
// report fatal error in json format
if ($outputFormat === JsonOutputFormatter::NAME) {
echo Json::encode(['fatal_errors' => [$throwable->getMessage()]]);
} else {
// report fatal errors in console format
$symfonyStyleFactory = new SymfonyStyleFactory(new PrivatesAccessor());
$symfonyStyle = $symfonyStyleFactory->create();
$symfonyStyle->error(\str_replace("\r\n", "\n", $throwable->getMessage()));
}
exit(Command::FAILURE);
}
/** @var Application $application */
$application = $container->get(Application::class);
exit($application->run());
-55
View File
@@ -1,55 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix20220529;
// resolve git version stored in released rector
// tag for tagged one, hash for dev
/**
* Inspired by https://github.com/composer/composer/blob/master/src/Composer/Composer.php
* See https://github.com/composer/composer/blob/6587715d0f8cae0cd39073b3bc5f018d0e6b84fe/src/Composer/Compiler.php#L208
*
* @see \Rector\Core\Tests\Application\VersionResolverTest
*/
final class VersionResolver
{
/**
* @var int
*/
private const SUCCESS_CODE = 0;
public function resolve() : string
{
// resolve current tag
\exec('git tag --points-at', $tagExecOutput, $tagExecResultCode);
if ($tagExecResultCode !== self::SUCCESS_CODE) {
die('Ensure to run compile from composer git repository clone and that git binary is available.');
}
// debug output
\var_dump($tagExecOutput);
if ($tagExecOutput !== []) {
$tag = $tagExecOutput[0];
if ($tag !== '') {
return $tag;
}
}
\exec('git log --pretty="%H" -n1 HEAD', $commitHashExecOutput, $commitHashResultCode);
if ($commitHashResultCode !== 0) {
die('Ensure to run compile from composer git repository clone and that git binary is available.');
}
// debug output
\var_dump($commitHashExecOutput);
$version = \trim($commitHashExecOutput[0]);
return \trim($version, '"');
}
}
// resolve git version stored in released rector
// tag for tagged one, hash for dev
/**
* Inspired by https://github.com/composer/composer/blob/master/src/Composer/Composer.php
* See https://github.com/composer/composer/blob/6587715d0f8cae0cd39073b3bc5f018d0e6b84fe/src/Composer/Compiler.php#L208
*
* @see \Rector\Core\Tests\Application\VersionResolverTest
*/
\class_alias('VersionResolver', 'VersionResolver', \false);
$versionResolver = new \RectorPrefix20220529\VersionResolver();
echo $versionResolver->resolve() . \PHP_EOL;
-53
View File
@@ -1,53 +0,0 @@
<?php
declare(strict_types=1);
use PHPParser\Node;
use PHPUnit\Runner\Version;
/**
* The preload.php contains 2 dependencies
* - phpstan/phpdoc-parser
* - nikic/php-parser
*
* They need to be loaded early to avoid conflict version between rector prefixed vendor and Project vendor
* For example, a project may use phpstan/phpdoc-parser v1, while rector uses phpstan/phpdoc-parser uses v2, that will error as class or logic are different.
*/
if (
// verify PHPUnit is running
defined('PHPUNIT_COMPOSER_INSTALL')
// no need to preload if Node interface exists
&& ! interface_exists(Node::class, false)
// load preload.php on local PHPUnit installation
&& ! class_exists(Version::class, false)
// load preload.php only on PHPUnit 12+
&& class_exists(Version::class, true) && (int) Version::id() >= 12
) {
require_once __DIR__ . '/preload.php';
}
// inspired by https://github.com/phpstan/phpstan/blob/master/bootstrap.php
spl_autoload_register(function (string $class): void {
static $composerAutoloader;
// already loaded in bin/rector.php
if (defined('__RECTOR_RUNNING__')) {
return;
}
// load prefixed or native class, e.g. for running tests
if (strpos($class, 'RectorPrefix') === 0 || strpos($class, 'Rector\\') === 0) {
if ($composerAutoloader === null) {
// prefixed version autoload
$composerAutoloader = require __DIR__ . '/vendor/autoload.php';
}
// some weird collision with PHPStan custom rule tests
if (! is_int($composerAutoloader)) {
$composerAutoloader->loadClass($class);
}
}
});
-30
View File
@@ -1,30 +0,0 @@
{
"name": "rector/rector",
"description": "Instant Upgrade and Automated Refactoring of any PHP code",
"homepage": "https://getrector.com/",
"license": "MIT",
"keywords": ["dev", "refactoring", "automation", "migration"],
"bin": [
"bin/rector"
],
"require": {
"php": "^7.4|^8.0",
"phpstan/phpstan": "^2.1.26"
},
"autoload": {
"files": [
"bootstrap.php"
]
},
"conflict": {
"rector/rector-phpunit": "*",
"rector/rector-symfony": "*",
"rector/rector-doctrine": "*",
"rector/rector-downgrade-php": "*"
},
"minimum-stability": "dev",
"prefer-stable": true,
"suggest": {
"ext-dom": "To manipulate phpunit.xml via the custom-rule command"
}
}
-39
View File
@@ -1,39 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use RectorPrefix202510\OndraM\CiDetector\CiDetector;
use Rector\Bootstrap\ExtensionConfigResolver;
use Rector\Caching\ValueObject\Storage\MemoryCacheStorage;
use Rector\Config\RectorConfig;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->paths([]);
$rectorConfig->skip([]);
$rectorConfig->autoloadPaths([]);
$rectorConfig->bootstrapFiles([]);
$rectorConfig->parallel();
// to avoid autoimporting out of the box
$rectorConfig->importNames(\false, \false);
$rectorConfig->removeUnusedImports(\false);
$rectorConfig->importShortClasses();
$rectorConfig->indent(' ', 4);
$rectorConfig->fileExtensions(['php']);
$rectorConfig->cacheDirectory(\sys_get_temp_dir() . '/rector_cached_files');
$rectorConfig->containerCacheDirectory(\sys_get_temp_dir());
// use faster in-memory cache in CI.
// CI always starts from scratch, therefore IO intensive caching is not worth it
if ((new CiDetector())->isCiDetected()) {
$rectorConfig->cacheClass(MemoryCacheStorage::class);
}
// load internal rector-* extension configs
$extensionConfigResolver = new ExtensionConfigResolver();
foreach ($extensionConfigResolver->provide() as $extensionConfigFile) {
$rectorConfig->import($extensionConfigFile);
}
// use original php-parser printer to avoid BC break on fluent call
$rectorConfig->newLineOnFluentCall(\false);
// allow real paths in output formatters
$rectorConfig->reportingRealPath(\false);
$rectorConfig->treatClassesAsFinal(\false);
};
@@ -1,2 +0,0 @@
parameters:
inferPrivatePropertyTypeFromConstructor: true
-27
View File
@@ -1,27 +0,0 @@
# see original config.neon in phpstan.neon - https://github.com/phpstan/phpstan-src/blob/386eb913abb6ac05886c5642fd48b5d99db66a20/conf/config.neon#L1582
# this file overrides definitions from the config above
services:
defaultAnalysisParser:
factory: @pathRoutingParser
arguments!: []
cachedRectorParser:
class: PHPStan\Parser\CachedParser
arguments:
originalParser: @rectorParser
cachedNodesByStringCountMax: %cache.nodesByStringCountMax%
autowired: false
pathRoutingParser:
class: PHPStan\Parser\PathRoutingParser
arguments:
currentPhpVersionRichParser: @cachedRectorParser
currentPhpVersionSimpleParser: @cachedRectorParser
php8Parser: @php8Parser
autowired: false
rectorParser:
class: PHPStan\Parser\RichParser
arguments:
parser: @currentPhpVersionPhpParser
autowired: no
@@ -1,10 +0,0 @@
services:
- Rector\NodeTypeResolver\Reflection\BetterReflection\RectorBetterReflectionSourceLocatorFactory
- Rector\NodeTypeResolver\Reflection\BetterReflection\SourceLocator\IntermediateSourceLocator
- Rector\NodeTypeResolver\Reflection\BetterReflection\SourceLocatorProvider\DynamicSourceLocatorProvider
# basically decorates native PHPStan source locator with a dynamic source locator that is also available in Rector DI
betterReflectionSourceLocator:
class: PHPStan\BetterReflection\SourceLocator\Type\SourceLocator
factory: ['@Rector\NodeTypeResolver\Reflection\BetterReflection\RectorBetterReflectionSourceLocatorFactory', 'create']
autowired: false
-10
View File
@@ -1,10 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Assert\Rector\ClassMethod\AddAssertArrayFromClassMethodDocblockRector;
use Rector\Config\RectorConfig;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([AddAssertArrayFromClassMethodDocblockRector::class]);
};
@@ -1,11 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Php80\Rector\Class_\AnnotationToAttributeRector;
use Rector\Php80\ValueObject\AnnotationToAttribute;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->ruleWithConfiguration(AnnotationToAttributeRector::class, [new AnnotationToAttribute('Given', 'Behat\Step\Given', [], \true), new AnnotationToAttribute('When', 'Behat\Step\When', [], \true), new AnnotationToAttribute('Then', 'Behat\Step\Then', [], \true), new AnnotationToAttribute('BeforeSuite', 'Behat\Hook\BeforeSuite', [], \true), new AnnotationToAttribute('AfterSuite', 'Behat\Hook\AfterSuite', [], \true), new AnnotationToAttribute('BeforeFeature', 'Behat\Hook\BeforeFeature', [], \true), new AnnotationToAttribute('AfterFeature', 'Behat\Hook\AfterFeature', [], \true), new AnnotationToAttribute('BeforeScenario', 'Behat\Hook\BeforeScenario', [], \true), new AnnotationToAttribute('AfterScenario', 'Behat\Hook\AfterScenario', [], \true), new AnnotationToAttribute('BeforeStep', 'Behat\Hook\BeforeStep', [], \true), new AnnotationToAttribute('AfterStep', 'Behat\Hook\AfterStep', [], \true)]);
};
-15
View File
@@ -1,15 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\Level\CodeQualityLevel;
use Rector\Config\RectorConfig;
return static function (RectorConfig $rectorConfig): void {
foreach (CodeQualityLevel::RULES_WITH_CONFIGURATION as $rectorClass => $configuration) {
$rectorConfig->ruleWithConfiguration($rectorClass, $configuration);
}
// the rule order matters, as its used in withCodeQualityLevel() method
// place the safest rules first, follow by more complex ones
$rectorConfig->rules(CodeQualityLevel::RULES);
};
-15
View File
@@ -1,15 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\Level\CodingStyleLevel;
use Rector\Config\RectorConfig;
return static function (RectorConfig $rectorConfig): void {
foreach (CodingStyleLevel::RULES_WITH_CONFIGURATION as $rectorClass => $configuration) {
$rectorConfig->ruleWithConfiguration($rectorClass, $configuration);
}
// the rule order matters, as its used in withCodingStyleLevel() method
// place the safest rules first, follow by more complex ones
$rectorConfig->rules(CodingStyleLevel::RULES);
};
@@ -1,13 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Carbon\Rector\FuncCall\DateFuncCallToCarbonRector;
use Rector\Carbon\Rector\FuncCall\TimeFuncCallToCarbonRector;
use Rector\Carbon\Rector\MethodCall\DateTimeMethodCallToCarbonRector;
use Rector\Carbon\Rector\New_\DateTimeInstanceToCarbonRector;
use Rector\Config\RectorConfig;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([DateFuncCallToCarbonRector::class, DateTimeInstanceToCarbonRector::class, DateTimeMethodCallToCarbonRector::class, TimeFuncCallToCarbonRector::class]);
};
-10
View File
@@ -1,10 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\Level\DeadCodeLevel;
use Rector\Config\RectorConfig;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules(DeadCodeLevel::RULES);
};
-17
View File
@@ -1,17 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\EarlyReturn\Rector\Foreach_\ChangeNestedForeachIfsToEarlyContinueRector;
use Rector\EarlyReturn\Rector\If_\ChangeIfElseValueAssignToEarlyReturnRector;
use Rector\EarlyReturn\Rector\If_\ChangeNestedIfsToEarlyReturnRector;
use Rector\EarlyReturn\Rector\If_\ChangeOrIfContinueToMultiContinueRector;
use Rector\EarlyReturn\Rector\If_\RemoveAlwaysElseRector;
use Rector\EarlyReturn\Rector\Return_\PreparedValueToEarlyReturnRector;
use Rector\EarlyReturn\Rector\Return_\ReturnBinaryOrToEarlyReturnRector;
use Rector\EarlyReturn\Rector\StmtsAwareInterface\ReturnEarlyIfVariableRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([ChangeNestedForeachIfsToEarlyContinueRector::class, ChangeIfElseValueAssignToEarlyReturnRector::class, ChangeNestedIfsToEarlyReturnRector::class, RemoveAlwaysElseRector::class, ChangeOrIfContinueToMultiContinueRector::class, PreparedValueToEarlyReturnRector::class, ReturnBinaryOrToEarlyReturnRector::class, ReturnEarlyIfVariableRector::class]);
};
File diff suppressed because one or more lines are too long
-16
View File
@@ -1,16 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\CodeQuality\Rector\FuncCall\InlineIsAInstanceOfRector;
use Rector\CodeQuality\Rector\Identical\FlipTypeControlToUseExclusiveTypeRector;
use Rector\Config\RectorConfig;
use Rector\DeadCode\Rector\If_\RemoveDeadInstanceOfRector;
use Rector\Instanceof_\Rector\Ternary\FlipNegatedTernaryInstanceofRector;
use Rector\TypeDeclaration\Rector\BooleanAnd\BinaryOpNullableToInstanceofRector;
use Rector\TypeDeclaration\Rector\Empty_\EmptyOnNullableObjectToInstanceOfRector;
use Rector\TypeDeclaration\Rector\While_\WhileNullableToInstanceofRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([EmptyOnNullableObjectToInstanceOfRector::class, InlineIsAInstanceOfRector::class, FlipTypeControlToUseExclusiveTypeRector::class, RemoveDeadInstanceOfRector::class, FlipNegatedTernaryInstanceofRector::class, BinaryOpNullableToInstanceofRector::class, WhileNullableToInstanceofRector::class]);
};
@@ -1,10 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\SetList;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->sets([SetList::PHP_53, SetList::PHP_52]);
};
@@ -1,11 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->sets([SetList::PHP_54, LevelSetList::UP_TO_PHP_53]);
};
@@ -1,11 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->sets([SetList::PHP_55, LevelSetList::UP_TO_PHP_54]);
};
@@ -1,11 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->sets([SetList::PHP_56, LevelSetList::UP_TO_PHP_55]);
};
@@ -1,11 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->sets([SetList::PHP_70, LevelSetList::UP_TO_PHP_56]);
};
@@ -1,11 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->sets([SetList::PHP_71, LevelSetList::UP_TO_PHP_70]);
};
@@ -1,11 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->sets([SetList::PHP_72, LevelSetList::UP_TO_PHP_71]);
};
@@ -1,11 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->sets([SetList::PHP_73, LevelSetList::UP_TO_PHP_72]);
};
@@ -1,11 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->sets([SetList::PHP_74, LevelSetList::UP_TO_PHP_73]);
};
@@ -1,11 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->sets([SetList::PHP_80, LevelSetList::UP_TO_PHP_74]);
};
@@ -1,11 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->sets([SetList::PHP_81, LevelSetList::UP_TO_PHP_80]);
};
@@ -1,11 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->sets([SetList::PHP_82, LevelSetList::UP_TO_PHP_81]);
};
@@ -1,11 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->sets([SetList::PHP_83, LevelSetList::UP_TO_PHP_82]);
};
@@ -1,11 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->sets([SetList::PHP_84, LevelSetList::UP_TO_PHP_83]);
};
@@ -1,11 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
use Rector\Set\ValueObject\SetList;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->sets([SetList::PHP_85, LevelSetList::UP_TO_PHP_84]);
};
-15
View File
@@ -1,15 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Naming\Rector\Assign\RenameVariableToMatchMethodCallReturnTypeRector;
use Rector\Naming\Rector\Class_\RenamePropertyToMatchTypeRector;
use Rector\Naming\Rector\ClassMethod\RenameParamToMatchTypeRector;
use Rector\Naming\Rector\ClassMethod\RenameVariableToMatchNewTypeRector;
use Rector\Naming\Rector\Foreach_\RenameForeachValueVariableToMatchExprVariableRector;
use Rector\Naming\Rector\Foreach_\RenameForeachValueVariableToMatchMethodCallReturnTypeRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([RenameParamToMatchTypeRector::class, RenamePropertyToMatchTypeRector::class, RenameVariableToMatchNewTypeRector::class, RenameVariableToMatchMethodCallReturnTypeRector::class, RenameForeachValueVariableToMatchMethodCallReturnTypeRector::class, RenameForeachValueVariableToMatchExprVariableRector::class]);
};
@@ -1,10 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\NetteUtils\Rector\StaticCall\UtilsJsonStaticCallNamedArgRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([UtilsJsonStaticCallNamedArgRector::class]);
};
-18
View File
@@ -1,18 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Php73\Rector\BooleanOr\IsCountableRector;
use Rector\Php73\Rector\FuncCall\ArrayKeyFirstLastRector;
use Rector\Php80\Rector\Identical\StrEndsWithRector;
use Rector\Php80\Rector\Identical\StrStartsWithRector;
use Rector\Php80\Rector\NotIdentical\StrContainsRector;
use Rector\Php80\Rector\Ternary\GetDebugTypeRector;
// @note longer rule registration must be used here, to separate from withRules() from root rector.php
// these rules can be used ahead of PHP version,
// as long composer.json includes particular symfony/php-polyfill package
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([ArrayKeyFirstLastRector::class, IsCountableRector::class, GetDebugTypeRector::class, StrStartsWithRector::class, StrEndsWithRector::class, StrContainsRector::class]);
};
-17
View File
@@ -1,17 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Php52\Rector\Property\VarToPublicPropertyRector;
use Rector\Php52\Rector\Switch_\ContinueToBreakInSwitchRector;
use Rector\Removing\Rector\FuncCall\RemoveFuncCallArgRector;
use Rector\Removing\ValueObject\RemoveFuncCallArg;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([VarToPublicPropertyRector::class, ContinueToBreakInSwitchRector::class]);
$rectorConfig->ruleWithConfiguration(RemoveFuncCallArgRector::class, [
// see https://www.php.net/manual/en/function.ldap-first-attribute.php
new RemoveFuncCallArg('ldap_first_attribute', 2),
]);
};
-12
View File
@@ -1,12 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Php53\Rector\FuncCall\DirNameFileConstantToDirConstantRector;
use Rector\Php53\Rector\Ternary\TernaryToElvisRector;
use Rector\Php53\Rector\Variable\ReplaceHttpServerVarsByServerRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([TernaryToElvisRector::class, DirNameFileConstantToDirConstantRector::class, ReplaceHttpServerVarsByServerRector::class]);
};
-14
View File
@@ -1,14 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Php54\Rector\Array_\LongArrayToShortArrayRector;
use Rector\Php54\Rector\Break_\RemoveZeroBreakContinueRector;
use Rector\Php54\Rector\FuncCall\RemoveReferenceFromCallRector;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([LongArrayToShortArrayRector::class, RemoveReferenceFromCallRector::class, RemoveZeroBreakContinueRector::class]);
$rectorConfig->ruleWithConfiguration(RenameFunctionRector::class, ['mysqli_param_count' => 'mysqli_stmt_param_count']);
};
-15
View File
@@ -1,15 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Php55\Rector\Class_\ClassConstantToSelfClassRector;
use Rector\Php55\Rector\ClassConstFetch\StaticToSelfOnFinalClassRector;
use Rector\Php55\Rector\FuncCall\GetCalledClassToSelfClassRector;
use Rector\Php55\Rector\FuncCall\GetCalledClassToStaticClassRector;
use Rector\Php55\Rector\FuncCall\PregReplaceEModifierRector;
use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([StringClassNameToClassConstantRector::class, ClassConstantToSelfClassRector::class, PregReplaceEModifierRector::class, GetCalledClassToSelfClassRector::class, GetCalledClassToStaticClassRector::class, StaticToSelfOnFinalClassRector::class]);
};
-12
View File
@@ -1,12 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Php56\Rector\FuncCall\PowToExpRector;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(PowToExpRector::class);
$rectorConfig->ruleWithConfiguration(RenameFunctionRector::class, ['mcrypt_generic_end' => 'mcrypt_generic_deinit', 'set_socket_blocking' => 'stream_set_blocking', 'ocibindbyname' => 'oci_bind_by_name', 'ocicancel' => 'oci_cancel', 'ocicolumnisnull' => 'oci_field_is_null', 'ocicolumnname' => 'oci_field_name', 'ocicolumnprecision' => 'oci_field_precision', 'ocicolumnscale' => 'oci_field_scale', 'ocicolumnsize' => 'oci_field_size', 'ocicolumntype' => 'oci_field_type', 'ocicolumntyperaw' => 'oci_field_type_raw', 'ocicommit' => 'oci_commit', 'ocidefinebyname' => 'oci_define_by_name', 'ocierror' => 'oci_error', 'ociexecute' => 'oci_execute', 'ocifetch' => 'oci_fetch', 'ocifetchstatement' => 'oci_fetch_all', 'ocifreecursor' => 'oci_free_statement', 'ocifreestatement' => 'oci_free_statement', 'ociinternaldebug' => 'oci_internal_debug', 'ocilogoff' => 'oci_close', 'ocilogon' => 'oci_connect', 'ocinewcollection' => 'oci_new_collection', 'ocinewcursor' => 'oci_new_cursor', 'ocinewdescriptor' => 'oci_new_descriptor', 'ocinlogon' => 'oci_new_connect', 'ocinumcols' => 'oci_num_fields', 'ociparse' => 'oci_parse', 'ociplogon' => 'oci_pconnect', 'ociresult' => 'oci_result', 'ocirollback' => 'oci_rollback', 'ocirowcount' => 'oci_num_rows', 'ociserverversion' => 'oci_server_version', 'ocisetprefetch' => 'oci_set_prefetch', 'ocistatementtype' => 'oci_statement_type']);
};
-49
View File
@@ -1,49 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Php70\Rector\Assign\ListSplitStringRector;
use Rector\Php70\Rector\Assign\ListSwapArrayOrderRector;
use Rector\Php70\Rector\Break_\BreakNotInLoopOrSwitchToReturnRector;
use Rector\Php70\Rector\ClassMethod\Php4ConstructorRector;
use Rector\Php70\Rector\FuncCall\CallUserMethodRector;
use Rector\Php70\Rector\FuncCall\EregToPregMatchRector;
use Rector\Php70\Rector\FuncCall\MultiDirnameRector;
use Rector\Php70\Rector\FuncCall\RandomFunctionRector;
use Rector\Php70\Rector\FuncCall\RenameMktimeWithoutArgsToTimeRector;
use Rector\Php70\Rector\FunctionLike\ExceptionHandlerTypehintRector;
use Rector\Php70\Rector\If_\IfToSpaceshipRector;
use Rector\Php70\Rector\List_\EmptyListRector;
use Rector\Php70\Rector\MethodCall\ThisCallOnStaticMethodToStaticCallRector;
use Rector\Php70\Rector\StaticCall\StaticCallOnNonStaticToInstanceCallRector;
use Rector\Php70\Rector\StmtsAwareInterface\IfIssetToCoalescingRector;
use Rector\Php70\Rector\Switch_\ReduceMultipleDefaultSwitchRector;
use Rector\Php70\Rector\Ternary\TernaryToNullCoalescingRector;
use Rector\Php70\Rector\Ternary\TernaryToSpaceshipRector;
use Rector\Php70\Rector\Variable\WrapVariableVariableNameInCurlyBracesRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([
Php4ConstructorRector::class,
TernaryToNullCoalescingRector::class,
RandomFunctionRector::class,
ExceptionHandlerTypehintRector::class,
MultiDirnameRector::class,
ListSplitStringRector::class,
EmptyListRector::class,
// be careful, run this just once, since it can keep swapping order back and forth
ListSwapArrayOrderRector::class,
CallUserMethodRector::class,
EregToPregMatchRector::class,
ReduceMultipleDefaultSwitchRector::class,
TernaryToSpaceshipRector::class,
WrapVariableVariableNameInCurlyBracesRector::class,
IfToSpaceshipRector::class,
StaticCallOnNonStaticToInstanceCallRector::class,
ThisCallOnStaticMethodToStaticCallRector::class,
BreakNotInLoopOrSwitchToReturnRector::class,
RenameMktimeWithoutArgsToTimeRector::class,
IfIssetToCoalescingRector::class,
]);
};
-15
View File
@@ -1,15 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Php71\Rector\Assign\AssignArrayToStringRector;
use Rector\Php71\Rector\BinaryOp\BinaryOpBetweenNumberAndStringRector;
use Rector\Php71\Rector\BooleanOr\IsIterableRector;
use Rector\Php71\Rector\FuncCall\RemoveExtraParametersRector;
use Rector\Php71\Rector\List_\ListToArrayDestructRector;
use Rector\Php71\Rector\TryCatch\MultiExceptionCatchRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([IsIterableRector::class, MultiExceptionCatchRector::class, AssignArrayToStringRector::class, RemoveExtraParametersRector::class, BinaryOpBetweenNumberAndStringRector::class, ListToArrayDestructRector::class]);
};
-30
View File
@@ -1,30 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Php72\Rector\Assign\ListEachRector;
use Rector\Php72\Rector\Assign\ReplaceEachAssignmentWithKeyCurrentRector;
use Rector\Php72\Rector\FuncCall\CreateFunctionToAnonymousFunctionRector;
use Rector\Php72\Rector\FuncCall\GetClassOnNullRector;
use Rector\Php72\Rector\FuncCall\ParseStrWithResultArgumentRector;
use Rector\Php72\Rector\FuncCall\StringifyDefineRector;
use Rector\Php72\Rector\FuncCall\StringsAssertNakedRector;
use Rector\Php72\Rector\Unset_\UnsetCastRector;
use Rector\Php72\Rector\While_\WhileEachToForeachRector;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->ruleWithConfiguration(RenameFunctionRector::class, [
# and imagewbmp
'jpeg2wbmp' => 'imagecreatefromjpeg',
# or imagewbmp
'png2wbmp' => 'imagecreatefrompng',
#migration72.deprecated.gmp_random-function
# http://php.net/manual/en/migration72.deprecated.php
# or gmp_random_range
'gmp_random' => 'gmp_random_bits',
'read_exif_data' => 'exif_read_data',
]);
$rectorConfig->rules([GetClassOnNullRector::class, ParseStrWithResultArgumentRector::class, StringsAssertNakedRector::class, CreateFunctionToAnonymousFunctionRector::class, StringifyDefineRector::class, WhileEachToForeachRector::class, ListEachRector::class, ReplaceEachAssignmentWithKeyCurrentRector::class, UnsetCastRector::class]);
};
-35
View File
@@ -1,35 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Php73\Rector\BooleanOr\IsCountableRector;
use Rector\Php73\Rector\ConstFetch\SensitiveConstantNameRector;
use Rector\Php73\Rector\FuncCall\ArrayKeyFirstLastRector;
use Rector\Php73\Rector\FuncCall\RegexDashEscapeRector;
use Rector\Php73\Rector\FuncCall\SensitiveDefineRector;
use Rector\Php73\Rector\FuncCall\SetCookieRector;
use Rector\Php73\Rector\FuncCall\StringifyStrNeedlesRector;
use Rector\Php73\Rector\String_\SensitiveHereNowDocRector;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->ruleWithConfiguration(RenameFunctionRector::class, [
# https://wiki.php.net/rfc/deprecations_php_7_3
'image2wbmp' => 'imagewbmp',
'mbregex_encoding' => 'mb_regex_encoding',
'mbereg' => 'mb_ereg',
'mberegi' => 'mb_eregi',
'mbereg_replace' => 'mb_ereg_replace',
'mberegi_replace' => 'mb_eregi_replace',
'mbsplit' => 'mb_split',
'mbereg_match' => 'mb_ereg_match',
'mbereg_search' => 'mb_ereg_search',
'mbereg_search_pos' => 'mb_ereg_search_pos',
'mbereg_search_regs' => 'mb_ereg_search_regs',
'mbereg_search_init' => 'mb_ereg_search_init',
'mbereg_search_getregs' => 'mb_ereg_search_getregs',
'mbereg_search_getpos' => 'mb_ereg_search_getpos',
]);
$rectorConfig->rules([StringifyStrNeedlesRector::class, RegexDashEscapeRector::class, SetCookieRector::class, IsCountableRector::class, ArrayKeyFirstLastRector::class, SensitiveDefineRector::class, SensitiveConstantNameRector::class, SensitiveHereNowDocRector::class]);
};
-31
View File
@@ -1,31 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use PhpParser\Node\Expr\Cast\Double;
use Rector\Config\RectorConfig;
use Rector\Php74\Rector\ArrayDimFetch\CurlyToSquareBracketArrayStringRector;
use Rector\Php74\Rector\Assign\NullCoalescingOperatorRector;
use Rector\Php74\Rector\Closure\ClosureToArrowFunctionRector;
use Rector\Php74\Rector\FuncCall\ArrayKeyExistsOnPropertyRector;
use Rector\Php74\Rector\FuncCall\FilterVarToAddSlashesRector;
use Rector\Php74\Rector\FuncCall\HebrevcToNl2brHebrevRector;
use Rector\Php74\Rector\FuncCall\MbStrrposEncodingArgumentPositionRector;
use Rector\Php74\Rector\FuncCall\MoneyFormatToNumberFormatRector;
use Rector\Php74\Rector\FuncCall\RestoreIncludePathToIniRestoreRector;
use Rector\Php74\Rector\Property\RestoreDefaultNullToNullableTypePropertyRector;
use Rector\Php74\Rector\StaticCall\ExportToReflectionFunctionRector;
use Rector\Php74\Rector\Ternary\ParenthesizeNestedTernaryRector;
use Rector\Renaming\Rector\Cast\RenameCastRector;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
use Rector\Renaming\ValueObject\RenameCast;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->ruleWithConfiguration(RenameFunctionRector::class, [
#the_real_type
# https://wiki.php.net/rfc/deprecations_php_7_4
'is_real' => 'is_float',
]);
$rectorConfig->rules([ArrayKeyExistsOnPropertyRector::class, FilterVarToAddSlashesRector::class, ExportToReflectionFunctionRector::class, MbStrrposEncodingArgumentPositionRector::class, NullCoalescingOperatorRector::class, ClosureToArrowFunctionRector::class, RestoreDefaultNullToNullableTypePropertyRector::class, CurlyToSquareBracketArrayStringRector::class, MoneyFormatToNumberFormatRector::class, ParenthesizeNestedTernaryRector::class, RestoreIncludePathToIniRestoreRector::class, HebrevcToNl2brHebrevRector::class]);
$rectorConfig->ruleWithConfiguration(RenameCastRector::class, [new RenameCast(Double::class, Double::KIND_REAL, Double::KIND_FLOAT)]);
};
-38
View File
@@ -1,38 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Arguments\Rector\ClassMethod\ArgumentAdderRector;
use Rector\Arguments\Rector\FuncCall\FunctionArgumentDefaultValueReplacerRector;
use Rector\Arguments\ValueObject\ArgumentAdder;
use Rector\Arguments\ValueObject\ReplaceFuncCallArgumentDefaultValue;
use Rector\CodeQuality\Rector\ClassMethod\OptionalParametersAfterRequiredRector;
use Rector\CodingStyle\Rector\FuncCall\ConsistentImplodeRector;
use Rector\Config\RectorConfig;
use Rector\DeadCode\Rector\StaticCall\RemoveParentCallWithoutParentRector;
use Rector\Php80\Rector\Catch_\RemoveUnusedVariableInCatchRector;
use Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector;
use Rector\Php80\Rector\Class_\StringableForToStringRector;
use Rector\Php80\Rector\ClassConstFetch\ClassOnThisVariableObjectRector;
use Rector\Php80\Rector\ClassMethod\AddParamBasedOnParentClassMethodRector;
use Rector\Php80\Rector\ClassMethod\FinalPrivateToPrivateVisibilityRector;
use Rector\Php80\Rector\ClassMethod\SetStateToStaticRector;
use Rector\Php80\Rector\FuncCall\ClassOnObjectRector;
use Rector\Php80\Rector\Identical\StrEndsWithRector;
use Rector\Php80\Rector\Identical\StrStartsWithRector;
use Rector\Php80\Rector\NotIdentical\StrContainsRector;
use Rector\Php80\Rector\Switch_\ChangeSwitchToMatchRector;
use Rector\Php80\Rector\Ternary\GetDebugTypeRector;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
use Rector\Transform\Rector\StaticCall\StaticCallToFuncCallRector;
use Rector\Transform\ValueObject\StaticCallToFuncCall;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([StrContainsRector::class, StrStartsWithRector::class, StrEndsWithRector::class, StringableForToStringRector::class, ClassOnObjectRector::class, GetDebugTypeRector::class, RemoveUnusedVariableInCatchRector::class, ClassPropertyAssignToConstructorPromotionRector::class, ChangeSwitchToMatchRector::class, RemoveParentCallWithoutParentRector::class, SetStateToStaticRector::class, FinalPrivateToPrivateVisibilityRector::class, AddParamBasedOnParentClassMethodRector::class, ClassOnThisVariableObjectRector::class, ConsistentImplodeRector::class, OptionalParametersAfterRequiredRector::class]);
$rectorConfig->ruleWithConfiguration(StaticCallToFuncCallRector::class, [new StaticCallToFuncCall('Nette\Utils\Strings', 'startsWith', 'str_starts_with'), new StaticCallToFuncCall('Nette\Utils\Strings', 'endsWith', 'str_ends_with'), new StaticCallToFuncCall('Nette\Utils\Strings', 'contains', 'str_contains')]);
// nette\utils and Strings::replace()
$rectorConfig->ruleWithConfiguration(ArgumentAdderRector::class, [new ArgumentAdder('Nette\Utils\Strings', 'replace', 2, 'replacement', '')]);
// @see https://php.watch/versions/8.0/pgsql-aliases-deprecated
$rectorConfig->ruleWithConfiguration(RenameFunctionRector::class, ['pg_clientencoding' => 'pg_client_encoding', 'pg_cmdtuples' => 'pg_affected_rows', 'pg_errormessage' => 'pg_last_error', 'pg_fieldisnull' => 'pg_field_is_null', 'pg_fieldname' => 'pg_field_name', 'pg_fieldnum' => 'pg_field_num', 'pg_fieldprtlen' => 'pg_field_prtlen', 'pg_fieldsize' => 'pg_field_size', 'pg_fieldtype' => 'pg_field_type', 'pg_freeresult' => 'pg_free_result', 'pg_getlastoid' => 'pg_last_oid', 'pg_loclose' => 'pg_lo_close', 'pg_locreate' => 'pg_lo_create', 'pg_loexport' => 'pg_lo_export', 'pg_loimport' => 'pg_lo_import', 'pg_loopen' => 'pg_lo_open', 'pg_loread' => 'pg_lo_read', 'pg_loreadall' => 'pg_lo_read_all', 'pg_lounlink' => 'pg_lo_unlink', 'pg_lowrite' => 'pg_lo_write', 'pg_numfields' => 'pg_num_fields', 'pg_numrows' => 'pg_num_rows', 'pg_result' => 'pg_fetch_result', 'pg_setclientencoding' => 'pg_set_client_encoding']);
$rectorConfig->ruleWithConfiguration(FunctionArgumentDefaultValueReplacerRector::class, [new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, 'gte', 'ge'), new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, 'lte', 'le'), new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, '', '!='), new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, '!', '!='), new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, 'g', 'gt'), new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, 'l', 'lt'), new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, 'n', 'ne'), new ReplaceFuncCallArgumentDefaultValue('get_headers', 1, 0, \false), new ReplaceFuncCallArgumentDefaultValue('get_headers', 1, 1, \true)]);
};
-42
View File
@@ -1,42 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\CodingStyle\Rector\FuncCall\ClosureFromCallableToFirstClassCallableRector;
use Rector\CodingStyle\Rector\FuncCall\FunctionFirstClassCallableRector;
use Rector\CodingStyle\Rector\FunctionLike\FunctionLikeToFirstClassCallableRector;
use Rector\Config\RectorConfig;
use Rector\Php81\Rector\Array_\FirstClassCallableRector;
use Rector\Php81\Rector\Class_\MyCLabsClassToEnumRector;
use Rector\Php81\Rector\Class_\SpatieEnumClassToEnumRector;
use Rector\Php81\Rector\ClassMethod\NewInInitializerRector;
use Rector\Php81\Rector\FuncCall\NullToStrictIntPregSlitFuncCallLimitArgRector;
use Rector\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector;
use Rector\Php81\Rector\MethodCall\MyCLabsMethodCallToEnumConstRector;
use Rector\Php81\Rector\MethodCall\RemoveReflectionSetAccessibleCallsRector;
use Rector\Php81\Rector\MethodCall\SpatieEnumMethodCallToEnumConstRector;
use Rector\Php81\Rector\New_\MyCLabsConstructorCallToEnumFromRector;
use Rector\Php81\Rector\Property\ReadOnlyPropertyRector;
use Rector\TypeDeclaration\Rector\ClassMethod\ReturnNeverTypeRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([
ReturnNeverTypeRector::class,
MyCLabsClassToEnumRector::class,
MyCLabsMethodCallToEnumConstRector::class,
MyCLabsConstructorCallToEnumFromRector::class,
ReadOnlyPropertyRector::class,
SpatieEnumClassToEnumRector::class,
SpatieEnumMethodCallToEnumConstRector::class,
NullToStrictStringFuncCallArgRector::class,
NullToStrictIntPregSlitFuncCallLimitArgRector::class,
// array of local method call
FirstClassCallableRector::class,
// closure/arrow function
FunctionLikeToFirstClassCallableRector::class,
ClosureFromCallableToFirstClassCallableRector::class,
FunctionFirstClassCallableRector::class,
RemoveReflectionSetAccessibleCallsRector::class,
NewInInitializerRector::class,
]);
};
-13
View File
@@ -1,13 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Php82\Rector\Class_\ReadOnlyClassRector;
use Rector\Php82\Rector\Encapsed\VariableInStringInterpolationFixerRector;
use Rector\Php82\Rector\FuncCall\Utf8DecodeEncodeToMbConvertEncodingRector;
use Rector\Php82\Rector\New_\FilesystemIteratorSkipDotsRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([ReadOnlyClassRector::class, Utf8DecodeEncodeToMbConvertEncodingRector::class, FilesystemIteratorSkipDotsRector::class, VariableInStringInterpolationFixerRector::class]);
};
-16
View File
@@ -1,16 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Php83\Rector\BooleanAnd\JsonValidateRector;
use Rector\Php83\Rector\Class_\ReadOnlyAnonymousClassRector;
use Rector\Php83\Rector\ClassConst\AddTypeToConstRector;
use Rector\Php83\Rector\ClassMethod\AddOverrideAttributeToOverriddenMethodsRector;
use Rector\Php83\Rector\FuncCall\CombineHostPortLdapUriRector;
use Rector\Php83\Rector\FuncCall\DynamicClassConstFetchRector;
use Rector\Php83\Rector\FuncCall\RemoveGetClassGetParentClassNoArgsRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([AddOverrideAttributeToOverriddenMethodsRector::class, AddTypeToConstRector::class, CombineHostPortLdapUriRector::class, RemoveGetClassGetParentClassNoArgsRector::class, ReadOnlyAnonymousClassRector::class, DynamicClassConstFetchRector::class, JsonValidateRector::class]);
};
-18
View File
@@ -1,18 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Php84\Rector\Class_\DeprecatedAnnotationToDeprecatedAttributeRector;
use Rector\Php84\Rector\Foreach_\ForeachToArrayAllRector;
use Rector\Php84\Rector\Foreach_\ForeachToArrayAnyRector;
use Rector\Php84\Rector\Foreach_\ForeachToArrayFindKeyRector;
use Rector\Php84\Rector\Foreach_\ForeachToArrayFindRector;
use Rector\Php84\Rector\FuncCall\AddEscapeArgumentRector;
use Rector\Php84\Rector\FuncCall\RoundingModeEnumRector;
use Rector\Php84\Rector\MethodCall\NewMethodCallWithoutParenthesesRector;
use Rector\Php84\Rector\Param\ExplicitNullableParamTypeRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([ExplicitNullableParamTypeRector::class, RoundingModeEnumRector::class, AddEscapeArgumentRector::class, NewMethodCallWithoutParenthesesRector::class, DeprecatedAnnotationToDeprecatedAttributeRector::class, ForeachToArrayFindRector::class, ForeachToArrayFindKeyRector::class, ForeachToArrayAllRector::class, ForeachToArrayAnyRector::class]);
};
-75
View File
@@ -1,75 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use PhpParser\Node\Expr\Cast\Bool_;
use PhpParser\Node\Expr\Cast\Double;
use PhpParser\Node\Expr\Cast\Int_;
use PhpParser\Node\Expr\Cast\String_;
use Rector\Config\RectorConfig;
use Rector\Php85\Rector\ArrayDimFetch\ArrayFirstLastRector;
use Rector\Php85\Rector\Class_\SleepToSerializeRector;
use Rector\Php85\Rector\Class_\WakeupToUnserializeRector;
use Rector\Php85\Rector\ClassMethod\NullDebugInfoReturnRector;
use Rector\Php85\Rector\Const_\DeprecatedAnnotationToDeprecatedAttributeRector;
use Rector\Php85\Rector\FuncCall\ArrayKeyExistsNullToEmptyStringRector;
use Rector\Php85\Rector\FuncCall\ChrArgModuloRector;
use Rector\Php85\Rector\FuncCall\OrdSingleByteRector;
use Rector\Php85\Rector\FuncCall\RemoveFinfoBufferContextArgRector;
use Rector\Php85\Rector\ShellExec\ShellExecFunctionCallOverBackticksRector;
use Rector\Php85\Rector\Switch_\ColonAfterSwitchCaseRector;
use Rector\Removing\Rector\FuncCall\RemoveFuncCallArgRector;
use Rector\Removing\Rector\FuncCall\RemoveFuncCallRector;
use Rector\Removing\ValueObject\RemoveFuncCallArg;
use Rector\Renaming\Rector\Cast\RenameCastRector;
use Rector\Renaming\Rector\ClassConstFetch\RenameClassConstFetchRector;
use Rector\Renaming\Rector\ConstFetch\RenameConstantRector;
use Rector\Renaming\Rector\FuncCall\RenameFunctionRector;
use Rector\Renaming\Rector\MethodCall\RenameMethodRector;
use Rector\Renaming\ValueObject\MethodCallRename;
use Rector\Renaming\ValueObject\RenameCast;
use Rector\Renaming\ValueObject\RenameClassAndConstFetch;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([ArrayFirstLastRector::class, RemoveFinfoBufferContextArgRector::class, NullDebugInfoReturnRector::class, DeprecatedAnnotationToDeprecatedAttributeRector::class, ColonAfterSwitchCaseRector::class, ArrayKeyExistsNullToEmptyStringRector::class, ChrArgModuloRector::class, SleepToSerializeRector::class, OrdSingleByteRector::class, WakeupToUnserializeRector::class, ShellExecFunctionCallOverBackticksRector::class]);
$rectorConfig->ruleWithConfiguration(RemoveFuncCallArgRector::class, [
// https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_key_length_parameter_of_openssl_pkey_derive
new RemoveFuncCallArg('openssl_pkey_derive', 2),
// https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_the_exclude_disabled_parameter_of_get_defined_functions
new RemoveFuncCallArg('get_defined_functions', 0),
]);
$rectorConfig->ruleWithConfiguration(RenameMethodRector::class, [
// https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_splobjectstoragecontains_splobjectstorageattach_and_splobjectstoragedetach
new MethodCallRename('SplObjectStorage', 'contains', 'offsetExists'),
new MethodCallRename('SplObjectStorage', 'attach', 'offsetSet'),
new MethodCallRename('SplObjectStorage', 'detach', 'offsetUnset'),
// https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_driver_specific_pdo_constants_and_methods
new MethodCallRename('PDO', 'pgsqlCopyFromArray', 'copyFromArray'),
new MethodCallRename('PDO', 'pgsqlCopyFromFile', 'copyFromFile'),
new MethodCallRename('PDO', 'pgsqlCopyToArray', 'copyToArray'),
new MethodCallRename('PDO', 'pgsqlCopyToFile', 'copyToFile'),
new MethodCallRename('PDO', 'pgsqlGetNotify', 'getNotify'),
new MethodCallRename('PDO', 'pgsqlGetPid', 'getPid'),
new MethodCallRename('PDO', 'pgsqlLOBCreate', 'lobCreate'),
new MethodCallRename('PDO', 'pgsqlLOBOpen', 'lobOpen'),
new MethodCallRename('PDO', 'pgsqlLOBUnlink', 'lobUnlink'),
new MethodCallRename('PDO', 'sqliteCreateAggregate', 'createAggregate'),
new MethodCallRename('PDO', 'sqliteCreateCollation', 'createCollation'),
new MethodCallRename('PDO', 'sqliteCreateFunction', 'createFunction'),
]);
$rectorConfig->ruleWithConfiguration(RenameFunctionRector::class, [
// https://wiki.php.net/rfc/deprecations_php_8_5#formally_deprecate_socket_set_timeout
'socket_set_timeout' => 'stream_set_timeout',
// https://wiki.php.net/rfc/deprecations_php_8_5#formally_deprecate_mysqli_execute
'mysqli_execute' => 'mysqli_stmt_execute',
]);
// https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_driver_specific_pdo_constants_and_methods
$rectorConfig->ruleWithConfiguration(RenameClassConstFetchRector::class, [new RenameClassAndConstFetch('PDO', 'DBLIB_ATTR_CONNECTION_TIMEOUT', 'Pdo\Dblib', 'ATTR_CONNECTION_TIMEOUT'), new RenameClassAndConstFetch('PDO', 'DBLIB_ATTR_QUERY_TIMEOUT', 'Pdo\Dblib', 'ATTR_QUERY_TIMEOUT'), new RenameClassAndConstFetch('PDO', 'DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER', 'Pdo\Dblib', 'ATTR_STRINGIFY_UNIQUEIDENTIFIER'), new RenameClassAndConstFetch('PDO', 'DBLIB_ATTR_VERSION', 'Pdo\Dblib', 'ATTR_VERSION'), new RenameClassAndConstFetch('PDO', 'DBLIB_ATTR_TDS_VERSION', 'Pdo\Dblib', 'ATTR_TDS_VERSION'), new RenameClassAndConstFetch('PDO', 'DBLIB_ATTR_SKIP_EMPTY_ROWSETS', 'Pdo\Dblib', 'ATTR_SKIP_EMPTY_ROWSETS'), new RenameClassAndConstFetch('PDO', 'DBLIB_ATTR_DATETIME_CONVERT', 'Pdo\Dblib', 'ATTR_DATETIME_CONVERT'), new RenameClassAndConstFetch('PDO', 'FB_ATTR_DATE_FORMAT', 'Pdo\Firebird', 'ATTR_DATE_FORMAT'), new RenameClassAndConstFetch('PDO', 'FB_ATTR_TIME_FORMAT', 'Pdo\Firebird', 'ATTR_TIME_FORMAT'), new RenameClassAndConstFetch('PDO', 'FB_ATTR_TIMESTAMP_FORMAT', 'Pdo\Firebird', 'ATTR_TIMESTAMP_FORMAT'), new RenameClassAndConstFetch('PDO', 'MYSQL_ATTR_USE_BUFFERED_QUERY', 'Pdo\Mysql', 'ATTR_USE_BUFFERED_QUERY'), new RenameClassAndConstFetch('PDO', 'MYSQL_ATTR_LOCAL_INFILE', 'Pdo\Mysql', 'ATTR_LOCAL_INFILE'), new RenameClassAndConstFetch('PDO', 'MYSQL_ATTR_LOCAL_INFILE_DIRECTORY', 'Pdo\Mysql', 'ATTR_LOCAL_INFILE_DIRECTORY'), new RenameClassAndConstFetch('PDO', 'MYSQL_ATTR_INIT_COMMAND', 'Pdo\Mysql', 'ATTR_INIT_COMMAND'), new RenameClassAndConstFetch('PDO', 'MYSQL_ATTR_MAX_BUFFER_SIZE', 'Pdo\Mysql', 'ATTR_MAX_BUFFER_SIZE'), new RenameClassAndConstFetch('PDO', 'MYSQL_ATTR_READ_DEFAULT_FILE', 'Pdo\Mysql', 'ATTR_READ_DEFAULT_FILE'), new RenameClassAndConstFetch('PDO', 'MYSQL_ATTR_READ_DEFAULT_GROUP', 'Pdo\Mysql', 'ATTR_READ_DEFAULT_GROUP'), new RenameClassAndConstFetch('PDO', 'MYSQL_ATTR_COMPRESS', 'Pdo\Mysql', 'ATTR_COMPRESS'), new RenameClassAndConstFetch('PDO', 'MYSQL_ATTR_DIRECT_QUERY', 'Pdo\Mysql', 'ATTR_DIRECT_QUERY'), new RenameClassAndConstFetch('PDO', 'MYSQL_ATTR_FOUND_ROWS', 'Pdo\Mysql', 'ATTR_FOUND_ROWS'), new RenameClassAndConstFetch('PDO', 'MYSQL_ATTR_IGNORE_SPACE', 'Pdo\Mysql', 'ATTR_IGNORE_SPACE'), new RenameClassAndConstFetch('PDO', 'MYSQL_ATTR_SSL_KEY', 'Pdo\Mysql', 'ATTR_SSL_KEY'), new RenameClassAndConstFetch('PDO', 'MYSQL_ATTR_SSL_CERT', 'Pdo\Mysql', 'ATTR_SSL_CERT'), new RenameClassAndConstFetch('PDO', 'MYSQL_ATTR_SSL_CA', 'Pdo\Mysql', 'ATTR_SSL_CA'), new RenameClassAndConstFetch('PDO', 'MYSQL_ATTR_SSL_CAPATH', 'Pdo\Mysql', 'ATTR_SSL_CAPATH'), new RenameClassAndConstFetch('PDO', 'MYSQL_ATTR_SSL_CIPHER', 'Pdo\Mysql', 'ATTR_SSL_CIPHER'), new RenameClassAndConstFetch('PDO', 'MYSQL_ATTR_SSL_VERIFY_SERVER_CERT', 'Pdo\Mysql', 'ATTR_SSL_VERIFY_SERVER_CERT'), new RenameClassAndConstFetch('PDO', 'MYSQL_ATTR_SERVER_PUBLIC_KEY', 'Pdo\Mysql', 'ATTR_SERVER_PUBLIC_KEY'), new RenameClassAndConstFetch('PDO', 'MYSQL_ATTR_MULTI_STATEMENTS', 'Pdo\Mysql', 'ATTR_MULTI_STATEMENTS'), new RenameClassAndConstFetch('PDO', 'ODBC_ATTR_USE_CURSOR_LIBRARY', 'Pdo\Odbc', 'ATTR_USE_CURSOR_LIBRARY'), new RenameClassAndConstFetch('PDO', 'ODBC_ATTR_ASSUME_UTF8', 'Pdo\Odbc', 'ATTR_ASSUME_UTF8'), new RenameClassAndConstFetch('PDO', 'ODBC_SQL_USE_IF_NEEDED', 'Pdo\Odbc', 'SQL_USE_IF_NEEDED'), new RenameClassAndConstFetch('PDO', 'ODBC_SQL_USE_DRIVER', 'Pdo\Odbc', 'SQL_USE_DRIVER'), new RenameClassAndConstFetch('PDO', 'ODBC_SQL_USE_ODBC', 'Pdo\Odbc', 'SQL_USE_ODBC'), new RenameClassAndConstFetch('PDO', 'PGSQL_ATTR_DISABLE_PREPARES', 'Pdo\Pgsql', 'ATTR_DISABLE_PREPARES'), new RenameClassAndConstFetch('PDO', 'SQLITE_ATTR_EXTENDED_RESULT_CODES', 'Pdo\Sqlite', 'ATTR_EXTENDED_RESULT_CODES'), new RenameClassAndConstFetch('PDO', 'SQLITE_ATTR_OPEN_FLAGS', 'Pdo\Sqlite', 'OPEN_FLAGS'), new RenameClassAndConstFetch('PDO', 'SQLITE_ATTR_READONLY_STATEMENT', 'Pdo\Sqlite', 'ATTR_READONLY_STATEMENT'), new RenameClassAndConstFetch('PDO', 'SQLITE_DETERMINISTIC', 'Pdo\Sqlite', 'DETERMINISTIC'), new RenameClassAndConstFetch('PDO', 'SQLITE_OPEN_READONLY', 'Pdo\Sqlite', 'OPEN_READONLY'), new RenameClassAndConstFetch('PDO', 'SQLITE_OPEN_READWRITE', 'Pdo\Sqlite', 'OPEN_READWRITE'), new RenameClassAndConstFetch('PDO', 'SQLITE_OPEN_CREATE', 'Pdo\Sqlite', 'OPEN_CREATE')]);
// https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_non-standard_cast_names
$rectorConfig->ruleWithConfiguration(RenameCastRector::class, [new RenameCast(Int_::class, Int_::KIND_INTEGER, Int_::KIND_INT), new RenameCast(Bool_::class, Bool_::KIND_BOOLEAN, Bool_::KIND_BOOL), new RenameCast(Double::class, Double::KIND_DOUBLE, Double::KIND_FLOAT), new RenameCast(String_::class, String_::KIND_BINARY, String_::KIND_STRING)]);
// https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_no-op_functions_from_the_resource_to_object_conversion
// these function have no effect when use
$rectorConfig->ruleWithConfiguration(RemoveFuncCallRector::class, ['curl_close', 'curl_share_close', 'finfo_close', 'imagedestroy', 'xml_parser_free']);
// https://wiki.php.net/rfc/deprecations_php_8_5#deprecate_filter_default_constant
$rectorConfig->ruleWithConfiguration(RenameConstantRector::class, ['FILTER_DEFAULT' => 'FILTER_UNSAFE_RAW']);
};
-12
View File
@@ -1,12 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Privatization\Rector\ClassMethod\PrivatizeFinalClassMethodRector;
use Rector\Privatization\Rector\MethodCall\PrivatizeLocalGetterToPropertyRector;
use Rector\Privatization\Rector\Property\PrivatizeFinalClassPropertyRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([PrivatizeLocalGetterToPropertyRector::class, PrivatizeFinalClassPropertyRector::class, PrivatizeFinalClassMethodRector::class]);
};
-12
View File
@@ -1,12 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\CodingStyle\Rector\PostInc\PostIncDecToPreIncDecRector;
use Rector\Config\RectorConfig;
use Rector\Privatization\Rector\Class_\FinalizeTestCaseClassRector;
use Rector\TypeDeclaration\Rector\StmtsAwareInterface\DeclareStrictTypesRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([DeclareStrictTypesRector::class, PostIncDecToPreIncDecRector::class, FinalizeTestCaseClassRector::class]);
};
-10
View File
@@ -1,10 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\RectorConfig;
use Rector\Strict\Rector\Empty_\DisallowedEmptyRuleFixerRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules([DisallowedEmptyRuleFixerRector::class]);
};
@@ -1,13 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\Level\TypeDeclarationDocblocksLevel;
use Rector\Config\RectorConfig;
/**
* @experimental * 2025-09, experimental hidden set for type declaration in docblocks
*/
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rules(TypeDeclarationDocblocksLevel::RULES);
};
@@ -1,12 +0,0 @@
<?php
declare (strict_types=1);
namespace RectorPrefix202510;
use Rector\Config\Level\TypeDeclarationLevel;
use Rector\Config\RectorConfig;
return static function (RectorConfig $rectorConfig): void {
// the rule order matters, as its used in withTypeCoverageLevel() method
// place the safest rules first, follow by more complex ones
$rectorConfig->rules(TypeDeclarationLevel::RULES);
};
-380
View File
@@ -1,380 +0,0 @@
<?php
declare(strict_types=1);
use PhpParser\Node;
use PHPStan\Testing\PHPStanTestCase;
if (defined('__PHPSTAN_RUNNING__')) {
return;
}
// edge case during Rector tests case, happens when
// 1. phpstan autoload test case is triggered first,
// 2. all php-parser classes are loaded,
if (defined('PHPUNIT_COMPOSER_INSTALL') && isPHPStanTestPreloaded()) {
return;
}
function isPHPStanTestPreloaded(): bool
{
if (! class_exists(PHPStanTestCase::class, false)) {
return false;
}
return interface_exists(Node::class, false);
}
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node.php';
require_once __DIR__ . '/src/Contract/PhpParser/Node/StmtsAwareInterface.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeAbstract.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeVisitorAbstract.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Comment.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinterAbstract.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Parser.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/ParserAbstract.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/FunctionLike.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Builder.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/ComplexType.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/CallLike.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Name.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeTraverserInterface.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Builder/Declaration.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Builder/FunctionLike.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Builder/ClassConst.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Builder/Class_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Builder/EnumCase.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Builder/Enum_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Builder/Function_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Builder/Interface_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Builder/Method.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Builder/Namespace_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Builder/Param.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Builder/Property.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Builder/TraitUse.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Builder/Trait_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Builder/Use_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/BuilderFactory.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/BuilderHelpers.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Comment/Doc.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/ConstExprEvaluationException.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/ConstExprEvaluator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Error.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Collecting.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/ErrorHandler/Throwing.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Internal/DiffElem.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Internal/Differ.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Internal/TokenPolyfill.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Internal/TokenStream.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/JsonDecoder.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/Emulative.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AsymmetricVisibilityTokenEmulator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/EnumTokenEmulator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/PipeOperatorEmulator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/PropertyTokenEmulator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyFunctionTokenEmulator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyTokenEmulator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Lexer/TokenEmulator/VoidCastEmulator.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Modifiers.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NameContext.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Arg.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/ArrayItem.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Attribute.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/AttributeGroup.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/ClosureUse.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Const_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/DeclareItem.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Array_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Assign.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/AssignRef.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pipe.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Cast/Void_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Clone_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Closure.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Empty_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Error.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Eval_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Exit_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/FuncCall.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Include_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Isset_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/List_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Match_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/MethodCall.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/New_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostDec.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PostInc.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreDec.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PreInc.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Print_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/ShellExec.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticCall.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Ternary.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Throw_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Variable.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Expr/Yield_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Identifier.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/InterpolatedStringPart.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/IntersectionType.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/MatchArm.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Name/FullyQualified.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Name/Relative.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/NullableType.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Param.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/PropertyHook.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/PropertyItem.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/DNumber.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Float_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/Int_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/InterpolatedString.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Property.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Scalar/String_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/StaticVar.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Block.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Break_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Case_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Catch_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Class_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Const_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Continue_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Declare_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Do_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Echo_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Else_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/EnumCase.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Enum_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Expression.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Finally_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/For_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Function_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Global_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Goto_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/If_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Interface_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Label.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Nop.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Property.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Return_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Static_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Switch_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Trait_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Unset_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/UseUse.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/Use_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/Stmt/While_.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/UnionType.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/UseItem.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Node/VariadicPlaceholder.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeDumper.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeFinder.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeTraverser.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/CommentAnnotatingVisitor.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Parser/Php7.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Parser/Php8.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/ParserFactory.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/PhpVersion.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/PrettyPrinter/Standard.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/Token.php';
require_once __DIR__ . '/vendor/nikic/php-parser/lib/PhpParser/compatibility_tokens.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Node.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Lexer/Lexer.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Comment.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/NodeAttributes.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/AbstractNodeVisitor.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Attribute.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/ConstExpr/DoctrineConstExprStringNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/NodeTraverser.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/NodeVisitor/CloningVisitor.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagMethodValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagPropertyValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/AssertTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineAnnotation.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArgument.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArray.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineArrayItem.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/Doctrine/DoctrineTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamClosureThisTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamImmediatelyInvokedCallableTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamLaterInvokedCallableTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamOutTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/PureUnlessCallableIsImpureTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireExtendsTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/RequireImplementsTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/SealedTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/SelfOutTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypelessParamTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeUnsealedTypeNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeForParameterNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Type/ConditionalTypeNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Type/InvalidTypeNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeItemNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Type/ObjectShapeNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Type/OffsetAccessTypeNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Parser/ParserException.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Parser/StringUnescaper.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Parser/TokenIterator.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Parser/TypeParser.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/ParserConfig.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Printer/DiffElem.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Printer/Differ.php';
require_once __DIR__ . '/vendor/phpstan/phpdoc-parser/src/Printer/Printer.php';
@@ -1,171 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Arguments;
use PhpParser\BuilderHelpers;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\Arguments\Contract\ReplaceArgumentDefaultValueInterface;
use Rector\Arguments\ValueObject\ReplaceArgumentDefaultValue;
use Rector\PhpParser\Node\NodeFactory;
use Rector\PhpParser\Node\Value\ValueResolver;
final class ArgumentDefaultValueReplacer
{
/**
* @readonly
*/
private NodeFactory $nodeFactory;
/**
* @readonly
*/
private ValueResolver $valueResolver;
public function __construct(NodeFactory $nodeFactory, ValueResolver $valueResolver)
{
$this->nodeFactory = $nodeFactory;
$this->valueResolver = $valueResolver;
}
/**
* @template TCall as (MethodCall|StaticCall|ClassMethod|FuncCall|New_)
*
* @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\New_ $node
* @return TCall|null
*/
public function processReplaces($node, ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue)
{
if ($node instanceof ClassMethod) {
if (!isset($node->params[$replaceArgumentDefaultValue->getPosition()])) {
return null;
}
return $this->processParams($node, $replaceArgumentDefaultValue);
}
if (!isset($node->args[$replaceArgumentDefaultValue->getPosition()])) {
return null;
}
return $this->processArgs($node, $replaceArgumentDefaultValue);
}
/**
* @param mixed $value
*/
private function isDefaultValueMatched(?Expr $expr, $value): bool
{
// allow any values before, also allow param without default value
if ($value === ReplaceArgumentDefaultValue::ANY_VALUE_BEFORE) {
return \true;
}
if (!$expr instanceof Expr) {
return \false;
}
if ($this->valueResolver->isValue($expr, $value)) {
return \true;
}
// ValueResolver::isValue returns false when default value is `null`
return $value === null && $this->valueResolver->isNull($expr);
}
private function processParams(ClassMethod $classMethod, ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue): ?ClassMethod
{
$position = $replaceArgumentDefaultValue->getPosition();
if (!$this->isDefaultValueMatched($classMethod->params[$position]->default, $replaceArgumentDefaultValue->getValueBefore())) {
return null;
}
$classMethod->params[$position]->default = $this->normalizeValue($replaceArgumentDefaultValue->getValueAfter());
return $classMethod;
}
/**
* @template TCall as (MethodCall|StaticCall|FuncCall|New_)
*
* @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Expr\FuncCall|\PhpParser\Node\Expr\New_ $expr
* @return TCall|null
*/
private function processArgs($expr, ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue): ?Expr
{
if ($expr->isFirstClassCallable()) {
return null;
}
$position = $replaceArgumentDefaultValue->getPosition();
$particularArg = $expr->getArgs()[$position] ?? null;
if (!$particularArg instanceof Arg) {
return null;
}
$argValue = $this->valueResolver->getValue($particularArg->value);
if (is_scalar($replaceArgumentDefaultValue->getValueBefore()) && $argValue === $replaceArgumentDefaultValue->getValueBefore()) {
$expr->args[$position] = $this->normalizeValueToArgument($replaceArgumentDefaultValue->getValueAfter());
return $expr;
}
if (is_array($replaceArgumentDefaultValue->getValueBefore())) {
$newArgs = $this->processArrayReplacement($expr->getArgs(), $replaceArgumentDefaultValue);
if (is_array($newArgs)) {
$expr->args = $newArgs;
return $expr;
}
}
return null;
}
/**
* @param mixed $value
*/
private function normalizeValueToArgument($value): Arg
{
return new Arg($this->normalizeValue($value));
}
/**
* @return \PhpParser\Node\Expr\ClassConstFetch|\PhpParser\Node\Expr
* @param mixed $value
*/
private function normalizeValue($value)
{
// class constants → turn string to composite
if (is_string($value) && strpos($value, '::') !== \false) {
[$class, $constant] = explode('::', $value);
return $this->nodeFactory->createClassConstFetch($class, $constant);
}
return BuilderHelpers::normalizeValue($value);
}
/**
* @param array<int, Arg> $args
* @return array<int, Arg>|null
*/
private function processArrayReplacement(array $args, ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue): ?array
{
$argumentValues = $this->resolveArgumentValuesToBeforeRecipe($args, $replaceArgumentDefaultValue);
if ($argumentValues !== $replaceArgumentDefaultValue->getValueBefore()) {
return null;
}
if (is_string($replaceArgumentDefaultValue->getValueAfter())) {
$args[$replaceArgumentDefaultValue->getPosition()] = $this->normalizeValueToArgument($replaceArgumentDefaultValue->getValueAfter());
// clear following arguments
$argumentCountToClear = count($replaceArgumentDefaultValue->getValueBefore());
for ($i = $replaceArgumentDefaultValue->getPosition() + 1; $i <= $replaceArgumentDefaultValue->getPosition() + $argumentCountToClear; ++$i) {
unset($args[$i]);
}
}
return $args;
}
/**
* @param Arg[] $argumentNodes
* @return mixed[]
*/
private function resolveArgumentValuesToBeforeRecipe(array $argumentNodes, ReplaceArgumentDefaultValueInterface $replaceArgumentDefaultValue): array
{
$argumentValues = [];
$valueBefore = $replaceArgumentDefaultValue->getValueBefore();
if (!is_array($valueBefore)) {
return [];
}
$beforeArgumentCount = count($valueBefore);
for ($i = 0; $i < $beforeArgumentCount; ++$i) {
if (!isset($argumentNodes[$replaceArgumentDefaultValue->getPosition() + $i])) {
continue;
}
$nextArg = $argumentNodes[$replaceArgumentDefaultValue->getPosition() + $i];
$argumentValues[] = $this->valueResolver->getValue($nextArg->value);
}
return $argumentValues;
}
}
@@ -1,17 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Arguments\Contract;
interface ReplaceArgumentDefaultValueInterface
{
public function getPosition(): int;
/**
* @return mixed
*/
public function getValueBefore();
/**
* @return mixed
*/
public function getValueAfter();
}
@@ -1,60 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Arguments\NodeAnalyzer;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Name;
use Rector\Arguments\ValueObject\ArgumentAdder;
use Rector\Arguments\ValueObject\ArgumentAdderWithoutDefaultValue;
use Rector\Enum\ObjectReference;
use Rector\NodeNameResolver\NodeNameResolver;
final class ArgumentAddingScope
{
/**
* @readonly
*/
private NodeNameResolver $nodeNameResolver;
/**
* @api
* @var string
*/
public const SCOPE_PARENT_CALL = 'parent_call';
/**
* @api
* @var string
*/
public const SCOPE_METHOD_CALL = 'method_call';
/**
* @api
* @var string
*/
public const SCOPE_CLASS_METHOD = 'class_method';
public function __construct(NodeNameResolver $nodeNameResolver)
{
$this->nodeNameResolver = $nodeNameResolver;
}
/**
* @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $expr
* @param \Rector\Arguments\ValueObject\ArgumentAdder|\Rector\Arguments\ValueObject\ArgumentAdderWithoutDefaultValue $argumentAdder
*/
public function isInCorrectScope($expr, $argumentAdder): bool
{
if ($argumentAdder->getScope() === null) {
return \true;
}
$scope = $argumentAdder->getScope();
if ($expr instanceof StaticCall) {
if (!$expr->class instanceof Name) {
return \false;
}
if ($this->nodeNameResolver->isName($expr->class, ObjectReference::PARENT)) {
return $scope === self::SCOPE_PARENT_CALL;
}
return $scope === self::SCOPE_METHOD_CALL;
}
// MethodCall
return $scope === self::SCOPE_METHOD_CALL;
}
}
@@ -1,54 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Arguments\NodeAnalyzer;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Param;
use PHPStan\Type\Type;
use Rector\NodeTypeResolver\TypeComparator\TypeComparator;
use Rector\PhpParser\Node\Value\ValueResolver;
use Rector\StaticTypeMapper\StaticTypeMapper;
final class ChangedArgumentsDetector
{
/**
* @readonly
*/
private ValueResolver $valueResolver;
/**
* @readonly
*/
private StaticTypeMapper $staticTypeMapper;
/**
* @readonly
*/
private TypeComparator $typeComparator;
public function __construct(ValueResolver $valueResolver, StaticTypeMapper $staticTypeMapper, TypeComparator $typeComparator)
{
$this->valueResolver = $valueResolver;
$this->staticTypeMapper = $staticTypeMapper;
$this->typeComparator = $typeComparator;
}
/**
* @param mixed $value
*/
public function isDefaultValueChanged(Param $param, $value): bool
{
if (!$param->default instanceof Expr) {
return \false;
}
return !$this->valueResolver->isValue($param->default, $value);
}
public function isTypeChanged(Param $param, ?Type $newType): bool
{
if (!$param->type instanceof Node) {
return \false;
}
if (!$newType instanceof Type) {
return \true;
}
$currentParamType = $this->staticTypeMapper->mapPhpParserNodePHPStanType($param->type);
return !$this->typeComparator->areTypesEqual($currentParamType, $newType);
}
}
@@ -1,328 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Arguments\Rector\ClassMethod;
use PhpParser\BuilderHelpers;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Name;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use Rector\Arguments\NodeAnalyzer\ArgumentAddingScope;
use Rector\Arguments\NodeAnalyzer\ChangedArgumentsDetector;
use Rector\Arguments\ValueObject\ArgumentAdder;
use Rector\Arguments\ValueObject\ArgumentAdderWithoutDefaultValue;
use Rector\Contract\Rector\ConfigurableRectorInterface;
use Rector\Enum\ObjectReference;
use Rector\Exception\ShouldNotHappenException;
use Rector\PhpParser\AstResolver;
use Rector\PHPStanStaticTypeMapper\Enum\TypeKind;
use Rector\Rector\AbstractRector;
use Rector\StaticTypeMapper\StaticTypeMapper;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
use RectorPrefix202510\Webmozart\Assert\Assert;
/**
* @see \Rector\Tests\Arguments\Rector\ClassMethod\ArgumentAdderRector\ArgumentAdderRectorTest
*/
final class ArgumentAdderRector extends AbstractRector implements ConfigurableRectorInterface
{
/**
* @readonly
*/
private ArgumentAddingScope $argumentAddingScope;
/**
* @readonly
*/
private ChangedArgumentsDetector $changedArgumentsDetector;
/**
* @readonly
*/
private AstResolver $astResolver;
/**
* @readonly
*/
private StaticTypeMapper $staticTypeMapper;
/**
* @var ArgumentAdder[]|ArgumentAdderWithoutDefaultValue[]
*/
private array $addedArguments = [];
private bool $hasChanged = \false;
public function __construct(ArgumentAddingScope $argumentAddingScope, ChangedArgumentsDetector $changedArgumentsDetector, AstResolver $astResolver, StaticTypeMapper $staticTypeMapper)
{
$this->argumentAddingScope = $argumentAddingScope;
$this->changedArgumentsDetector = $changedArgumentsDetector;
$this->astResolver = $astResolver;
$this->staticTypeMapper = $staticTypeMapper;
}
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Add new default arguments in calls of defined methods and class types', [new ConfiguredCodeSample(<<<'CODE_SAMPLE'
$someObject = new SomeExampleClass;
$someObject->someMethod();
class MyCustomClass extends SomeExampleClass
{
public function someMethod()
{
}
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
$someObject = new SomeExampleClass;
$someObject->someMethod(true);
class MyCustomClass extends SomeExampleClass
{
public function someMethod($value = true)
{
}
}
CODE_SAMPLE
, [new ArgumentAdder('SomeExampleClass', 'someMethod', 0, 'someArgument', \true, new ObjectType('SomeType'))])]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [MethodCall::class, StaticCall::class, Class_::class];
}
/**
* @param MethodCall|StaticCall|Class_ $node
* @return \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Stmt\Class_|null
*/
public function refactor(Node $node)
{
$this->hasChanged = \false;
if ($node instanceof MethodCall || $node instanceof StaticCall) {
$this->refactorCall($node);
} else {
foreach ($node->getMethods() as $classMethod) {
$this->refactorClassMethod($node, $classMethod);
}
}
if ($this->hasChanged) {
return $node;
}
return null;
}
/**
* @param mixed[] $configuration
*/
public function configure(array $configuration): void
{
Assert::allIsAnyOf($configuration, [ArgumentAdder::class, ArgumentAdderWithoutDefaultValue::class]);
$this->addedArguments = $configuration;
}
/**
* @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $call
*/
private function isObjectTypeMatch($call, ObjectType $objectType): bool
{
if ($call instanceof MethodCall) {
return $this->isObjectType($call->var, $objectType);
}
return $this->isObjectType($call->class, $objectType);
}
/**
* @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $node
* @param \Rector\Arguments\ValueObject\ArgumentAdder|\Rector\Arguments\ValueObject\ArgumentAdderWithoutDefaultValue $argumentAdder
*/
private function processPositionWithDefaultValues($node, $argumentAdder): void
{
if ($this->shouldSkipParameter($node, $argumentAdder)) {
return;
}
$argumentType = $argumentAdder->getArgumentType();
$position = $argumentAdder->getPosition();
if ($node instanceof ClassMethod) {
$this->addClassMethodParam($node, $argumentAdder, $argumentType, $position);
return;
}
if ($node instanceof StaticCall) {
$this->processStaticCall($node, $position, $argumentAdder);
return;
}
$this->processMethodCall($node, $argumentAdder, $position);
}
/**
* @param \Rector\Arguments\ValueObject\ArgumentAdder|\Rector\Arguments\ValueObject\ArgumentAdderWithoutDefaultValue $argumentAdder
*/
private function processMethodCall(MethodCall $methodCall, $argumentAdder, int $position): void
{
if ($argumentAdder instanceof ArgumentAdderWithoutDefaultValue) {
return;
}
$defaultValue = $argumentAdder->getArgumentDefaultValue();
$arg = new Arg(BuilderHelpers::normalizeValue($defaultValue));
if (isset($methodCall->args[$position])) {
return;
}
$this->fillGapBetweenWithDefaultValue($methodCall, $position);
$methodCall->args[$position] = $arg;
$this->hasChanged = \true;
}
/**
* @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $node
*/
private function fillGapBetweenWithDefaultValue($node, int $position): void
{
$lastPosition = count($node->getArgs()) - 1;
if ($position <= $lastPosition) {
return;
}
if ($position - $lastPosition === 1) {
return;
}
$classMethod = $this->astResolver->resolveClassMethodFromCall($node);
if (!$classMethod instanceof ClassMethod) {
return;
}
for ($index = $lastPosition + 1; $index < $position; ++$index) {
$param = $classMethod->params[$index];
if (!$param->default instanceof Expr) {
throw new ShouldNotHappenException('Previous position does not have default value');
}
$node->args[$index] = new Arg($this->nodeFactory->createReprintedNode($param->default));
}
}
/**
* @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $node
* @param \Rector\Arguments\ValueObject\ArgumentAdder|\Rector\Arguments\ValueObject\ArgumentAdderWithoutDefaultValue $argumentAdder
*/
private function shouldSkipParameter($node, $argumentAdder): bool
{
$position = $argumentAdder->getPosition();
$argumentName = $argumentAdder->getArgumentName();
if ($argumentName === null) {
return \true;
}
if ($node instanceof ClassMethod) {
// already added?
if (!isset($node->params[$position])) {
return \false;
}
$param = $node->params[$position];
// argument added and name has been changed
if (!$this->isName($param, $argumentName)) {
return \true;
}
// argument added and default has been changed
if ($this->isDefaultValueChanged($argumentAdder, $node, $position)) {
return \true;
}
// argument added and type has been changed
return $this->changedArgumentsDetector->isTypeChanged($param, $argumentAdder->getArgumentType());
}
if (isset($node->args[$position])) {
return \true;
}
// Check if default value is the same
$classMethod = $this->astResolver->resolveClassMethodFromCall($node);
if (!$classMethod instanceof ClassMethod) {
// is correct scope?
return !$this->argumentAddingScope->isInCorrectScope($node, $argumentAdder);
}
if (!isset($classMethod->params[$position])) {
// is correct scope?
return !$this->argumentAddingScope->isInCorrectScope($node, $argumentAdder);
}
if ($this->isDefaultValueChanged($argumentAdder, $classMethod, $position)) {
// is correct scope?
return !$this->argumentAddingScope->isInCorrectScope($node, $argumentAdder);
}
return \true;
}
/**
* @param \Rector\Arguments\ValueObject\ArgumentAdder|\Rector\Arguments\ValueObject\ArgumentAdderWithoutDefaultValue $argumentAdder
*/
private function isDefaultValueChanged($argumentAdder, ClassMethod $classMethod, int $position): bool
{
return $argumentAdder instanceof ArgumentAdder && $this->changedArgumentsDetector->isDefaultValueChanged($classMethod->params[$position], $argumentAdder->getArgumentDefaultValue());
}
/**
* @param \Rector\Arguments\ValueObject\ArgumentAdder|\Rector\Arguments\ValueObject\ArgumentAdderWithoutDefaultValue $argumentAdder
*/
private function addClassMethodParam(ClassMethod $classMethod, $argumentAdder, ?Type $type, int $position): void
{
$argumentName = $argumentAdder->getArgumentName();
if ($argumentName === null) {
throw new ShouldNotHappenException();
}
if ($argumentAdder instanceof ArgumentAdder) {
$param = new Param(new Variable($argumentName), BuilderHelpers::normalizeValue($argumentAdder->getArgumentDefaultValue()));
} else {
$param = new Param(new Variable($argumentName));
}
if ($type instanceof Type) {
$param->type = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($type, TypeKind::PARAM);
}
$classMethod->params[$position] = $param;
$this->hasChanged = \true;
}
/**
* @param \Rector\Arguments\ValueObject\ArgumentAdder|\Rector\Arguments\ValueObject\ArgumentAdderWithoutDefaultValue $argumentAdder
*/
private function processStaticCall(StaticCall $staticCall, int $position, $argumentAdder): void
{
if ($argumentAdder instanceof ArgumentAdderWithoutDefaultValue) {
return;
}
$argumentName = $argumentAdder->getArgumentName();
if ($argumentName === null) {
throw new ShouldNotHappenException();
}
if (!$staticCall->class instanceof Name) {
return;
}
if (!$this->isName($staticCall->class, ObjectReference::PARENT)) {
return;
}
$this->fillGapBetweenWithDefaultValue($staticCall, $position);
$staticCall->args[$position] = new Arg(new Variable($argumentName));
$this->hasChanged = \true;
}
/**
* @param \PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Expr\MethodCall $call
*/
private function refactorCall($call): void
{
if ($call->isFirstClassCallable()) {
return;
}
$callName = $this->getName($call->name);
if ($callName === null) {
return;
}
foreach ($this->addedArguments as $addedArgument) {
if (!$this->nodeNameResolver->isStringName($callName, $addedArgument->getMethod())) {
continue;
}
if (!$this->isObjectTypeMatch($call, $addedArgument->getObjectType())) {
continue;
}
$this->processPositionWithDefaultValues($call, $addedArgument);
}
}
private function refactorClassMethod(Class_ $class, ClassMethod $classMethod): void
{
foreach ($this->addedArguments as $addedArgument) {
if (!$this->isName($classMethod, $addedArgument->getMethod())) {
continue;
}
if (!$this->isObjectType($class, $addedArgument->getObjectType())) {
continue;
}
$this->processPositionWithDefaultValues($classMethod, $addedArgument);
}
}
}
@@ -1,113 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Arguments\Rector\ClassMethod;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\Arguments\ArgumentDefaultValueReplacer;
use Rector\Arguments\ValueObject\ReplaceArgumentDefaultValue;
use Rector\Contract\Rector\ConfigurableRectorInterface;
use Rector\Rector\AbstractRector;
use Rector\ValueObject\MethodName;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
use RectorPrefix202510\Webmozart\Assert\Assert;
/**
* @api used in rector-symfony
* @see \Rector\Tests\Arguments\Rector\ClassMethod\ReplaceArgumentDefaultValueRector\ReplaceArgumentDefaultValueRectorTest
*/
final class ReplaceArgumentDefaultValueRector extends AbstractRector implements ConfigurableRectorInterface
{
/**
* @readonly
*/
private ArgumentDefaultValueReplacer $argumentDefaultValueReplacer;
/**
* @var ReplaceArgumentDefaultValue[]
*/
private array $replaceArgumentDefaultValues = [];
public function __construct(ArgumentDefaultValueReplacer $argumentDefaultValueReplacer)
{
$this->argumentDefaultValueReplacer = $argumentDefaultValueReplacer;
}
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Replace defined map of arguments in defined methods and their calls', [new ConfiguredCodeSample(<<<'CODE_SAMPLE'
$someObject = new SomeClass;
$someObject->someMethod(SomeClass::OLD_CONSTANT);
CODE_SAMPLE
, <<<'CODE_SAMPLE'
$someObject = new SomeClass;
$someObject->someMethod(false);
CODE_SAMPLE
, [new ReplaceArgumentDefaultValue('SomeClass', 'someMethod', 0, 'SomeClass::OLD_CONSTANT', \false)])]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [MethodCall::class, StaticCall::class, ClassMethod::class, New_::class];
}
/**
* @param MethodCall|StaticCall|ClassMethod|New_ $node
* @return \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Expr\New_|null
*/
public function refactor(Node $node)
{
if ($node instanceof New_) {
return $this->refactorNew($node);
}
$nodeName = $this->getName($node->name);
if ($nodeName === null) {
return null;
}
$hasChanged = \false;
$currentNode = $node;
foreach ($this->replaceArgumentDefaultValues as $replaceArgumentDefaultValue) {
if (!$this->nodeNameResolver->isStringName($nodeName, $replaceArgumentDefaultValue->getMethod())) {
continue;
}
if (!$this->nodeTypeResolver->isMethodStaticCallOrClassMethodObjectType($currentNode, $replaceArgumentDefaultValue->getObjectType())) {
continue;
}
$replacedNode = $this->argumentDefaultValueReplacer->processReplaces($currentNode, $replaceArgumentDefaultValue);
if ($replacedNode !== null && $replacedNode !== $currentNode) {
$currentNode = $replacedNode;
$hasChanged = \true;
}
}
return $hasChanged ? $currentNode : null;
}
/**
* @param mixed[] $configuration
*/
public function configure(array $configuration): void
{
Assert::allIsAOf($configuration, ReplaceArgumentDefaultValue::class);
$this->replaceArgumentDefaultValues = $configuration;
}
private function refactorNew(New_ $new): ?New_
{
$hasChanged = \false;
$currentNode = $new;
foreach ($this->replaceArgumentDefaultValues as $replaceArgumentDefaultValue) {
if ($replaceArgumentDefaultValue->getMethod() !== MethodName::CONSTRUCT) {
continue;
}
if (!$this->isObjectType($currentNode, $replaceArgumentDefaultValue->getObjectType())) {
continue;
}
$replacedNode = $this->argumentDefaultValueReplacer->processReplaces($currentNode, $replaceArgumentDefaultValue);
if ($replacedNode !== null && $replacedNode !== $currentNode) {
$currentNode = $replacedNode;
$hasChanged = \true;
}
}
return $hasChanged ? $currentNode : null;
}
}
@@ -1,77 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Arguments\Rector\FuncCall;
use PhpParser\Node;
use PhpParser\Node\Expr\FuncCall;
use Rector\Arguments\ArgumentDefaultValueReplacer;
use Rector\Arguments\ValueObject\ReplaceFuncCallArgumentDefaultValue;
use Rector\Contract\Rector\ConfigurableRectorInterface;
use Rector\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
use RectorPrefix202510\Webmozart\Assert\Assert;
/**
* @see \Rector\Tests\Arguments\Rector\FuncCall\FunctionArgumentDefaultValueReplacerRector\FunctionArgumentDefaultValueReplacerRectorTest
*/
final class FunctionArgumentDefaultValueReplacerRector extends AbstractRector implements ConfigurableRectorInterface
{
/**
* @readonly
*/
private ArgumentDefaultValueReplacer $argumentDefaultValueReplacer;
/**
* @var ReplaceFuncCallArgumentDefaultValue[]
*/
private array $replacedArguments = [];
public function __construct(ArgumentDefaultValueReplacer $argumentDefaultValueReplacer)
{
$this->argumentDefaultValueReplacer = $argumentDefaultValueReplacer;
}
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Streamline the operator arguments of `version_compare` function', [new ConfiguredCodeSample(<<<'CODE_SAMPLE'
version_compare(PHP_VERSION, '5.6', 'gte');
CODE_SAMPLE
, <<<'CODE_SAMPLE'
version_compare(PHP_VERSION, '5.6', 'ge');
CODE_SAMPLE
, [new ReplaceFuncCallArgumentDefaultValue('version_compare', 2, 'gte', 'ge')])]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [FuncCall::class];
}
/**
* @param FuncCall $node
*/
public function refactor(Node $node): ?\PhpParser\Node\Expr\FuncCall
{
$hasChanged = \false;
foreach ($this->replacedArguments as $replacedArgument) {
if (!$this->isName($node->name, $replacedArgument->getFunction())) {
continue;
}
$changedNode = $this->argumentDefaultValueReplacer->processReplaces($node, $replacedArgument);
if ($changedNode instanceof Node) {
$hasChanged = \true;
}
}
if ($hasChanged) {
return $node;
}
return null;
}
/**
* @param mixed[] $configuration
*/
public function configure(array $configuration): void
{
Assert::allIsAOf($configuration, ReplaceFuncCallArgumentDefaultValue::class);
$this->replacedArguments = $configuration;
}
}
@@ -1,100 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Arguments\Rector\MethodCall;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use Rector\Arguments\ValueObject\RemoveMethodCallParam;
use Rector\Contract\Rector\ConfigurableRectorInterface;
use Rector\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
use RectorPrefix202510\Webmozart\Assert\Assert;
/**
* @note used extensively https://github.com/search?q=RemoveMethodCallParamRector%3A%3Aclass+language%3APHP&type=code&l=PHP
* @see \Rector\Tests\Arguments\Rector\MethodCall\RemoveMethodCallParamRector\RemoveMethodCallParamRectorTest
*/
final class RemoveMethodCallParamRector extends AbstractRector implements ConfigurableRectorInterface
{
/**
* @var RemoveMethodCallParam[]
*/
private array $removeMethodCallParams = [];
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Remove parameter of method call', [new ConfiguredCodeSample(<<<'CODE_SAMPLE'
final class SomeClass
{
public function run(Caller $caller)
{
$caller->process(1, 2);
}
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
final class SomeClass
{
public function run(Caller $caller)
{
$caller->process(1);
}
}
CODE_SAMPLE
, [new RemoveMethodCallParam('Caller', 'process', 1)])]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [MethodCall::class, StaticCall::class];
}
/**
* @param MethodCall|StaticCall $node
*/
public function refactor(Node $node): ?Node
{
$hasChanged = \false;
if ($node->isFirstClassCallable()) {
return null;
}
foreach ($this->removeMethodCallParams as $removeMethodCallParam) {
if (!$this->isName($node->name, $removeMethodCallParam->getMethodName())) {
continue;
}
if (!$this->isCallerObjectType($node, $removeMethodCallParam)) {
continue;
}
$args = $node->getArgs();
if (!isset($args[$removeMethodCallParam->getParamPosition()])) {
continue;
}
unset($node->args[$removeMethodCallParam->getParamPosition()]);
$hasChanged = \true;
}
if (!$hasChanged) {
return null;
}
return $node;
}
/**
* @param mixed[] $configuration
*/
public function configure(array $configuration): void
{
Assert::allIsInstanceOf($configuration, RemoveMethodCallParam::class);
$this->removeMethodCallParams = $configuration;
}
/**
* @param \PhpParser\Node\Expr\StaticCall|\PhpParser\Node\Expr\MethodCall $call
*/
private function isCallerObjectType($call, RemoveMethodCallParam $removeMethodCallParam): bool
{
if ($call instanceof MethodCall) {
return $this->isObjectType($call->var, $removeMethodCallParam->getObjectType());
}
return $this->isObjectType($call->class, $removeMethodCallParam->getObjectType());
}
}
@@ -1,85 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Arguments\ValueObject;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use Rector\Validation\RectorAssert;
final class ArgumentAdder
{
/**
* @readonly
*/
private string $class;
/**
* @readonly
*/
private string $method;
/**
* @readonly
*/
private int $position;
/**
* @readonly
*/
private ?string $argumentName = null;
/**
* @var mixed|null
*/
private $argumentDefaultValue = null;
/**
* @readonly
* @var \PHPStan\Type\Type|null
*/
private $argumentType = null;
/**
* @readonly
*/
private ?string $scope = null;
/**
* @param mixed|null $argumentDefaultValue
*/
public function __construct(string $class, string $method, int $position, ?string $argumentName = null, $argumentDefaultValue = null, ?\PHPStan\Type\Type $argumentType = null, ?string $scope = null)
{
$this->class = $class;
$this->method = $method;
$this->position = $position;
$this->argumentName = $argumentName;
$this->argumentDefaultValue = $argumentDefaultValue;
$this->argumentType = $argumentType;
$this->scope = $scope;
RectorAssert::className($class);
}
public function getObjectType(): ObjectType
{
return new ObjectType($this->class);
}
public function getMethod(): string
{
return $this->method;
}
public function getPosition(): int
{
return $this->position;
}
public function getArgumentName(): ?string
{
return $this->argumentName;
}
/**
* @return mixed|null
*/
public function getArgumentDefaultValue()
{
return $this->argumentDefaultValue;
}
public function getArgumentType(): ?Type
{
return $this->argumentType;
}
public function getScope(): ?string
{
return $this->scope;
}
}
@@ -1,70 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Arguments\ValueObject;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use Rector\Validation\RectorAssert;
final class ArgumentAdderWithoutDefaultValue
{
/**
* @readonly
*/
private string $class;
/**
* @readonly
*/
private string $method;
/**
* @readonly
*/
private int $position;
/**
* @readonly
*/
private ?string $argumentName = null;
/**
* @readonly
* @var \PHPStan\Type\Type|null
*/
private $argumentType = null;
/**
* @readonly
*/
private ?string $scope = null;
public function __construct(string $class, string $method, int $position, ?string $argumentName = null, ?\PHPStan\Type\Type $argumentType = null, ?string $scope = null)
{
$this->class = $class;
$this->method = $method;
$this->position = $position;
$this->argumentName = $argumentName;
$this->argumentType = $argumentType;
$this->scope = $scope;
RectorAssert::className($class);
}
public function getObjectType(): ObjectType
{
return new ObjectType($this->class);
}
public function getMethod(): string
{
return $this->method;
}
public function getPosition(): int
{
return $this->position;
}
public function getArgumentName(): ?string
{
return $this->argumentName;
}
public function getArgumentType(): ?Type
{
return $this->argumentType;
}
public function getScope(): ?string
{
return $this->scope;
}
}
@@ -1,42 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Arguments\ValueObject;
use PHPStan\Type\ObjectType;
use Rector\Validation\RectorAssert;
final class RemoveMethodCallParam
{
/**
* @readonly
*/
private string $class;
/**
* @readonly
*/
private string $methodName;
/**
* @readonly
*/
private int $paramPosition;
public function __construct(string $class, string $methodName, int $paramPosition)
{
$this->class = $class;
$this->methodName = $methodName;
$this->paramPosition = $paramPosition;
RectorAssert::className($class);
RectorAssert::methodName($methodName);
}
public function getObjectType(): ObjectType
{
return new ObjectType($this->class);
}
public function getMethodName(): string
{
return $this->methodName;
}
public function getParamPosition(): int
{
return $this->paramPosition;
}
}
@@ -1,78 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Arguments\ValueObject;
use PHPStan\Type\ObjectType;
use Rector\Arguments\Contract\ReplaceArgumentDefaultValueInterface;
use Rector\Validation\RectorAssert;
final class ReplaceArgumentDefaultValue implements ReplaceArgumentDefaultValueInterface
{
/**
* @readonly
*/
private string $class;
/**
* @readonly
*/
private string $method;
/**
* @var int<0, max>
* @readonly
*/
private int $position;
/**
* @readonly
* @var mixed
*/
private $valueBefore;
/**
* @readonly
* @var mixed
*/
private $valueAfter;
/**
* @var string
*/
public const ANY_VALUE_BEFORE = '*ANY_VALUE_BEFORE*';
/**
* @param int<0, max> $position
* @param mixed $valueBefore
* @param mixed $valueAfter
*/
public function __construct(string $class, string $method, int $position, $valueBefore, $valueAfter)
{
$this->class = $class;
$this->method = $method;
$this->position = $position;
$this->valueBefore = $valueBefore;
$this->valueAfter = $valueAfter;
RectorAssert::className($class);
}
public function getObjectType(): ObjectType
{
return new ObjectType($this->class);
}
public function getMethod(): string
{
return $this->method;
}
public function getPosition(): int
{
return $this->position;
}
/**
* @return mixed
*/
public function getValueBefore()
{
return $this->valueBefore;
}
/**
* @return mixed
*/
public function getValueAfter()
{
return $this->valueAfter;
}
}
@@ -1,60 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Arguments\ValueObject;
use Rector\Arguments\Contract\ReplaceArgumentDefaultValueInterface;
final class ReplaceFuncCallArgumentDefaultValue implements ReplaceArgumentDefaultValueInterface
{
/**
* @readonly
*/
private string $function;
/**
* @readonly
*/
private int $position;
/**
* @readonly
* @var mixed
*/
private $valueBefore;
/**
* @readonly
* @var mixed
*/
private $valueAfter;
/**
* @param mixed $valueBefore
* @param mixed $valueAfter
*/
public function __construct(string $function, int $position, $valueBefore, $valueAfter)
{
$this->function = $function;
$this->position = $position;
$this->valueBefore = $valueBefore;
$this->valueAfter = $valueAfter;
}
public function getFunction(): string
{
return $this->function;
}
public function getPosition(): int
{
return $this->position;
}
/**
* @return mixed
*/
public function getValueBefore()
{
return $this->valueBefore;
}
/**
* @return mixed
*/
public function getValueAfter()
{
return $this->valueAfter;
}
}
@@ -1,16 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Assert\Enum;
final class AssertClassName
{
/**
* @var string
*/
public const WEBMOZART = 'Webmozart\Assert\Assert';
/**
* @var string
*/
public const BEBERLEI = 'Assert\Assertion';
}
@@ -1,42 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Assert\NodeAnalyzer;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use PhpParser\PrettyPrinter\Standard;
use Rector\Assert\Enum\AssertClassName;
final class ExistingAssertStaticCallResolver
{
/**
* @return string[]
*/
public function resolve(ClassMethod $classMethod): array
{
if ($classMethod->stmts === null) {
return [];
}
$existingAssertCallHashes = [];
$standard = new Standard();
foreach ($classMethod->stmts as $currentStmt) {
if (!$currentStmt instanceof Expression) {
continue;
}
if (!$currentStmt->expr instanceof StaticCall) {
continue;
}
$staticCall = $currentStmt->expr;
if (!$staticCall->class instanceof Name) {
continue;
}
if (!in_array($staticCall->class->toString(), [AssertClassName::WEBMOZART, AssertClassName::BEBERLEI], \true)) {
continue;
}
$existingAssertCallHashes[] = $standard->prettyPrintExpr($staticCall);
}
return $existingAssertCallHashes;
}
}
@@ -1,208 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Assert\Rector\ClassMethod;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use PhpParser\PrettyPrinter\Standard;
use PHPStan\Type\ArrayType;
use PHPStan\Type\BooleanType;
use PHPStan\Type\FloatType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use Rector\Assert\Enum\AssertClassName;
use Rector\Assert\NodeAnalyzer\ExistingAssertStaticCallResolver;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\Contract\Rector\ConfigurableRectorInterface;
use Rector\PHPStan\ScopeFetcher;
use Rector\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
use RectorPrefix202510\Webmozart\Assert\Assert;
/**
* @experimental Check generic array key/value types in runtime with assert. Generics for impatient people.
*
* @see \Rector\Tests\Assert\Rector\ClassMethod\AddAssertArrayFromClassMethodDocblockRector\AddAssertArrayFromClassMethodDocblockRectorTest
*/
final class AddAssertArrayFromClassMethodDocblockRector extends AbstractRector implements ConfigurableRectorInterface
{
/**
* @readonly
*/
private PhpDocInfoFactory $phpDocInfoFactory;
/**
* @readonly
*/
private ExistingAssertStaticCallResolver $existingAssertStaticCallResolver;
private string $assertClass = AssertClassName::WEBMOZART;
public function __construct(PhpDocInfoFactory $phpDocInfoFactory, ExistingAssertStaticCallResolver $existingAssertStaticCallResolver)
{
$this->phpDocInfoFactory = $phpDocInfoFactory;
$this->existingAssertStaticCallResolver = $existingAssertStaticCallResolver;
}
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Add key and value assert based on docblock @param type declarations (pick from "webmozart" or "beberlei" asserts)', [new ConfiguredCodeSample(<<<'CODE_SAMPLE'
<?php
namespace RectorPrefix202510;
class SomeClass
{
/**
* @param int[] $items
*/
public function run(array $items)
{
}
}
\class_alias('SomeClass', 'SomeClass', \false);
CODE_SAMPLE
, <<<'CODE_SAMPLE'
<?php
namespace RectorPrefix202510;
use RectorPrefix202510\Webmozart\Assert\Assert;
class SomeClass
{
/**
* @param int[] $items
*/
public function run(array $items)
{
Assert::allInteger($items);
}
}
\class_alias('SomeClass', 'SomeClass', \false);
CODE_SAMPLE
, [AssertClassName::WEBMOZART])]);
}
public function getNodeTypes(): array
{
return [ClassMethod::class];
}
/**
* @param ClassMethod $node
*/
public function refactor(Node $node): ?ClassMethod
{
$scope = ScopeFetcher::fetch($node);
if (!$scope->isInClass()) {
return null;
}
if ($node->stmts === null || $node->isAbstract()) {
return null;
}
$methodPhpDocInfo = $this->phpDocInfoFactory->createFromNode($node);
if (!$methodPhpDocInfo instanceof PhpDocInfo) {
return null;
}
$paramTagValueNodes = $methodPhpDocInfo->getParamTagValueNodes();
if ($paramTagValueNodes === []) {
return null;
}
$assertStaticCallStmts = [];
foreach ($node->getParams() as $param) {
if (!$param->type instanceof Identifier) {
continue;
}
// handle arrays only
if (!$this->isName($param->type, 'array')) {
continue;
}
if (!$param->var instanceof Variable) {
continue;
}
$paramName = $param->var->name;
if (!is_string($paramName)) {
continue;
}
$paramDocType = $methodPhpDocInfo->getParamType($paramName);
if (!$paramDocType instanceof ArrayType) {
continue;
}
$valueAssertMethod = $this->matchTypeToAssertMethod($paramDocType->getItemType());
if (is_string($valueAssertMethod)) {
$assertStaticCallStmts[] = $this->createAssertExpression($param->var, $valueAssertMethod);
}
$keyAssertMethod = $this->matchTypeToAssertMethod($paramDocType->getKeyType());
if (is_string($keyAssertMethod)) {
$arrayKeys = new FuncCall(new Name('array_keys'), [new Arg($param->var)]);
$assertStaticCallStmts[] = $this->createAssertExpression($arrayKeys, $keyAssertMethod);
}
}
// filter existing assert to avoid duplication
if ($assertStaticCallStmts === []) {
return null;
}
$existingAssertCallHashes = $this->existingAssertStaticCallResolver->resolve($node);
$assertStaticCallStmts = $this->filterOutExistingStaticCall($assertStaticCallStmts, $existingAssertCallHashes);
if ($assertStaticCallStmts === []) {
return null;
}
$node->stmts = array_merge($assertStaticCallStmts, $node->stmts);
return $node;
}
/**
* @param array<string> $configuration
*/
public function configure(array $configuration): void
{
if ($configuration === []) {
// default
return;
}
Assert::count($configuration, 1);
Assert::inArray($configuration[0], [AssertClassName::BEBERLEI, AssertClassName::WEBMOZART]);
$this->assertClass = $configuration[0];
}
private function createAssertExpression(Expr $expr, string $methodName): Expression
{
$assertFullyQualified = new FullyQualified($this->assertClass);
$staticCall = new StaticCall($assertFullyQualified, $methodName, [new Arg($expr)]);
return new Expression($staticCall);
}
/**
* @param Expression[] $assertStaticCallStmts
* @param string[] $existingAssertCallHashes
* @return Expression[]
*/
private function filterOutExistingStaticCall(array $assertStaticCallStmts, array $existingAssertCallHashes): array
{
$standard = new Standard();
return array_filter($assertStaticCallStmts, function (Expression $assertStaticCallExpression) use ($standard, $existingAssertCallHashes): bool {
$currentStaticCallHash = $standard->prettyPrintExpr($assertStaticCallExpression->expr);
return !in_array($currentStaticCallHash, $existingAssertCallHashes, \true);
});
}
private function matchTypeToAssertMethod(Type $type): ?string
{
if ($type instanceof IntegerType) {
return 'allInteger';
}
if ($type instanceof StringType) {
return 'allString';
}
if ($type instanceof FloatType) {
return 'allFloat';
}
if ($type instanceof BooleanType) {
return 'allBoolean';
}
return null;
}
}
@@ -1,142 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Carbon\NodeFactory;
use RectorPrefix202510\Nette\Utils\Strings;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Scalar\Int_;
use PhpParser\Node\Scalar\String_;
final class CarbonCallFactory
{
/**
* @var string
* @see https://regex101.com/r/LLMrFw/1
*/
private const PLUS_MINUS_COUNT_REGEX = '#(?<operator>\+|-)(\s+)?(?<count>\d+)(\s+)?(?<unit>seconds|second|sec|minutes|minute|min|hours|hour|days|day|weeks|week|months|month|years|year)#';
/**
* @var string
* @see https://regex101.com/r/IhxHTO/1
*/
private const STATIC_DATE_REGEX = '#now|yesterday|today|tomorrow#';
/**
* @return \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall
*/
public function createFromDateTimeString(FullyQualified $carbonFullyQualified, String_ $string)
{
$carbonCall = $this->createStaticCall($carbonFullyQualified, $string);
$string->value = Strings::replace($string->value, self::STATIC_DATE_REGEX);
// Handle add/sub multiple times
while ($match = Strings::match($string->value, self::PLUS_MINUS_COUNT_REGEX)) {
$methodCall = $this->createModifyMethodCall($carbonCall, new Int_((int) $match['count']), $match['unit'], $match['operator']);
if ($methodCall instanceof MethodCall) {
$carbonCall = $methodCall;
$string->value = Strings::replace($string->value, self::PLUS_MINUS_COUNT_REGEX, '', 1);
}
}
// If we still have something in the string, we go back to the first method and replace this with a parse
if (($rest = Strings::trim($string->value)) !== '') {
$currentCall = $carbonCall;
$callStack = [];
while ($currentCall instanceof MethodCall) {
$callStack[] = $currentCall;
$currentCall = $currentCall->var;
}
if (!$currentCall instanceof StaticCall) {
return $carbonCall;
}
// If we fallback to a parse we want to include tomorrow/today/yesterday etc
if ($currentCall->name instanceof Identifier && $currentCall->name->name !== 'now') {
$rest .= ' ' . $currentCall->name->name;
}
$currentCall->name = new Identifier('parse');
$currentCall->args = [new Arg(new String_($rest))];
// Rebuild original call from callstack
$carbonCall = $this->rebuildCallStack($currentCall, $callStack);
}
return $carbonCall;
}
private function createStaticCall(FullyQualified $carbonFullyQualified, String_ $string): StaticCall
{
$startDate = Strings::match($string->value, self::STATIC_DATE_REGEX)[0] ?? 'now';
return new StaticCall($carbonFullyQualified, new Identifier($startDate));
}
/**
* @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $carbonCall
*/
private function createModifyMethodCall($carbonCall, Int_ $int, string $unit, string $operator): ?MethodCall
{
switch ($unit) {
case 'sec':
case 'second':
case 'seconds':
$unit = 'seconds';
break;
case 'min':
case 'minute':
case 'minutes':
$unit = 'minutes';
break;
case 'hour':
case 'hours':
$unit = 'hours';
break;
case 'day':
case 'days':
$unit = 'days';
break;
case 'week':
case 'weeks':
$unit = 'weeks';
break;
case 'month':
case 'months':
$unit = 'months';
break;
case 'year':
case 'years':
$unit = 'years';
break;
default:
$unit = null;
break;
}
switch ($operator) {
case '+':
$operator = 'add';
break;
case '-':
$operator = 'sub';
break;
default:
$operator = null;
break;
}
if ($unit === null || $operator === null) {
return null;
}
$methodName = $operator . ucfirst($unit);
return new MethodCall($carbonCall, new Identifier($methodName), [new Arg($int)]);
}
/**
* @param MethodCall[] $callStack
* @return \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall
*/
private function rebuildCallStack(StaticCall $staticCall, array $callStack)
{
if ($callStack === []) {
return $staticCall;
}
$currentCall = $staticCall;
$callStack = array_reverse($callStack);
foreach ($callStack as $call) {
$call->var = $currentCall;
$currentCall = $call;
}
return $currentCall;
}
}
@@ -1,207 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Carbon\Rector\FuncCall;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\BinaryOp\Minus;
use PhpParser\Node\Expr\BinaryOp\Mul;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Scalar\Int_;
use PhpParser\Node\Scalar\String_;
use Rector\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\Carbon\Rector\FuncCall\DateFuncCallToCarbonRector\DateFuncCallToCarbonRectorTest
*/
final class DateFuncCallToCarbonRector extends AbstractRector
{
private const TIME_UNITS = [['weeks', 604800], ['days', 86400], ['hours', 3600], ['minutes', 60], ['seconds', 1]];
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Convert `date()` function call to `Carbon::now()->format(*)`', [new CodeSample(<<<'CODE_SAMPLE'
class SomeClass
{
public function run()
{
$date = date('Y-m-d');
}
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
class SomeClass
{
public function run()
{
$date = \Carbon\Carbon::now()->format('Y-m-d');
}
}
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [Minus::class, FuncCall::class];
}
/**
* @param FuncCall $node
*/
public function refactor(Node $node): ?Node
{
if ($node instanceof Minus) {
$left = $node->left;
if ($left instanceof FuncCall && !$left->isFirstClassCallable() && $this->isName($left->name, 'time')) {
$timeUnit = $this->detectTimeUnit($node->right);
if ($timeUnit !== null) {
return $this->createCarbonSubtract($timeUnit);
}
}
return null;
}
if (!$node instanceof FuncCall) {
return null;
}
if ($node->isFirstClassCallable()) {
return null;
}
if ($this->isName($node->name, 'date') && isset($node->args[1]) && $node->args[1] instanceof Arg) {
$format = $this->getArgValue($node, 0);
if (!$format instanceof Expr) {
return null;
}
$timestamp = $node->args[1]->value;
if ($timestamp instanceof FuncCall && $this->isName($timestamp->name, 'strtotime') && isset($timestamp->args[0]) && $timestamp->args[0] instanceof Arg) {
$dateExpr = $timestamp->args[0]->value;
return $this->createCarbonParseFormat($dateExpr, $format);
}
// @phpstan-ignore if.alwaysTrue
if ($this->getType($timestamp)->isInteger()) {
return $this->createCarbonFromTimestamp($timestamp, $format);
}
}
if ($this->isName($node->name, 'date') && isset($node->args[0])) {
$format = $this->getArgValue($node, 0);
if ($format instanceof String_) {
return $this->createCarbonNowFormat($format);
}
}
if ($this->isName($node->name, 'strtotime') && isset($node->args[0])) {
$dateExpr = $this->getArgValue($node, 0);
$baseTimestamp = $this->getArgValue($node, 1);
if ($dateExpr instanceof Expr && !$baseTimestamp instanceof Expr) {
return $this->createCarbonParseTimestamp($dateExpr);
}
if ($dateExpr instanceof Expr && $baseTimestamp instanceof String_) {
$isRelative = strncmp($baseTimestamp->value, '+', strlen('+')) === 0 || strncmp($baseTimestamp->value, '-', strlen('-')) === 0;
if ($isRelative) {
return null;
// @todo implement relative changes based on second arg
}
}
}
return null;
}
private function getArgValue(FuncCall $funcCall, int $index): ?Expr
{
if (!isset($funcCall->args[$index]) || !$funcCall->args[$index] instanceof Arg) {
return null;
}
return $funcCall->args[$index]->value;
}
private function createCarbonNowFormat(String_ $string): MethodCall
{
return new MethodCall($this->createCarbonNow(), 'format', [new Arg($string)]);
}
private function createCarbonNow(): StaticCall
{
return new StaticCall(new FullyQualified('Carbon\Carbon'), 'now');
}
private function createCarbonParseTimestamp(Expr $dateExpr): MethodCall
{
$staticCall = new StaticCall(new FullyQualified('Carbon\Carbon'), 'parse', [new Arg($dateExpr)]);
return new MethodCall($staticCall, 'getTimestamp');
}
private function createCarbonParseFormat(Expr $dateExpr, Expr $format): MethodCall
{
$staticCall = new StaticCall(new FullyQualified('Carbon\Carbon'), 'parse', [new Arg($dateExpr)]);
return new MethodCall($staticCall, 'format', [new Arg($format)]);
}
private function createCarbonFromTimestamp(Expr $timestampExpr, Expr $format): MethodCall
{
$staticCall = new StaticCall(new FullyQualified('Carbon\Carbon'), 'createFromTimestamp', [new Arg($timestampExpr)]);
return new MethodCall($staticCall, 'format', [new Arg($format)]);
}
/**
* @param array{unit: string, value: int} $timeUnit
*/
private function createCarbonSubtract(array $timeUnit): MethodCall
{
$staticCall = new StaticCall(new FullyQualified('Carbon\Carbon'), 'now');
$methodName = 'sub' . ucfirst($timeUnit['unit']);
$methodCall = new MethodCall($staticCall, $methodName, [new Arg(new Int_($timeUnit['value']))]);
return new MethodCall($methodCall, 'getTimestamp');
}
/**
* @return array{unit: string, value: int}|null
*/
private function detectTimeUnit(Expr $expr): ?array
{
$product = $this->calculateProduct($expr);
if ($product === null) {
return null;
}
foreach (self::TIME_UNITS as [$unit, $seconds]) {
if ($product % $seconds === 0) {
return ['unit' => (string) $unit, 'value' => (int) ($product / $seconds)];
}
}
return null;
}
/**
* @return float|int|null
*/
private function calculateProduct(Expr $expr)
{
if ($expr instanceof Int_) {
return $expr->value;
}
if (!$expr instanceof Mul) {
return null;
}
$multipliers = $this->extractMultipliers($expr);
if ($multipliers === []) {
return null;
}
return array_product($multipliers);
}
/**
* @return int[]
*/
private function extractMultipliers(Node $node): array
{
$multipliers = [];
if (!$node instanceof Mul) {
return $multipliers;
}
if ($node->left instanceof Int_) {
$multipliers[] = $node->left->value;
} elseif ($node->left instanceof Mul) {
$multipliers = array_merge($multipliers, $this->extractMultipliers($node->left));
}
if ($node->right instanceof Int_) {
$multipliers[] = $node->right->value;
} elseif ($node->right instanceof Mul) {
$multipliers = array_merge($multipliers, $this->extractMultipliers($node->right));
}
return $multipliers;
}
}
@@ -1,69 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Carbon\Rector\FuncCall;
use PhpParser\Node;
use PhpParser\Node\Expr\ArrowFunction;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Name\FullyQualified;
use Rector\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\Carbon\Rector\FuncCall\TimeFuncCallToCarbonRector\TimeFuncCallToCarbonRectorTest
*/
final class TimeFuncCallToCarbonRector extends AbstractRector
{
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Convert `time()` function call to `Carbon::now()->getTimestamp()`', [new CodeSample(<<<'CODE_SAMPLE'
class SomeClass
{
public function run()
{
$time = time();
}
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
class SomeClass
{
public function run()
{
$time = \Carbon\Carbon::now()->getTimestamp();
}
}
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [FuncCall::class];
}
/**
* @param FuncCall $node
*/
public function refactor(Node $node): ?Node
{
if (!$this->isName($node->name, 'time')) {
return null;
}
$firstClassCallable = $node->isFirstClassCallable();
if (!$firstClassCallable && count($node->getArgs()) !== 0) {
return null;
}
// create now and format()
$nowStaticCall = new StaticCall(new FullyQualified('Carbon\Carbon'), 'now');
$methodCall = new MethodCall($nowStaticCall, 'getTimestamp');
if ($firstClassCallable) {
return new ArrowFunction(['static' => \true, 'expr' => $methodCall]);
}
return $methodCall;
}
}
@@ -1,93 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Carbon\Rector\MethodCall;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Name;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Scalar\String_;
use Rector\Carbon\NodeFactory\CarbonCallFactory;
use Rector\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Tests\Carbon\Rector\MethodCall\DateTimeMethodCallToCarbonRector\DateTimeMethodCallToCarbonRectorTest
*/
final class DateTimeMethodCallToCarbonRector extends AbstractRector
{
/**
* @readonly
*/
private CarbonCallFactory $carbonCallFactory;
public function __construct(CarbonCallFactory $carbonCallFactory)
{
$this->carbonCallFactory = $carbonCallFactory;
}
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Convert `new DateTime()` with a method call to `Carbon::*()`', [new CodeSample(<<<'CODE_SAMPLE'
class SomeClass
{
public function run()
{
$date = (new \DateTime('today +20 day'))->format('Y-m-d');
}
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
class SomeClass
{
public function run()
{
$date = \Carbon\Carbon::today()->addDays(20)->format('Y-m-d')
}
}
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [MethodCall::class];
}
/**
* @param MethodCall $node
*/
public function refactor(Node $node): ?Node
{
if (!$node->var instanceof New_) {
return null;
}
$new = $node->var;
if (!$new->class instanceof Name) {
return null;
}
if (!$this->isName($new->class, 'DateTime') && !$this->isName($new->class, 'DateTimeImmutable')) {
return null;
}
if ($new->isFirstClassCallable()) {
return null;
}
if (count($new->getArgs()) !== 1) {
// @todo handle in separate static call
return null;
}
$firstArg = $new->getArgs()[0];
if (!$firstArg->value instanceof String_) {
return null;
}
if ($this->isName($new->class, 'DateTime')) {
$carbonFullyQualified = new FullyQualified('Carbon\Carbon');
} else {
$carbonFullyQualified = new FullyQualified('Carbon\CarbonImmutable');
}
$carbonCall = $this->carbonCallFactory->createFromDateTimeString($carbonFullyQualified, $firstArg->value);
$node->var = $carbonCall;
return $node;
}
}

Some files were not shown because too many files have changed in this diff Show More