From 85682c412e09e21372044da9dda08b3f687a95b4 Mon Sep 17 00:00:00 2001 From: TomasVotruba Date: Wed, 6 May 2020 16:55:08 +0200 Subject: [PATCH 1/6] improve static removal test --- .../Fixture/fixture.php.inc | 63 ------------------- .../PassFactoryToEntityRectorTest.php | 22 ------- 2 files changed, 85 deletions(-) delete mode 100644 rules/removing-static/tests/Rector/Class_/PassFactoryToEntityRector/Fixture/fixture.php.inc diff --git a/rules/removing-static/tests/Rector/Class_/PassFactoryToEntityRector/Fixture/fixture.php.inc b/rules/removing-static/tests/Rector/Class_/PassFactoryToEntityRector/Fixture/fixture.php.inc deleted file mode 100644 index 5c7723071f0..00000000000 --- a/rules/removing-static/tests/Rector/Class_/PassFactoryToEntityRector/Fixture/fixture.php.inc +++ /dev/null @@ -1,63 +0,0 @@ - ------ -anotherClassFactory = $anotherClassFactory; - } - public function run() - { - return $this->anotherClassFactory->create(); - } -} - -class AnotherClass -{ - /** - * @var \Rector\RemovingStatic\Tests\Rector\Class_\PassFactoryToEntityRector\Source\TurnMeToService - */ - private $turnMeToService; - public function __construct(\Rector\RemovingStatic\Tests\Rector\Class_\PassFactoryToEntityRector\Source\TurnMeToService $turnMeToService) - { - $this->turnMeToService = $turnMeToService; - } - public function someFun() - { - return $this->turnMeToService->someStaticCall(); - } -} - -?> diff --git a/rules/removing-static/tests/Rector/Class_/PassFactoryToEntityRector/PassFactoryToEntityRectorTest.php b/rules/removing-static/tests/Rector/Class_/PassFactoryToEntityRector/PassFactoryToEntityRectorTest.php index f7954d2fec0..8b13442d7dc 100644 --- a/rules/removing-static/tests/Rector/Class_/PassFactoryToEntityRector/PassFactoryToEntityRectorTest.php +++ b/rules/removing-static/tests/Rector/Class_/PassFactoryToEntityRector/PassFactoryToEntityRectorTest.php @@ -19,23 +19,6 @@ final class PassFactoryToEntityRectorTest extends AbstractRectorTestCase { $this->doTestFile($file); - // test factory content - $this->assertFileExists($this->getTempPath() . '/AnotherClassFactory.php'); - $this->assertFileEquals( - __DIR__ . '/Source/ExpectedAnotherClassFactory.php', - $this->getTempPath() . '/AnotherClassFactory.php' - ); - } - - /** - * @dataProvider provideDataMultipleArguments() - */ - public function testMultipleArguments(string $file): void - { - $this->markTestSkipped('Conflicting with previous test() for unknown reason. Works well separately'); - - $this->doTestFile($file); - // test factory content $this->assertFileExists($this->getTempPath() . '/AnotherClassWithMoreArgumentsFactory.php'); $this->assertFileEquals( @@ -45,11 +28,6 @@ final class PassFactoryToEntityRectorTest extends AbstractRectorTestCase } public function provideData(): Iterator - { - return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture'); - } - - public function provideDataMultipleArguments(): Iterator { return $this->yieldFilesFromDirectory(__DIR__ . '/FixtureWithMultipleArguments'); } From af22fe379ef1c3a3dc40aa17ef23c49bf864cea8 Mon Sep 17 00:00:00 2001 From: TomasVotruba Date: Wed, 6 May 2020 13:17:03 +0200 Subject: [PATCH 2/6] quote tag keys --- .../src/PhpDocNode/AbstractTagValueNode.php | 13 ++++++++++++- .../Fixture/DoctrineColumn/QuotesInNestedArray.php | 2 +- .../TagValueNodeReprint/TagValueNodeReprintTest.php | 4 ---- .../PhpDocNode/PhpAttributePhpDocNodePrintTrait.php | 3 +++ 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/packages/better-php-doc-parser/src/PhpDocNode/AbstractTagValueNode.php b/packages/better-php-doc-parser/src/PhpDocNode/AbstractTagValueNode.php index 61eb32b0b3c..9c4125b70cf 100644 --- a/packages/better-php-doc-parser/src/PhpDocNode/AbstractTagValueNode.php +++ b/packages/better-php-doc-parser/src/PhpDocNode/AbstractTagValueNode.php @@ -83,7 +83,9 @@ abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpD public function __toString(): string { $items = $this->completeItemsQuotes($this->items); + $items = $this->filterOutMissingItems($items); $items = $this->makeKeysExplicit($items); + return $this->printContentItems($items); } @@ -119,6 +121,14 @@ abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpD $json = Strings::replace($json, '#"#'); } + // @todo, quote keys! + foreach (array_keys($item) as $key) { + $isKeyQuoted = (bool) Strings::match($this->originalContent, '#\"' . $key . '\"#'); + if ($isKeyQuoted) { + $json = Strings::replace($json, '#' . $key . '#', '"' . $key . '"'); + } + } + return $keyPart . $json; } @@ -146,8 +156,9 @@ abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpD continue; } + $arrayItemAsString = $this->printArrayItem($value, $key); /** @var string $key */ - $items[$key] = $this->printArrayItem($value, $key); + $items[$key] = $arrayItemAsString; } return sprintf( diff --git a/packages/better-php-doc-parser/tests/PhpDocParser/TagValueNodeReprint/Fixture/DoctrineColumn/QuotesInNestedArray.php b/packages/better-php-doc-parser/tests/PhpDocParser/TagValueNodeReprint/Fixture/DoctrineColumn/QuotesInNestedArray.php index ccb1b577198..479d6d6fc21 100644 --- a/packages/better-php-doc-parser/tests/PhpDocParser/TagValueNodeReprint/Fixture/DoctrineColumn/QuotesInNestedArray.php +++ b/packages/better-php-doc-parser/tests/PhpDocParser/TagValueNodeReprint/Fixture/DoctrineColumn/QuotesInNestedArray.php @@ -9,7 +9,7 @@ use Doctrine\ORM\Mapping as ORM; final class QuotesInNestedArray { /** - * @ORM\Column(options={"unsigned":true, "default":0}) + * @ORM\Column(options={"unsigned"=true, "default"=0}) */ private $loginCount; } diff --git a/packages/better-php-doc-parser/tests/PhpDocParser/TagValueNodeReprint/TagValueNodeReprintTest.php b/packages/better-php-doc-parser/tests/PhpDocParser/TagValueNodeReprint/TagValueNodeReprintTest.php index fcc8341c60b..1ef195bcc56 100644 --- a/packages/better-php-doc-parser/tests/PhpDocParser/TagValueNodeReprint/TagValueNodeReprintTest.php +++ b/packages/better-php-doc-parser/tests/PhpDocParser/TagValueNodeReprint/TagValueNodeReprintTest.php @@ -28,10 +28,6 @@ final class TagValueNodeReprintTest extends AbstractPhpDocInfoTest */ public function test(string $filePath, string $tagValueNodeClass): void { - if (Strings::endsWith($filePath, 'QuotesInNestedArray.php')) { - $this->markTestSkipped('Quoting nested keys in annotations is in progress'); - } - $this->doTestPrintedPhpDocInfo($filePath, $tagValueNodeClass); } diff --git a/packages/php-attribute/src/PhpDocNode/PhpAttributePhpDocNodePrintTrait.php b/packages/php-attribute/src/PhpDocNode/PhpAttributePhpDocNodePrintTrait.php index 6005374a283..17c28af37ef 100644 --- a/packages/php-attribute/src/PhpDocNode/PhpAttributePhpDocNodePrintTrait.php +++ b/packages/php-attribute/src/PhpDocNode/PhpAttributePhpDocNodePrintTrait.php @@ -4,6 +4,9 @@ declare(strict_types=1); namespace Rector\PhpAttribute\PhpDocNode; +/** + * @see https://wiki.php.net/rfc/attributes_v2 + */ trait PhpAttributePhpDocNodePrintTrait { /** From 32da6f5b998ef8f7003ccae974fb66bdbe073c9d Mon Sep 17 00:00:00 2001 From: TomasVotruba Date: Wed, 6 May 2020 16:52:41 +0200 Subject: [PATCH 3/6] add support for quoted key in php doc --- .../src/PhpDocNode/AbstractTagValueNode.php | 23 ++++++++++++++----- .../TagValueNodeReprintTest.php | 1 - 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/packages/better-php-doc-parser/src/PhpDocNode/AbstractTagValueNode.php b/packages/better-php-doc-parser/src/PhpDocNode/AbstractTagValueNode.php index 9c4125b70cf..3c56538c45d 100644 --- a/packages/better-php-doc-parser/src/PhpDocNode/AbstractTagValueNode.php +++ b/packages/better-php-doc-parser/src/PhpDocNode/AbstractTagValueNode.php @@ -121,12 +121,8 @@ abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpD $json = Strings::replace($json, '#"#'); } - // @todo, quote keys! - foreach (array_keys($item) as $key) { - $isKeyQuoted = (bool) Strings::match($this->originalContent, '#\"' . $key . '\"#'); - if ($isKeyQuoted) { - $json = Strings::replace($json, '#' . $key . '#', '"' . $key . '"'); - } + if ($this->originalContent !== null && $key !== null) { + $json = $this->quoteKeys($item, $key, $json, $this->originalContent); } return $keyPart . $json; @@ -315,4 +311,19 @@ abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpD // @see https://regex101.com/r/VgvK8C/3/ return sprintf('#%s="#', $escapedKey); } + + private function quoteKeys(array $item, string $key, string $json, string $originalContent): string + { + foreach (array_keys($item) as $itemKey) { + // @see https://regex101.com/r/V7nq5D/1 + $quotedKeyPattern = '#' . $key . '={(.*?)?\"' . $itemKey . '\"(.*?)?}#'; + $isKeyQuoted = (bool) Strings::match($originalContent, $quotedKeyPattern); + if ($isKeyQuoted === false) { + continue; + } + + $json = Strings::replace($json, '#([^\"])' . $itemKey . '([^\"])#', '$1"' . $itemKey . '"$2'); + } + return $json; + } } diff --git a/packages/better-php-doc-parser/tests/PhpDocParser/TagValueNodeReprint/TagValueNodeReprintTest.php b/packages/better-php-doc-parser/tests/PhpDocParser/TagValueNodeReprint/TagValueNodeReprintTest.php index 1ef195bcc56..455d2fdb6df 100644 --- a/packages/better-php-doc-parser/tests/PhpDocParser/TagValueNodeReprint/TagValueNodeReprintTest.php +++ b/packages/better-php-doc-parser/tests/PhpDocParser/TagValueNodeReprint/TagValueNodeReprintTest.php @@ -5,7 +5,6 @@ declare(strict_types=1); namespace Rector\BetterPhpDocParser\Tests\PhpDocParser\TagValueNodeReprint; use Iterator; -use Nette\Utils\Strings; use PHPStan\PhpDocParser\Ast\PhpDoc\GenericTagValueNode; use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Class_\EntityTagValueNode; use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Class_\TableTagValueNode; From 790ab2fb06bee9102a22c1d06bb7c770f49d5e89 Mon Sep 17 00:00:00 2001 From: TomasVotruba Date: Wed, 6 May 2020 17:03:06 +0200 Subject: [PATCH 4/6] allow ReservedFnFunctionRector on older PHP 7.3 --- .../Function_/ReservedFnFunctionRector.php | 32 ++++++++++++++++--- .../Fixture/fixture.php.inc | 4 +-- .../ReservedFnFunctionRectorTest.php | 16 ++++++---- 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/rules/php74/src/Rector/Function_/ReservedFnFunctionRector.php b/rules/php74/src/Rector/Function_/ReservedFnFunctionRector.php index 38bfb0d658a..b59e96d52df 100644 --- a/rules/php74/src/Rector/Function_/ReservedFnFunctionRector.php +++ b/rules/php74/src/Rector/Function_/ReservedFnFunctionRector.php @@ -6,6 +6,7 @@ namespace Rector\Php74\Rector\Function_; use PhpParser\Node; use PhpParser\Node\Expr\FuncCall; +use PhpParser\Node\Identifier; use PhpParser\Node\Name; use PhpParser\Node\Stmt\Function_; use Rector\Core\Rector\AbstractRector; @@ -18,6 +19,19 @@ use Rector\Core\RectorDefinition\RectorDefinition; */ final class ReservedFnFunctionRector extends AbstractRector { + /** + * @var string[] + */ + private $reservedNamesToNewOnes = []; + + public function __construct(array $reservedNamesToNewOnes = [ + // PHP 7.4 + 'fn' => 'f', + ]) + { + $this->reservedNamesToNewOnes = $reservedNamesToNewOnes; + } + public function getDefinition(): RectorDefinition { return new RectorDefinition('Change fn() function name, since it will be reserved keyword', [ @@ -68,12 +82,20 @@ PHP */ public function refactor(Node $node): ?Node { - if (! $this->isName($node, 'fn')) { - return null; + foreach ($this->reservedNamesToNewOnes as $reservedName => $newName) { + if (! $this->isName($node->name, $reservedName)) { + continue; + } + + if ($node instanceof FuncCall) { + $node->name = new Name($newName); + } else { + $node->name = new Identifier($newName); + } + + return $node; } - $node->name = new Name('f'); - - return $node; + return null; } } diff --git a/rules/php74/tests/Rector/Function_/ReservedFnFunctionRector/Fixture/fixture.php.inc b/rules/php74/tests/Rector/Function_/ReservedFnFunctionRector/Fixture/fixture.php.inc index b0d813f5e2c..a19c2d40d11 100644 --- a/rules/php74/tests/Rector/Function_/ReservedFnFunctionRector/Fixture/fixture.php.inc +++ b/rules/php74/tests/Rector/Function_/ReservedFnFunctionRector/Fixture/fixture.php.inc @@ -6,12 +6,12 @@ class SomeClass { public function run() { - function fn($value) + function reservedFn($value) { return $value; } - fn(5); + reservedFn(5); } } diff --git a/rules/php74/tests/Rector/Function_/ReservedFnFunctionRector/ReservedFnFunctionRectorTest.php b/rules/php74/tests/Rector/Function_/ReservedFnFunctionRector/ReservedFnFunctionRectorTest.php index 4a7b78c3c02..29e0c859d24 100644 --- a/rules/php74/tests/Rector/Function_/ReservedFnFunctionRector/ReservedFnFunctionRectorTest.php +++ b/rules/php74/tests/Rector/Function_/ReservedFnFunctionRector/ReservedFnFunctionRectorTest.php @@ -5,7 +5,6 @@ declare(strict_types=1); namespace Rector\Php74\Tests\Rector\Function_\ReservedFnFunctionRector; use Iterator; -use PhpParser\Parser\Tokens; use Rector\Core\Testing\PHPUnit\AbstractRectorTestCase; use Rector\Php74\Rector\Function_\ReservedFnFunctionRector; @@ -16,10 +15,6 @@ final class ReservedFnFunctionRectorTest extends AbstractRectorTestCase */ public function test(string $file): void { - if (defined(Tokens::class . '::T_FN')) { - $this->markTestSkipped('fn is reserved name in PHP 7.4'); - } - $this->doTestFile($file); } @@ -28,8 +23,15 @@ final class ReservedFnFunctionRectorTest extends AbstractRectorTestCase return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture'); } - protected function getRectorClass(): string + protected function getRectorsWithConfiguration(): array { - return ReservedFnFunctionRector::class; + return [ + ReservedFnFunctionRector::class => [ + '$reservedNamesToNewOnes' => [ + // for testing purposes of "fn" even on PHP 7.3- + 'reservedFn' => 'f', + ], + ], + ]; } } From 3e655324316dbbfcbc4ef1a803323e9902aedb68 Mon Sep 17 00:00:00 2001 From: rector-bot Date: Wed, 6 May 2020 15:11:39 +0000 Subject: [PATCH 5/6] fixup! allow ReservedFnFunctionRector on older PHP 7.3 --- .../src/PhpDocNode/AbstractTagValueNode.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/better-php-doc-parser/src/PhpDocNode/AbstractTagValueNode.php b/packages/better-php-doc-parser/src/PhpDocNode/AbstractTagValueNode.php index 3c56538c45d..ce943c8d933 100644 --- a/packages/better-php-doc-parser/src/PhpDocNode/AbstractTagValueNode.php +++ b/packages/better-php-doc-parser/src/PhpDocNode/AbstractTagValueNode.php @@ -318,7 +318,7 @@ abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpD // @see https://regex101.com/r/V7nq5D/1 $quotedKeyPattern = '#' . $key . '={(.*?)?\"' . $itemKey . '\"(.*?)?}#'; $isKeyQuoted = (bool) Strings::match($originalContent, $quotedKeyPattern); - if ($isKeyQuoted === false) { + if (!$isKeyQuoted) { continue; } From 237aa4a5c36dd89bae9f98a7f32aac13c3691049 Mon Sep 17 00:00:00 2001 From: rector-bot Date: Wed, 6 May 2020 15:12:26 +0000 Subject: [PATCH 6/6] fixup! fixup! allow ReservedFnFunctionRector on older PHP 7.3 --- .../src/PhpDocNode/AbstractTagValueNode.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/better-php-doc-parser/src/PhpDocNode/AbstractTagValueNode.php b/packages/better-php-doc-parser/src/PhpDocNode/AbstractTagValueNode.php index ce943c8d933..66e4c3adf97 100644 --- a/packages/better-php-doc-parser/src/PhpDocNode/AbstractTagValueNode.php +++ b/packages/better-php-doc-parser/src/PhpDocNode/AbstractTagValueNode.php @@ -318,7 +318,7 @@ abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpD // @see https://regex101.com/r/V7nq5D/1 $quotedKeyPattern = '#' . $key . '={(.*?)?\"' . $itemKey . '\"(.*?)?}#'; $isKeyQuoted = (bool) Strings::match($originalContent, $quotedKeyPattern); - if (!$isKeyQuoted) { + if (! $isKeyQuoted) { continue; }