From 0c455e4ae10f1b1ed2427f064619f2a96413e9dd Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Tue, 5 Nov 2019 11:25:43 +0100 Subject: [PATCH 1/4] remove strlen() from Nette\Utils\String strict method --- ...trlenFunctionToNetteUtilsStringsRector.php | 7 ++--- .../StrposToStringsContainsRector.php | 4 +-- .../Fixture/strlen.php.inc | 27 ------------------- ...nFunctionToNetteUtilsStringsRectorTest.php | 1 - ...PHPUnitStaticToKernelTestCaseGetRector.php | 5 ++-- rector-ci.yaml | 1 + 6 files changed, 9 insertions(+), 36 deletions(-) delete mode 100644 packages/Nette/tests/Rector/FuncCall/SubstrStrlenFunctionToNetteUtilsStringsRector/Fixture/strlen.php.inc diff --git a/packages/Nette/src/Rector/FuncCall/SubstrStrlenFunctionToNetteUtilsStringsRector.php b/packages/Nette/src/Rector/FuncCall/SubstrStrlenFunctionToNetteUtilsStringsRector.php index 5fb34e1e821e..9c17350725cf 100644 --- a/packages/Nette/src/Rector/FuncCall/SubstrStrlenFunctionToNetteUtilsStringsRector.php +++ b/packages/Nette/src/Rector/FuncCall/SubstrStrlenFunctionToNetteUtilsStringsRector.php @@ -21,7 +21,6 @@ final class SubstrStrlenFunctionToNetteUtilsStringsRector extends AbstractRector */ private $functionToStaticMethod = [ 'substr' => 'substring', - 'strlen' => 'length', ]; public function getDefinition(): RectorDefinition @@ -65,9 +64,11 @@ public function getNodeTypes(): array public function refactor(Node $node): ?Node { foreach ($this->functionToStaticMethod as $function => $staticMethod) { - if ($this->isName($node, $function)) { - return $this->createStaticCall('Nette\Utils\Strings', $staticMethod, $node->args); + if (! $this->isName($node, $function)) { + continue; } + + return $this->createStaticCall('Nette\Utils\Strings', $staticMethod, $node->args); } return null; diff --git a/packages/Nette/src/Rector/NotIdentical/StrposToStringsContainsRector.php b/packages/Nette/src/Rector/NotIdentical/StrposToStringsContainsRector.php index 69686680b6c4..9f3a0b6e235d 100644 --- a/packages/Nette/src/Rector/NotIdentical/StrposToStringsContainsRector.php +++ b/packages/Nette/src/Rector/NotIdentical/StrposToStringsContainsRector.php @@ -10,8 +10,6 @@ use PhpParser\Node\Expr\BinaryOp\NotIdentical; use PhpParser\Node\Expr\BooleanNot; use PhpParser\Node\Expr\FuncCall; -use PhpParser\Node\Expr\StaticCall; -use PhpParser\Node\Name\FullyQualified; use Rector\Rector\AbstractRector; use Rector\RectorDefinition\CodeSample; use Rector\RectorDefinition\RectorDefinition; @@ -74,7 +72,7 @@ public function refactor(Node $node): ?Node return null; } - $containsStaticCall = new StaticCall(new FullyQualified('Nette\Utils\Strings'), 'contains'); + $containsStaticCall = $this->createStaticCall('Nette\Utils\Strings', 'contains'); $containsStaticCall->args[0] = $strpos->args[0]; $containsStaticCall->args[1] = $strpos->args[1]; diff --git a/packages/Nette/tests/Rector/FuncCall/SubstrStrlenFunctionToNetteUtilsStringsRector/Fixture/strlen.php.inc b/packages/Nette/tests/Rector/FuncCall/SubstrStrlenFunctionToNetteUtilsStringsRector/Fixture/strlen.php.inc deleted file mode 100644 index 25a8cc2b3afb..000000000000 --- a/packages/Nette/tests/Rector/FuncCall/SubstrStrlenFunctionToNetteUtilsStringsRector/Fixture/strlen.php.inc +++ /dev/null @@ -1,27 +0,0 @@ - ------ - diff --git a/packages/Nette/tests/Rector/FuncCall/SubstrStrlenFunctionToNetteUtilsStringsRector/SubstrStrlenFunctionToNetteUtilsStringsRectorTest.php b/packages/Nette/tests/Rector/FuncCall/SubstrStrlenFunctionToNetteUtilsStringsRector/SubstrStrlenFunctionToNetteUtilsStringsRectorTest.php index 670f8ba32c06..3edba8a51ca5 100644 --- a/packages/Nette/tests/Rector/FuncCall/SubstrStrlenFunctionToNetteUtilsStringsRector/SubstrStrlenFunctionToNetteUtilsStringsRectorTest.php +++ b/packages/Nette/tests/Rector/FuncCall/SubstrStrlenFunctionToNetteUtilsStringsRector/SubstrStrlenFunctionToNetteUtilsStringsRectorTest.php @@ -21,7 +21,6 @@ public function test(string $file): void public function provideDataForTest(): Iterator { yield [__DIR__ . '/Fixture/substr.php.inc']; - yield [__DIR__ . '/Fixture/strlen.php.inc']; } protected function getRectorClass(): string diff --git a/packages/RemovingStatic/src/Rector/Class_/PHPUnitStaticToKernelTestCaseGetRector.php b/packages/RemovingStatic/src/Rector/Class_/PHPUnitStaticToKernelTestCaseGetRector.php index 9a78b382d567..e4e34ed75ff9 100644 --- a/packages/RemovingStatic/src/Rector/Class_/PHPUnitStaticToKernelTestCaseGetRector.php +++ b/packages/RemovingStatic/src/Rector/Class_/PHPUnitStaticToKernelTestCaseGetRector.php @@ -103,7 +103,7 @@ final class SomeTestCase extends KernelTestCase * @var EntityFactory */ private $entityFactory; - + protected function setUp(): void { parent::setUp(); @@ -285,7 +285,8 @@ private function addNewPropertiesToClass(Class_ $class, array $newProperties): C private function createParentSetUpStaticCall(): Expression { - return new Expression(new StaticCall(new Name('parent'), 'setUp')); + $parentSetupStaticCall = $this->createStaticCall('parent', 'setUp'); + return new Expression($parentSetupStaticCall); } private function createContainerGetTypeToPropertyAssign(ObjectType $objectType): Expression diff --git a/rector-ci.yaml b/rector-ci.yaml index 4cfcf00e00eb..93da7708e3a4 100644 --- a/rector-ci.yaml +++ b/rector-ci.yaml @@ -2,6 +2,7 @@ parameters: sets: - "code-quality" - "dead-code" + - "nette-utils-code-quality" exclude_paths: - "/Fixture/" From 56d9059357ebf628274b1901b5676875d078cc39 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Tue, 5 Nov 2019 11:29:20 +0100 Subject: [PATCH 2/4] use Fixture name constantly --- .../{fixtures => Fixture}/anonymousClass.php.inc | 0 .../{fixtures => Fixture}/simple.php.inc | 0 .../FunctionMethodAndClassNodeVisitorTest.php | 4 ++-- 3 files changed, 2 insertions(+), 2 deletions(-) rename packages/NodeTypeResolver/tests/NodeVisitor/FunctionMethodAndClassNodeVisitor/{fixtures => Fixture}/anonymousClass.php.inc (100%) rename packages/NodeTypeResolver/tests/NodeVisitor/FunctionMethodAndClassNodeVisitor/{fixtures => Fixture}/simple.php.inc (100%) diff --git a/packages/NodeTypeResolver/tests/NodeVisitor/FunctionMethodAndClassNodeVisitor/fixtures/anonymousClass.php.inc b/packages/NodeTypeResolver/tests/NodeVisitor/FunctionMethodAndClassNodeVisitor/Fixture/anonymousClass.php.inc similarity index 100% rename from packages/NodeTypeResolver/tests/NodeVisitor/FunctionMethodAndClassNodeVisitor/fixtures/anonymousClass.php.inc rename to packages/NodeTypeResolver/tests/NodeVisitor/FunctionMethodAndClassNodeVisitor/Fixture/anonymousClass.php.inc diff --git a/packages/NodeTypeResolver/tests/NodeVisitor/FunctionMethodAndClassNodeVisitor/fixtures/simple.php.inc b/packages/NodeTypeResolver/tests/NodeVisitor/FunctionMethodAndClassNodeVisitor/Fixture/simple.php.inc similarity index 100% rename from packages/NodeTypeResolver/tests/NodeVisitor/FunctionMethodAndClassNodeVisitor/fixtures/simple.php.inc rename to packages/NodeTypeResolver/tests/NodeVisitor/FunctionMethodAndClassNodeVisitor/Fixture/simple.php.inc diff --git a/packages/NodeTypeResolver/tests/NodeVisitor/FunctionMethodAndClassNodeVisitor/FunctionMethodAndClassNodeVisitorTest.php b/packages/NodeTypeResolver/tests/NodeVisitor/FunctionMethodAndClassNodeVisitor/FunctionMethodAndClassNodeVisitorTest.php index 681447afc7e5..92b4572f5f27 100644 --- a/packages/NodeTypeResolver/tests/NodeVisitor/FunctionMethodAndClassNodeVisitor/FunctionMethodAndClassNodeVisitorTest.php +++ b/packages/NodeTypeResolver/tests/NodeVisitor/FunctionMethodAndClassNodeVisitor/FunctionMethodAndClassNodeVisitorTest.php @@ -16,8 +16,8 @@ final class FunctionMethodAndClassNodeVisitorTest extends AbstractNodeVisitorTes { public function provideDataForTest(): Iterator { - yield [__DIR__ . '/fixtures/simple.php.inc']; - yield [__DIR__ . '/fixtures/anonymousClass.php.inc']; + yield [__DIR__ . '/Fixture/simple.php.inc']; + yield [__DIR__ . '/Fixture/anonymousClass.php.inc']; } /** From 2fe6f20ea5bcb0132d2f4ca179f0ef1f789e6a60 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Tue, 5 Nov 2019 11:31:54 +0100 Subject: [PATCH 3/4] use Nette\Utils --- config/set/nette/nette-utils-code-quality.yaml | 1 + .../VersionCompareFuncCallToConstantRector.php | 3 ++- .../EntityAliasToClassConstantReferenceRector.php | 3 ++- packages/Php70/src/EregToPcreTransformer.php | 10 +++++----- src/Testing/PHPUnit/AbstractNodeVisitorTestCase.php | 3 ++- .../Node/BetterNodeFinder/BetterNodeFinderTest.php | 3 ++- 6 files changed, 14 insertions(+), 9 deletions(-) diff --git a/config/set/nette/nette-utils-code-quality.yaml b/config/set/nette/nette-utils-code-quality.yaml index d655037153bd..2e5767c4d3c6 100644 --- a/config/set/nette/nette-utils-code-quality.yaml +++ b/config/set/nette/nette-utils-code-quality.yaml @@ -5,6 +5,7 @@ services: file_get_contents: ['Nette\Utils\FileSystem', 'read'] unlink: ['Nette\Utils\FileSystem', 'delete'] rmdir: ['Nette\Utils\FileSystem', 'delete'] + file_put_contents: ['Nette\Utils\FileSystem', 'write'] # strings Rector\Nette\Rector\NotIdentical\StrposToStringsContainsRector: ~ diff --git a/packages/CodingStyle/src/Rector/FuncCall/VersionCompareFuncCallToConstantRector.php b/packages/CodingStyle/src/Rector/FuncCall/VersionCompareFuncCallToConstantRector.php index b766b600ffcb..a936459dbd3d 100644 --- a/packages/CodingStyle/src/Rector/FuncCall/VersionCompareFuncCallToConstantRector.php +++ b/packages/CodingStyle/src/Rector/FuncCall/VersionCompareFuncCallToConstantRector.php @@ -4,6 +4,7 @@ namespace Rector\CodingStyle\Rector\FuncCall; +use Nette\Utils\Strings; use PhpParser\Node; use PhpParser\Node\Expr; use PhpParser\Node\Expr\BinaryOp\Greater; @@ -131,7 +132,7 @@ private function getVersionNumberFormVersionString(Expr $expr): LNumber throw new ShouldNotHappenException(); } - if (! preg_match('#^\d+\.\d+\.\d+$#', $expr->value)) { + if (! Strings::match($expr->value, '#^\d+\.\d+\.\d+$#')) { throw new ShouldNotHappenException(); } diff --git a/packages/Doctrine/src/Rector/MethodCall/EntityAliasToClassConstantReferenceRector.php b/packages/Doctrine/src/Rector/MethodCall/EntityAliasToClassConstantReferenceRector.php index b7e7fd12dbaf..84c5f7624ecb 100644 --- a/packages/Doctrine/src/Rector/MethodCall/EntityAliasToClassConstantReferenceRector.php +++ b/packages/Doctrine/src/Rector/MethodCall/EntityAliasToClassConstantReferenceRector.php @@ -5,6 +5,7 @@ namespace Rector\Doctrine\Rector\MethodCall; use Doctrine\ORM\EntityManagerInterface; +use Nette\Utils\Strings; use PhpParser\Node; use PhpParser\Node\Expr\MethodCall; use PhpParser\Node\Scalar\String_; @@ -103,7 +104,7 @@ private function convertAliasToFqn(string $name): string private function isAlias(string $name): bool { - return strpos($name, ':') !== false; + return Strings::contains($name, ':'); } private function hasAlias(string $name): bool diff --git a/packages/Php70/src/EregToPcreTransformer.php b/packages/Php70/src/EregToPcreTransformer.php index 5dd6c97fab3c..ef3821f6357d 100644 --- a/packages/Php70/src/EregToPcreTransformer.php +++ b/packages/Php70/src/EregToPcreTransformer.php @@ -99,12 +99,12 @@ private function _ere2pcre(string $s, int $i): array $start = true; do { if ($s[$i] === '[' && - $i + 1 < $l && strpos('.=:', $s[$i + 1]) !== false) { + $i + 1 < $l && Strings::contains('.=:', $s[$i + 1])) { $ii = strpos($s, ']', $i); if ($ii === false) { throw new InvalidEregException('"[" does not have a matching "]"'); } - $ccls = substr($s, $i + 1, $ii - ($i + 1)); + $ccls = Strings::substring($s, $i + 1, $ii - ($i + 1)); $cclsmap = [ ':alnum:' => '[:alnum:]', ':alpha:' => '[:alpha:]', @@ -158,7 +158,7 @@ private function _ere2pcre(string $s, int $i): array } elseif ($c === '*' || $c === '+' || $c === '?') { throw new InvalidEregException('unescaped metacharacter "' . $c . '"'); } elseif ($c === '{') { - if ($i + 1 < $l && strpos('0123456789', $s[$i + 1]) !== false) { + if ($i + 1 < $l && Strings::contains('0123456789', $s[$i + 1])) { $r[$rr] .= '\{'; } else { throw new InvalidEregException('unescaped metacharacter "' . $c . '"'); @@ -199,7 +199,7 @@ private function _ere2pcre(string $s, int $i): array if ($ii === false) { throw new InvalidEregException('"{" does not have a matching "}"'); } - $bound = substr($s, $i + 1, $ii - ($i + 1)); + $bound = Strings::substring($s, $i + 1, $ii - ($i + 1)); if (! preg_match( '/^(\d|[1-9]\d|1\d\d| 2[0-4]\d|25[0-5]) @@ -234,7 +234,7 @@ private function _ere2pcre_escape(string $c): string { if ($c === "\0") { throw new InvalidEregException('a literal null byte in the regex'); - } elseif (strpos('\^$.[]|()?*+{}-/', $c) !== false) { + } elseif (Strings::contains('\^$.[]|()?*+{}-/', $c)) { return '\\' . $c; } diff --git a/src/Testing/PHPUnit/AbstractNodeVisitorTestCase.php b/src/Testing/PHPUnit/AbstractNodeVisitorTestCase.php index e34f660f3849..7f5199c6e4c2 100644 --- a/src/Testing/PHPUnit/AbstractNodeVisitorTestCase.php +++ b/src/Testing/PHPUnit/AbstractNodeVisitorTestCase.php @@ -4,6 +4,7 @@ namespace Rector\Testing\PHPUnit; +use Nette\Utils\FileSystem; use PhpParser\Node; use PhpParser\NodeDumper; use Rector\HttpKernel\RectorKernel; @@ -79,7 +80,7 @@ protected function doTestFile(string $file): void $dumpedNodes = $this->nodeDumper->dump($nodes); if (getenv('UPDATE_FIXTURE')) { - file_put_contents($file, file_get_contents($originalFile) . "-----\n" . $dumpedNodes); + FileSystem::write($file, FileSystem::read($originalFile) . "-----\n" . $dumpedNodes); } else { $this->assertSame(trim($smartFileInfo2->getContents()), $dumpedNodes, 'Caused by ' . $file); } diff --git a/tests/PhpParser/Node/BetterNodeFinder/BetterNodeFinderTest.php b/tests/PhpParser/Node/BetterNodeFinder/BetterNodeFinderTest.php index ef096b52c550..ac1d40f0d46f 100644 --- a/tests/PhpParser/Node/BetterNodeFinder/BetterNodeFinderTest.php +++ b/tests/PhpParser/Node/BetterNodeFinder/BetterNodeFinderTest.php @@ -4,6 +4,7 @@ namespace Rector\Tests\PhpParser\Node\BetterNodeFinder; +use Nette\Utils\FileSystem; use PhpParser\Node; use PhpParser\Node\Expr\Array_; use PhpParser\Node\Expr\Variable; @@ -63,7 +64,7 @@ public function testFindMissingFirstAncestorInstanceOf(): void private function createNodesFromFile(string $filePath): array { $phpParser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7); - $nodes = $phpParser->parse(file_get_contents($filePath)); + $nodes = $phpParser->parse(FileSystem::read($filePath)); if ($nodes === null) { return []; } From eef3489d4325bec4b0aad02e32bf319ef0db244c Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Tue, 5 Nov 2019 12:25:19 +0100 Subject: [PATCH 4/4] cover PregFunctionToNetteUtilsStringsRector to identical --- README.md | 2 +- .../PregFunctionToNetteUtilsStringsRector.php | 119 +++++++++++++----- .../Fixture/preg_match_identical_one.php.inc | 37 ++++++ ...g_match_identical_one_with_matches.php.inc | 33 +++++ ...gFunctionToNetteUtilsStringsRectorTest.php | 2 + packages/Php70/src/EregToPcreTransformer.php | 12 +- .../Check/ExcludeByDocBlockExclusionCheck.php | 3 +- 7 files changed, 167 insertions(+), 41 deletions(-) create mode 100644 packages/Nette/tests/Rector/FuncCall/PregFunctionToNetteUtilsStringsRector/Fixture/preg_match_identical_one.php.inc create mode 100644 packages/Nette/tests/Rector/FuncCall/PregFunctionToNetteUtilsStringsRector/Fixture/preg_match_identical_one_with_matches.php.inc diff --git a/README.md b/README.md index e4c3d3c00ba9..5504be8b13f7 100644 --- a/README.md +++ b/README.md @@ -155,7 +155,7 @@ run them by default: ```yaml # rector.yaml imports: - - { resource: 'vendor/rector/rector/config/set/code-quality/*.yaml' } + - { resource: 'vendor/rector/rector/config/set/code-quality/code-quality.yaml' } - { resource: 'vendor/rector/rector/config/set/php/php71.yaml' } - { resource: 'vendor/rector/rector/config/set/php/php72.yaml' } - { resource: 'vendor/rector/rector/config/set/php/php73.yaml' } diff --git a/packages/Nette/src/Rector/FuncCall/PregFunctionToNetteUtilsStringsRector.php b/packages/Nette/src/Rector/FuncCall/PregFunctionToNetteUtilsStringsRector.php index 83d22ec1c6b4..171572c013ef 100644 --- a/packages/Nette/src/Rector/FuncCall/PregFunctionToNetteUtilsStringsRector.php +++ b/packages/Nette/src/Rector/FuncCall/PregFunctionToNetteUtilsStringsRector.php @@ -6,10 +6,14 @@ use PhpParser\Node; use PhpParser\Node\Arg; +use PhpParser\Node\Expr; use PhpParser\Node\Expr\Assign; +use PhpParser\Node\Expr\BinaryOp\Identical; +use PhpParser\Node\Expr\Cast\Bool_; use PhpParser\Node\Expr\FuncCall; use PhpParser\Node\Expr\StaticCall; use PhpParser\Node\Name; +use PhpParser\Node\Stmt\Return_; use Rector\NodeTypeResolver\Node\AttributeKey; use Rector\Rector\AbstractRector; use Rector\RectorDefinition\CodeSample; @@ -17,6 +21,7 @@ /** * @see https://www.tomasvotruba.cz/blog/2019/02/07/what-i-learned-by-using-thecodingmachine-safe/#is-there-a-better-way + * * @see \Rector\Nette\Tests\Rector\FuncCall\PregFunctionToNetteUtilsStringsRector\PregFunctionToNetteUtilsStringsRectorTest */ final class PregFunctionToNetteUtilsStringsRector extends AbstractRector @@ -42,7 +47,7 @@ class SomeClass public function run() { $content = 'Hi my name is Tom'; - preg_match('#Hi#', $content); + preg_match('#Hi#', $content, $matches); } } PHP @@ -53,7 +58,7 @@ class SomeClass public function run() { $content = 'Hi my name is Tom'; - \Nette\Utils\Strings::match($content, '#Hi#'); + $matches = \Nette\Utils\Strings::match($content, '#Hi#'); } } PHP @@ -66,23 +71,71 @@ public function run() */ public function getNodeTypes(): array { - return [FuncCall::class]; + return [FuncCall::class, Identical::class]; } /** - * @param FuncCall $node + * @param FuncCall|Identical $node */ public function refactor(Node $node): ?Node { - if (! $this->isNames($node, array_keys($this->functionNameToMethodName))) { + if ($node instanceof Identical) { + return $this->refactorIdentical($node); + } + + return $this->refactorFuncCall($node); + } + + private function createMatchStaticCall(FuncCall $funcCall, string $methodName): StaticCall + { + $args = []; + + if ($methodName === 'replace') { + $args[] = $funcCall->args[2]; + $args[] = $funcCall->args[0]; + $args[] = $funcCall->args[1]; + } else { + $args[] = $funcCall->args[1]; + $args[] = $funcCall->args[0]; + } + + return $this->createStaticCall('Nette\Utils\Strings', $methodName, $args); + } + + /** + * @return FuncCall|StaticCall + */ + private function processSplit(FuncCall $funcCall, StaticCall $matchStaticCall): Expr + { + if (isset($funcCall->args[2])) { + if ($this->isValue($funcCall->args[2]->value, -1)) { + if (isset($funcCall->args[3])) { + $matchStaticCall->args[] = $funcCall->args[3]; + } + + return $matchStaticCall; + } + + return $funcCall; + } + + return $matchStaticCall; + } + + /** + * @return FuncCall|StaticCall|Assign|null + */ + private function refactorFuncCall(FuncCall $funcCall): ?Expr + { + if (! $this->isNames($funcCall, array_keys($this->functionNameToMethodName))) { return null; } - $methodName = $this->functionNameToMethodName[$this->getName($node)]; - $matchStaticCall = $this->createMatchStaticCall($node, $methodName); + $methodName = $this->functionNameToMethodName[$this->getName($funcCall)]; + $matchStaticCall = $this->createMatchStaticCall($funcCall, $methodName); // skip assigns, might be used with different return value - $parentNode = $node->getAttribute(AttributeKey::PARENT_NODE); + $parentNode = $funcCall->getAttribute(AttributeKey::PARENT_NODE); if ($parentNode instanceof Assign) { if ($methodName === 'matchAll') { // use count @@ -90,7 +143,7 @@ public function refactor(Node $node): ?Node } if ($methodName === 'split') { - return $this->processSplit($node, $matchStaticCall); + return $this->processSplit($funcCall, $matchStaticCall); } if ($methodName === 'replace') { @@ -101,43 +154,43 @@ public function refactor(Node $node): ?Node } // assign - if (isset($node->args[2])) { - return new Assign($node->args[2]->value, $matchStaticCall); + if (isset($funcCall->args[2])) { + return new Assign($funcCall->args[2]->value, $matchStaticCall); } return $matchStaticCall; } - private function createMatchStaticCall(FuncCall $funcCall, string $methodName): StaticCall + private function refactorIdentical(Identical $identical): ?Bool_ { - $args = []; + $parentNode = $identical->getAttribute(AttributeKey::PARENT_NODE); - if ($methodName === 'replace') { - $args[] = $funcCall->args[2]; - $args[] = $funcCall->args[0]; - $args[] = $funcCall->args[1]; - } else { - $args[] = $funcCall->args[1]; - $args[] = $funcCall->args[0]; + if ($identical->left instanceof FuncCall) { + $refactoredFuncCall = $this->refactorFuncCall($identical->left); + if ($refactoredFuncCall !== null && $this->isValue($identical->right, 1)) { + return $this->createBoolCast($parentNode, $refactoredFuncCall); + } } - return $this->createStaticCall('Nette\Utils\Strings', $methodName, $args); + if ($identical->right instanceof FuncCall) { + $refactoredFuncCall = $this->refactorFuncCall($identical->right); + if ($refactoredFuncCall !== null && $this->isValue($identical->left, 1)) { + return new Bool_($refactoredFuncCall); + } + } + + return null; } - private function processSplit(FuncCall $funcCall, StaticCall $matchStaticCall): Node + /** + * @param FuncCall|StaticCall|Assign $refactoredFuncCall + */ + private function createBoolCast(?Node $parentNode, Node $refactoredFuncCall): Bool_ { - if (isset($funcCall->args[2])) { - if ($this->isValue($funcCall->args[2]->value, -1)) { - if (isset($funcCall->args[3])) { - $matchStaticCall->args[] = $funcCall->args[3]; - } - - return $matchStaticCall; - } - - return $funcCall; + if ($parentNode instanceof Return_ && $refactoredFuncCall instanceof Assign) { + $refactoredFuncCall = $refactoredFuncCall->expr; } - return $matchStaticCall; + return new Bool_($refactoredFuncCall); } } diff --git a/packages/Nette/tests/Rector/FuncCall/PregFunctionToNetteUtilsStringsRector/Fixture/preg_match_identical_one.php.inc b/packages/Nette/tests/Rector/FuncCall/PregFunctionToNetteUtilsStringsRector/Fixture/preg_match_identical_one.php.inc new file mode 100644 index 000000000000..f226ae215efd --- /dev/null +++ b/packages/Nette/tests/Rector/FuncCall/PregFunctionToNetteUtilsStringsRector/Fixture/preg_match_identical_one.php.inc @@ -0,0 +1,37 @@ + +----- + diff --git a/packages/Nette/tests/Rector/FuncCall/PregFunctionToNetteUtilsStringsRector/Fixture/preg_match_identical_one_with_matches.php.inc b/packages/Nette/tests/Rector/FuncCall/PregFunctionToNetteUtilsStringsRector/Fixture/preg_match_identical_one_with_matches.php.inc new file mode 100644 index 000000000000..1e338ee5e168 --- /dev/null +++ b/packages/Nette/tests/Rector/FuncCall/PregFunctionToNetteUtilsStringsRector/Fixture/preg_match_identical_one_with_matches.php.inc @@ -0,0 +1,33 @@ +matches = $matches; + + return $haveResults; + } +} + +?> +----- +matches = $matches; + + return $haveResults; + } +} + +?> diff --git a/packages/Nette/tests/Rector/FuncCall/PregFunctionToNetteUtilsStringsRector/PregFunctionToNetteUtilsStringsRectorTest.php b/packages/Nette/tests/Rector/FuncCall/PregFunctionToNetteUtilsStringsRector/PregFunctionToNetteUtilsStringsRectorTest.php index daa1f8a79689..ba1fbe0b98e2 100644 --- a/packages/Nette/tests/Rector/FuncCall/PregFunctionToNetteUtilsStringsRector/PregFunctionToNetteUtilsStringsRectorTest.php +++ b/packages/Nette/tests/Rector/FuncCall/PregFunctionToNetteUtilsStringsRector/PregFunctionToNetteUtilsStringsRectorTest.php @@ -25,6 +25,8 @@ public function provideDataForTest(): Iterator yield [__DIR__ . '/Fixture/preg_split.php.inc']; yield [__DIR__ . '/Fixture/preg_replace.php.inc']; yield [__DIR__ . '/Fixture/preg_replace_callback.php.inc']; + yield [__DIR__ . '/Fixture/preg_match_identical_one.php.inc']; + yield [__DIR__ . '/Fixture/preg_match_identical_one_with_matches.php.inc']; } protected function getRectorClass(): string diff --git a/packages/Php70/src/EregToPcreTransformer.php b/packages/Php70/src/EregToPcreTransformer.php index ef3821f6357d..92b0b70361eb 100644 --- a/packages/Php70/src/EregToPcreTransformer.php +++ b/packages/Php70/src/EregToPcreTransformer.php @@ -200,16 +200,16 @@ private function _ere2pcre(string $s, int $i): array throw new InvalidEregException('"{" does not have a matching "}"'); } $bound = Strings::substring($s, $i + 1, $ii - ($i + 1)); - if (! preg_match( - '/^(\d|[1-9]\d|1\d\d| + + $m = Strings::match($bound, '/^(\d|[1-9]\d|1\d\d| 2[0-4]\d|25[0-5]) (,(\d|[1-9]\d|1\d\d| - 2[0-4]\d|25[0-5])?)?$/x', - $bound, - $m - )) { + 2[0-4]\d|25[0-5])?)?$/x'); + + if (! $m) { throw new InvalidEregException('an invalid bound'); } + if (isset($m[3])) { if ($m[1] > $m[3]) { throw new InvalidEregException('an invalid bound'); diff --git a/src/Exclusion/Check/ExcludeByDocBlockExclusionCheck.php b/src/Exclusion/Check/ExcludeByDocBlockExclusionCheck.php index 7f78e68c825e..c894c3549c92 100644 --- a/src/Exclusion/Check/ExcludeByDocBlockExclusionCheck.php +++ b/src/Exclusion/Check/ExcludeByDocBlockExclusionCheck.php @@ -4,6 +4,7 @@ namespace Rector\Exclusion\Check; +use Nette\Utils\Strings; use PhpParser\Comment\Doc; use PhpParser\Node; use PhpParser\Node\Stmt; @@ -32,6 +33,6 @@ public function isNodeSkippedByRector(PhpRectorInterface $phpRector, Node $node) private function checkCommentForIgnore(PhpRectorInterface $phpRector, Doc $doc): bool { $regex = '#@noRector\s*\\\\?' . preg_quote(get_class($phpRector), '/') . '#i'; - return preg_match($regex, $doc->getText(), $matches) === 1; + return (bool) Strings::match($doc->getText(), $regex); } }