Add custom rector rule for yoda conditions

This commit is contained in:
David Stone
2025-02-09 00:21:40 -07:00
parent be0ab98895
commit 07a69d33e5
7 changed files with 167 additions and 29 deletions

View File

@ -17,10 +17,12 @@
"license": [
"GPL-3.0-or-later"
],
"autoload": {
"classmap": ["inc"]
},
"type": "wordpress-plugin",
"autoload": {
"classmap": [
"inc"
]
},
"type": "wordpress-plugin",
"require": {
"php": ">=7.4.1",
"automattic/jetpack-autoloader": "^5.0.0",
@ -62,9 +64,9 @@
"phpstan/extension-installer": "^1.1"
},
"config": {
"platform": {
"php": "7.4.1"
},
"platform": {
"php": "7.4.1"
},
"allow-plugins": {
"composer/installers": true,
"dealerdirect/phpcodesniffer-composer-installer": true,
@ -95,7 +97,9 @@
},
"extra": {
"installer-paths": {
"vendor/woocommerce/{$name}/": ["type:wordpress-plugin"]
"vendor/woocommerce/{$name}/": [
"type:wordpress-plugin"
]
},
"patches": {
"jasny/sso": [
@ -107,7 +111,13 @@
]
}
},
"scripts": {
"post-update-cmd": "cd vendor/mpdf/mpdf/ttfonts && rm -f AboriginalSansREGULAR.ttf Aegean.otf Aegyptus.otf Akkadian.otf ayar.ttf damase_v.2.ttf DBSILBR.ttf DejaVuSerif.ttf Dhyana-Regular.ttf DejaVuSansMono-Oblique.ttf DejaVuSerif-BoldItalic.ttf DhyanaOFL.txt DejaVuSerifCondensed-BoldItalic.ttf DejaVuSansMono-Bold.ttf DejaVuSerif-Italic.ttf DejaVuSansMono.ttf DejaVuSansMono-BoldOblique.ttf DejaVuSerif-Bold.ttf Dhyana-Bold.ttf DejaVuSerifCondensed-Italic.ttf DejaVuSansCondensed-BoldOblique.ttf DejaVuSansCondensed-Oblique.ttf DejaVuSans-Oblique.ttf DejaVuSans-BoldOblique.ttf DejaVuSans-Bold.ttf DejaVuSans.ttf FreeMonoBoldOblique.ttf FreeMonoOblique.ttf FreeSans.ttf FreeSansBold.ttf FreeSansBoldOblique.ttf FreeSansOblique.ttf FreeSerif.ttf FreeSerifBold.ttf FreeSerifBoldItalic.ttf FreeSerifItalic.ttf Garuda.ttf Garuda-Bold.ttf Garuda-BoldOblique.ttf Garuda-Oblique.ttf GNUFreeFontinfo.txt Jomolhari.ttf Jomolhari-OFL.txt kaputaunicode.ttf KhmerOFL.txt KhmerOS.ttf lannaalif-v1-03.ttf 'Lateef font OFL.txt' LateefRegOT.ttf Lohit-Kannada.ttf LohitKannadaOFL.txt ocrb10.ttf ocrbinfo.txt Padauk-book.ttf Pothana2000.ttf Quivira.otf Sun-ExtA.ttf Sun-ExtB.ttf SundaneseUnicode-1.0.5.ttf SyrCOMEdessa.otf SyrCOMEdessa_license.txt TaameyDavidCLM-LICENSE.txt TaameyDavidCLM-Medium.ttf TaiHeritagePro.ttf Tharlon-Regular.ttf TharlonOFL.txt UnBatang_0613.ttf Uthman.otf 'XB Riyaz.ttf' 'XB RiyazBd.ttf' 'XB RiyazBdIt.ttf' 'XB RiyazIt.ttf' 'XW Zar Font Info.txt' ZawgyiOne.ttf Abyssinica_SIL.ttf"
}
}
"scripts": {
"post-update-cmd": "cd vendor/mpdf/mpdf/ttfonts && rm -f AboriginalSansREGULAR.ttf Aegean.otf Aegyptus.otf Akkadian.otf ayar.ttf damase_v.2.ttf DBSILBR.ttf DejaVuSerif.ttf Dhyana-Regular.ttf DejaVuSansMono-Oblique.ttf DejaVuSerif-BoldItalic.ttf DhyanaOFL.txt DejaVuSerifCondensed-BoldItalic.ttf DejaVuSansMono-Bold.ttf DejaVuSerif-Italic.ttf DejaVuSansMono.ttf DejaVuSansMono-BoldOblique.ttf DejaVuSerif-Bold.ttf Dhyana-Bold.ttf DejaVuSerifCondensed-Italic.ttf DejaVuSansCondensed-BoldOblique.ttf DejaVuSansCondensed-Oblique.ttf DejaVuSans-Oblique.ttf DejaVuSans-BoldOblique.ttf DejaVuSans-Bold.ttf DejaVuSans.ttf FreeMonoBoldOblique.ttf FreeMonoOblique.ttf FreeSans.ttf FreeSansBold.ttf FreeSansBoldOblique.ttf FreeSansOblique.ttf FreeSerif.ttf FreeSerifBold.ttf FreeSerifBoldItalic.ttf FreeSerifItalic.ttf Garuda.ttf Garuda-Bold.ttf Garuda-BoldOblique.ttf Garuda-Oblique.ttf GNUFreeFontinfo.txt Jomolhari.ttf Jomolhari-OFL.txt kaputaunicode.ttf KhmerOFL.txt KhmerOS.ttf lannaalif-v1-03.ttf 'Lateef font OFL.txt' LateefRegOT.ttf Lohit-Kannada.ttf LohitKannadaOFL.txt ocrb10.ttf ocrbinfo.txt Padauk-book.ttf Pothana2000.ttf Quivira.otf Sun-ExtA.ttf Sun-ExtB.ttf SundaneseUnicode-1.0.5.ttf SyrCOMEdessa.otf SyrCOMEdessa_license.txt TaameyDavidCLM-LICENSE.txt TaameyDavidCLM-Medium.ttf TaiHeritagePro.ttf Tharlon-Regular.ttf TharlonOFL.txt UnBatang_0613.ttf Uthman.otf 'XB Riyaz.ttf' 'XB RiyazBd.ttf' 'XB RiyazBdIt.ttf' 'XB RiyazIt.ttf' 'XW Zar Font Info.txt' ZawgyiOne.ttf Abyssinica_SIL.ttf"
},
"autoload-dev": {
"psr-4": {
"Utils\\Rector\\": "utils/rector/src",
"Utils\\Rector\\Tests\\": "utils/rector/tests"
}
}
}

View File

@ -1,18 +1,14 @@
<?xml version="1.0"?>
<phpunit
bootstrap="tests/bootstrap.php"
backupGlobals="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
>
<php>
<const name="WP_TESTS_MULTISITE" value="1" />
</php>
<testsuites>
<testsuite name="testing">
<directory suffix="Test.php">./tests/</directory>
</testsuite>
</testsuites>
<phpunit bootstrap="tests/bootstrap.php" backupGlobals="false" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true">
<php>
<const name="WP_TESTS_MULTISITE" value="1"/>
</php>
<testsuites>
<testsuite name="testing">
<directory suffix="Test.php">./tests/</directory>
</testsuite>
<testsuite name="rector">
<directory>utils/rector/tests</directory>
</testsuite>
</testsuites>
</phpunit>

View File

@ -19,8 +19,10 @@ return RectorConfig::configure()
->withSkipPath(__DIR__ . '/vendor',)
->withImportNames(false)
->withPhpSets()
->withCodeQualityLevel(15)
->withCodingStyleLevel(5)
->withRules(
[
AddVoidReturnTypeWhereNoReturnRector::class,
\Utils\Rector\Rector\YodaConditionsRector::class,
]
);

View File

@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace Utils\Rector\Rector;
use PhpParser\Node;
use Rector\Rector\AbstractRector;
use PhpParser\Node\Expr\BinaryOp\Equal;
use PhpParser\Node\Expr\BinaryOp\Identical;
use PhpParser\Node\Expr\BinaryOp\NotIdentical;
use PhpParser\Node\Expr\BinaryOp\NotEqual;
use PhpParser\Node\Scalar;
use PhpParser\Node\Expr\ConstFetch;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
/**
* @see \Rector\Tests\TypeDeclaration\Rector\YodaConditionsRector\YodaConditionsRectorTest
*/
final class YodaConditionsRector extends AbstractRector
{
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes(): array
{
return [Equal::class, NotEqual::class, Identical::class, NotIdentical::class];
}
/**
* @param \PhpParser\Node\Stmt\Class_ $node
*/
public function refactor(Node $node): ?Node
{
// Ensure the left operand is not a constant
if ($node->left instanceof Node\Expr\Variable && (! $node->right instanceof Node\Expr\Variable)) {
// Swap the left and right operands
$this->mirrorComments($node->right, $node->left);
[$node->left, $node->right] = [$node->right, $node->left];
}
return $node;
}
}

View File

@ -0,0 +1,49 @@
<?php
namespace Rector\Tests\TypeDeclaration\Rector\YodaConditionsRector\Fixture;
const A_CONST = 'x';
$a = 'x';
if ($a === 'x') {
$a = 'xx';
}
if ($a === null) {
$a = 'xx';
}
if ($a == false) {
$a = 'xx';
}
if ($a === A_CONST) {
$a = 'xx';
}
if (strlen($a) === 1) {
$a = 'xx';
}
if ($a === 0 || $a === rand()) {
return $a;
}
?>
-----
<?php
namespace Rector\Tests\TypeDeclaration\Rector\YodaConditionsRector\Fixture;
const A_CONST = 'x';
$a = 'x';
if ('x' === $a) {
$a = 'xx';
}
if (null === $a) {
$a = 'xx';
}
if (false == $a) {
$a = 'xx';
}
if (A_CONST === $a) {
$a = 'xx';
}
if (strlen($a) === 1) {
$a = 'xx';
}
if (0 === $a || rand() === $a) {
return $a;
}
?>

View File

@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
namespace Rector\Tests\TypeDeclaration\Rector\YodaConditionsRector;
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
final class YodaConditionsRectorTest extends AbstractRectorTestCase
{
/**
* @dataProvider provideData()
*/
public function test(string $filePath): void
{
$this->doTestFile($filePath);
}
public static function provideData(): \Iterator
{
return self::yieldFilesFromDirectory(__DIR__ . '/Fixture');
}
public function provideConfigFilePath(): string
{
return __DIR__ . '/config/configured_rule.php';
}
}

View File

@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
use Rector\Config\RectorConfig;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(\Utils\Rector\Rector\YodaConditionsRector::class);
};