From 075707447a171defab92d14237e5042e56a788fd Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Tue, 23 Oct 2018 20:06:06 +0200 Subject: [PATCH] [Symfony] Add FormTypeInstanceToClassConstRector --- composer.json | 16 +- config/level/symfony/symfony30.yml | 3 +- .../src/Command/CreateRectorCommand.php | 53 ++- .../src/Configuration/Configuration.php | 16 +- .../Configuration/ConfigurationFactory.php | 17 +- .../ConstantToStaticCallRectorTest.php | 2 +- .../DefineConstantToStaticCallRectorTest.php | 2 +- .../FormTypeInstanceToClassConstRector.php | 333 ++++++++++++++++++ ...xceptionToErrorEventConstantRectorTest.php | 2 +- .../ActionSuffixRemoverRectorTest.php | 2 +- .../AddFlashRector/AddFlashRectorTest.php | 2 +- .../RedirectToRouteRectorTest.php | 2 +- ...nerBuilderCompileEnvArgumentRectorTest.php | 2 +- .../FormIsValidRectorTest.php | 2 +- .../FormTypeGetParentRectorTest.php | 2 +- .../OptionNameRector/OptionNameRectorTest.php | 2 +- .../StringFormTypeToClassRectorTest.php | 2 +- ...nerGetToConstructorInjectionRectorTest.php | 2 +- ...ameterToConstructorInjectionRectorTest.php | 2 +- .../GetToConstructorInjectionRectorTest.php | 2 +- ...gurationConstructorInjectionRectorTest.php | 2 +- ...gurationConstructorInjectionRectorTest.php | 2 +- ...gurationConstructorInjectionRectorTest.php | 2 +- .../GetRequestRector/GetRequestRectorTest.php | 2 +- .../Correct/correct.php.inc | 34 ++ .../Correct/correct2.php.inc | 18 + .../Correct/correct3.php.inc | 30 ++ ...FormTypeInstanceToClassConstRectorTest.php | 32 ++ .../Source/ControllerClass.php | 8 + .../Source/FormBuilder.php | 8 + .../Source/FormType.php | 8 + .../Wrong/wrong.php.inc | 31 ++ .../Wrong/wrong2.php.inc | 18 + .../Wrong/wrong3.php.inc | 27 ++ .../config.yml | 5 + .../ProcessBuilderGetProcessRectorTest.php | 2 +- .../ProcessBuilderInstanceRectorTest.php | 2 +- .../ConstraintUrlOptionRectorTest.php | 2 +- ...VarDumperTestTraitMethodArgsRectorTest.php | 2 +- .../ParseFileRector/ParseFileRectorTest.php | 2 +- ...ssionStrictTrueByDefaultYamlRectorTest.php | 2 +- .../SpaceBetweenKeyAndValueYamlRectorTest.php | 2 +- phpstan.neon | 1 + .../AutoloadWrongCasesEventSubscriber.php | 4 +- 44 files changed, 643 insertions(+), 69 deletions(-) create mode 100644 packages/Symfony/src/Rector/MethodCall/FormTypeInstanceToClassConstRector.php create mode 100644 packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Correct/correct.php.inc create mode 100644 packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Correct/correct2.php.inc create mode 100644 packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Correct/correct3.php.inc create mode 100644 packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/FormTypeInstanceToClassConstRectorTest.php create mode 100644 packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Source/ControllerClass.php create mode 100644 packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Source/FormBuilder.php create mode 100644 packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Source/FormType.php create mode 100644 packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Wrong/wrong.php.inc create mode 100644 packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Wrong/wrong2.php.inc create mode 100644 packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Wrong/wrong3.php.inc create mode 100644 packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/config.yml diff --git a/composer.json b/composer.json index 5127ee85061..b242ffd8c2f 100644 --- a/composer.json +++ b/composer.json @@ -80,18 +80,10 @@ "Rector\\FileSystemRector\\Tests\\": "packages/FileSystemRector/tests" }, "classmap": [ - "packages/CakePHP/tests", - "packages/Doctrine/tests", - "packages/FileSystemRector/tests", - "packages/NodeTypeResolver/tests", - "packages/PhpParser/tests", - "packages/PHPUnit/tests", - "packages/Sensio/tests", - "packages/Silverstripe/tests", - "packages/Sylius/tests", - "packages/Symfony/tests", - "packages/Twig/tests", - "packages/Utils/tests", + "packages/Symfony/tests/Rector/FrameworkBundle/AbstractToConstructorInjectionRectorSource", + "packages/Symfony/tests/Rector/FrameworkBundle/ContainerGetToConstructorInjectionRector/Source", + "packages/NodeTypeResolver/tests/PerNodeTypeResolver/ParamTypeResolver/Source", + "packages/NodeTypeResolver/tests/PerNodeTypeResolver/PropertyTypeResolver/Source", "tests/Source", "tests/Rector/Psr4/MultipleClassFileToPsr4ClassesRector/Source", "tests/Rector/Namespace_/PseudoNamespaceToNamespaceRector/Source" diff --git a/config/level/symfony/symfony30.yml b/config/level/symfony/symfony30.yml index c74f1927ff1..e595a0b598e 100644 --- a/config/level/symfony/symfony30.yml +++ b/config/level/symfony/symfony30.yml @@ -156,4 +156,5 @@ services: 'Symfony\Component\Validator\Mapping\MetadataFactoryInterface': 'Symfony\Component\Validator\Mapping\Factory\MetadataFactoryInterface' # swift mailer - 'Symfony\Bridge\Swiftmailer\DataCollector\MessageDataCollector': 'Symfony\Bundle\SwiftmailerBundle\DataCollector\MessageDataCollector' \ No newline at end of file + 'Symfony\Bridge\Swiftmailer\DataCollector\MessageDataCollector': 'Symfony\Bundle\SwiftmailerBundle\DataCollector\MessageDataCollector' + Rector\Symfony\Rector\MethodCall\FormTypeInstanceToClassConstRector: ~ diff --git a/packages/ContributorTools/src/Command/CreateRectorCommand.php b/packages/ContributorTools/src/Command/CreateRectorCommand.php index df373d19691..88bf445298d 100644 --- a/packages/ContributorTools/src/Command/CreateRectorCommand.php +++ b/packages/ContributorTools/src/Command/CreateRectorCommand.php @@ -6,13 +6,13 @@ use Nette\Utils\FileSystem; use Nette\Utils\Strings; use Rector\CodingStyle\AfterRectorCodingStyle; use Rector\Console\ConsoleStyle; +use Rector\ContributorTools\Configuration\Configuration; use Rector\ContributorTools\Configuration\ConfigurationFactory; use Rector\ContributorTools\TemplateVariablesFactory; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Finder\Finder; -use Symfony\Component\Yaml\Yaml; use Symplify\PackageBuilder\Console\Command\CommandNaming; use Symplify\PackageBuilder\Console\ShellCode; use Symplify\PackageBuilder\FileSystem\FinderSanitizer; @@ -28,6 +28,11 @@ final class CreateRectorCommand extends Command */ private const TEMPLATES_DIRECTORY = __DIR__ . '/../../templates'; + /** + * @var string + */ + private const RECTOR_FQN_NAME_PATTERN = 'Rector\_Package_\Rector\_Category_\_Name_'; + /** * @var ConsoleStyle */ @@ -101,19 +106,7 @@ final class CreateRectorCommand extends Command } } - if ($configuration->getLevel()) { - if (file_exists($configuration->getLevel())) { - $levelConfigContent = FileSystem::read($configuration->getLevel()); - $levelConfigContent = trim($levelConfigContent) . sprintf( - '%s%s: ~%s', - PHP_EOL, - Strings::indent($configuration->getName(), 8, ' '), - PHP_EOL - ); - - FileSystem::write($configuration->getLevel(), $levelConfigContent); - } - } + $this->appendToLevelConfig($configuration, $templateVariables); $this->applyCodingStyle(); $this->printSuccess($configuration->getName()); @@ -180,4 +173,36 @@ final class CreateRectorCommand extends Command { return $this->applyVariables($smartFileInfo->getContents(), $templateVariables); } + + /** + * @param string[] $templateVariables + */ + private function appendToLevelConfig(Configuration $configuration, array $templateVariables): void + { + if (! $configuration->getLevelConfig()) { + return; + } + + if (! file_exists($configuration->getLevelConfig())) { + return; + } + + $rectorFqnName = $this->applyVariables(self::RECTOR_FQN_NAME_PATTERN, $templateVariables); + + $levelConfigContent = FileSystem::read($configuration->getLevelConfig()); + + // already added + if (Strings::contains($levelConfigContent, $rectorFqnName)) { + return; + } + + $levelConfigContent = trim($levelConfigContent) . sprintf( + '%s%s: ~%s', + PHP_EOL, + Strings::indent($rectorFqnName, 8, ' '), + PHP_EOL + ); + + FileSystem::write($configuration->getLevelConfig(), $levelConfigContent); + } } diff --git a/packages/ContributorTools/src/Configuration/Configuration.php b/packages/ContributorTools/src/Configuration/Configuration.php index 00510205762..ab9742dfe8a 100644 --- a/packages/ContributorTools/src/Configuration/Configuration.php +++ b/packages/ContributorTools/src/Configuration/Configuration.php @@ -49,7 +49,7 @@ final class Configuration /** * @var string|null */ - private $level; + private $levelConfig; /** * @param string[] $nodeTypes @@ -63,7 +63,7 @@ final class Configuration string $codeBefore, string $codeAfter, string $source, - ?string $level + ?string $levelConfig ) { $this->package = $package; $this->setName($name); @@ -73,7 +73,7 @@ final class Configuration $this->codeAfter = $codeAfter; $this->description = $description; $this->source = $source; - $this->level = $level; + $this->levelConfig = $levelConfig; } public function getDescription(): string @@ -119,6 +119,11 @@ final class Configuration return $this->source; } + public function getLevelConfig(): ?string + { + return $this->levelConfig; + } + private function setName(string $name): void { if (! Strings::endsWith($name, 'Rector')) { @@ -127,9 +132,4 @@ final class Configuration $this->name = $name; } - - public function getLevel(): ?string - { - return $this->level; - } } diff --git a/packages/ContributorTools/src/Configuration/ConfigurationFactory.php b/packages/ContributorTools/src/Configuration/ConfigurationFactory.php index ebd766ad595..27b69465304 100644 --- a/packages/ContributorTools/src/Configuration/ConfigurationFactory.php +++ b/packages/ContributorTools/src/Configuration/ConfigurationFactory.php @@ -133,7 +133,7 @@ final class ConfigurationFactory return array_keys($robotLoader->getIndexedClasses()); } - private function isNodeClassMatch(String $nodeClass, String $nodeType): bool + private function isNodeClassMatch(string $nodeClass, string $nodeType): bool { if (Strings::endsWith($nodeClass, '\\' . $nodeType)) { return true; @@ -147,15 +147,16 @@ final class ConfigurationFactory { $finder = Finder::create()->files() ->in($this->levelsDirectory) - ->name('#.(yml|yaml)$#'); + ->name(sprintf('#%s$#', $level)); - /** @var SplFileInfo $fileInfo */ - foreach ($finder as $fileInfo) { - if ($fileInfo->getBasename() === $level) { - return $fileInfo->getRealPath(); - } + /** @var SplFileInfo[] $fileInfos */ + $fileInfos = iterator_to_array($finder->getIterator()); + if (! count($fileInfos)) { + return null; } - return null; + /** @var SplFileInfo $foundLevelConfigFileInfo */ + $foundLevelConfigFileInfo = array_pop($fileInfos); + return $foundLevelConfigFileInfo->getRealPath(); } } diff --git a/packages/Silverstripe/tests/Rector/ConstantToStaticCallRector/ConstantToStaticCallRectorTest.php b/packages/Silverstripe/tests/Rector/ConstantToStaticCallRector/ConstantToStaticCallRectorTest.php index f6665e983f7..a0f43bb3162 100644 --- a/packages/Silverstripe/tests/Rector/ConstantToStaticCallRector/ConstantToStaticCallRectorTest.php +++ b/packages/Silverstripe/tests/Rector/ConstantToStaticCallRector/ConstantToStaticCallRectorTest.php @@ -1,6 +1,6 @@ classNodeCollector = $classNodeCollector; + $this->controllerClass = $controllerClass; + $this->formBuilderType = $formBuilderType; + $this->formType = $formType; + $this->builderFactory = $builderFactory; + } + + public function getDefinition(): RectorDefinition + { + return new RectorDefinition( + 'Changes createForm(new FormType), add(new FormType) to ones with "FormType::class"', + [ + new CodeSample( + <<<'CODE_SAMPLE' +class SomeController +{ + public function action() + { + $form = $this->createForm(new TeamType, $entity, [ + 'action' => $this->generateUrl('teams_update', ['id' => $entity->getId()]), + 'method' => 'PUT', + ]); + } +} +CODE_SAMPLE + , + <<<'CODE_SAMPLE' +class SomeController +{ + public function action() + { + $form = $this->createForm(TeamType::class, $entity, [ + 'action' => $this->generateUrl('teams_update', ['id' => $entity->getId()]), + 'method' => 'PUT', + )); + } +} +CODE_SAMPLE + ), + ] + ); + } + + /** + * @return string[] + */ + public function getNodeTypes(): array + { + return [MethodCall::class]; + } + + /** + * @param MethodCall $node + */ + public function refactor(Node $node): ?Node + { + if ($this->isType($node, $this->controllerClass) && $this->isName($node, 'createForm')) { + return $this->processNewInstance($node, 0, 2); + } + + if ($this->isTypes($node, [$this->formBuilderType, $this->formType]) && $this->isName($node, 'add')) { + return $this->processNewInstance($node, 1, 2); + } + + return null; + } + + private function processNewInstance(MethodCall $methodCallNode, int $position, int $optionsPosition): ?Node + { + if (! isset($methodCallNode->args[$position])) { + return null; + } + + if (! $methodCallNode->args[$position]->value instanceof New_) { + return null; + } + + /** @var New_ $newNode */ + $newNode = $methodCallNode->args[$position]->value; + + // we can only process direct name + if (! $newNode->class instanceof Name) { + return null; + } + + if (count($newNode->args)) { + $methodCallNode = $this->moveArgumentsToOptions( + $methodCallNode, + $position, + $optionsPosition, + $newNode->class->toString(), + $newNode->args + ); + if ($methodCallNode === null) { + return null; + } + } + + $methodCallNode->args[$position]->value = new ClassConstFetch($newNode->class, 'class'); + + return $methodCallNode; + } + + /** + * @param Arg[] $argNodes + * @return Arg[] + */ + private function resolveNamesToArgs(string $className, array $argNodes): array + { + $reflectionClass = new ReflectionClass($className); + $constructorReflectionMethod = $reflectionClass->getConstructor(); + + if (! $constructorReflectionMethod) { + return []; + } + + $namesToArgs = []; + foreach ($constructorReflectionMethod->getParameters() as $parameterReflection) { + $namesToArgs[$parameterReflection->getName()] = $argNodes[$parameterReflection->getPosition()]; + } + + return $namesToArgs; + } + + /** + * @param Arg[] $argNodes + */ + private function moveArgumentsToOptions( + MethodCall $methodCallNode, + int $position, + int $optionsPosition, + string $className, + array $argNodes + ): ?Node { + $namesToArgs = $this->resolveNamesToArgs($className, $argNodes); + + // set default data in between + if ($position + 1 !== $optionsPosition) { + if (! isset($methodCallNode->args[$position + 1])) { + $methodCallNode->args[$position + 1] = new Arg(new ConstFetch(new Name('null'))); + } + } + + // @todo extend current options - array analyzer + if (! isset($methodCallNode->args[$optionsPosition])) { + $optionsArrayNode = new Array_(); + foreach ($namesToArgs as $name => $arg) { + $optionsArrayNode->items[] = new ArrayItem($arg->value, new String_($name)); + } + + $methodCallNode->args[$optionsPosition] = new Arg($optionsArrayNode); + } + + $formTypeClassNode = $this->classNodeCollector->findClass($className); + if ($formTypeClassNode === null) { + return null; + } + + $formTypeConstructorMethodNode = $formTypeClassNode->getMethod('__construct'); + + // nothing we can do, out of scope + if ($formTypeConstructorMethodNode === null) { + return null; + } + + // add "buildForm" method + "configureOptions" method with defaults + $this->addBuildFormMethod($formTypeClassNode, $formTypeConstructorMethodNode); + $this->addConfigureOptionsMethod($formTypeClassNode, $namesToArgs); + + // remove ctor + $this->removeNode($formTypeConstructorMethodNode); + + return $methodCallNode; + } + + /** + * @param Node[] $nodes + * @return Node[] + * + * $this->value = $value + * ↓ + * $this->value = $options['value'] + */ + private function replaceParameterAssignWithOptionAssign(array $nodes, Param $param): array + { + foreach ($nodes as $expression) { + if (! $expression instanceof Expression) { + continue; + } + + $node = $expression->expr; + + if ($node instanceof Assign && $node->expr instanceof Variable) { + $node->expr = new ArrayDimFetch($param->var, new String_($this->getName($node->var))); + } + } + + return $nodes; + } + + private function addBuildFormMethod(Class_ $classNode, ClassMethod $formTypeConstructorMethodNode): void + { + if ($classNode->getMethod('buildForm')) { + // @todo + return; + } + + $formBuilderParamNode = $this->builderFactory->param('builder') + ->setType(new FullyQualified($this->formBuilderType)) + ->getNode(); + + $optionsParamNode = $this->builderFactory->param('options') + ->setType('array') + ->getNode(); + + $buildFormClassMethodNode = $this->builderFactory->method('buildForm') + ->makePublic() + ->addParam($formBuilderParamNode) + ->addParam($optionsParamNode) + // raw copy stmts from ctor @todo improve + ->addStmts( + $this->replaceParameterAssignWithOptionAssign( + $formTypeConstructorMethodNode->stmts, + $optionsParamNode + ) + ) + ->getNode(); + + $classNode->stmts[] = $buildFormClassMethodNode; + } + + /** + * @param Arg[] $namesToArgs + */ + private function addConfigureOptionsMethod(Class_ $classNode, array $namesToArgs): void + { + if ($classNode->getMethod('configureOptions')) { + // @todo + return; + } + + $resolverParamNode = $this->builderFactory->param('resolver') + ->setType(new FullyQualified('Symfony\Component\OptionsResolver\OptionsResolver')) + ->getNode(); + + $optionsDefaults = new Array_(); + + foreach (array_keys($namesToArgs) as $optionName) { + $optionsDefaults->items[] = new ArrayItem(new ConstFetch(new Name('null')), new String_($optionName)); + } + + $setDefaultsMethodCall = new MethodCall($resolverParamNode->var, new Identifier('setDefaults')); + $setDefaultsMethodCall->args[] = new Arg($optionsDefaults); + + $configureOptionsClassMethodNode = $this->builderFactory->method('configureOptions') + ->makePublic() + ->addParam($resolverParamNode) + ->addStmt($setDefaultsMethodCall) + ->getNode(); + + $classNode->stmts[] = $configureOptionsClassMethodNode; + } +} diff --git a/packages/Symfony/tests/Rector/Console/ConsoleExceptionToErrorEventConstantRector/ConsoleExceptionToErrorEventConstantRectorTest.php b/packages/Symfony/tests/Rector/Console/ConsoleExceptionToErrorEventConstantRector/ConsoleExceptionToErrorEventConstantRectorTest.php index aa69db434f2..876a5264190 100644 --- a/packages/Symfony/tests/Rector/Console/ConsoleExceptionToErrorEventConstantRector/ConsoleExceptionToErrorEventConstantRectorTest.php +++ b/packages/Symfony/tests/Rector/Console/ConsoleExceptionToErrorEventConstantRector/ConsoleExceptionToErrorEventConstantRectorTest.php @@ -1,6 +1,6 @@ createForm(AnotherFormType::class, $entity, [ + 'action' => $this->generateUrl('teams_update', ['id' => $entity->getId()]), + 'method' => 'PUT', + ]); + + $form = $this->createForm(AnotherFormType::class, $entity, ['items' => [1]]); + } +} + +final class AnotherFormType +{ + /** + * @var array + */ + private $items; + public function buildForm(\Rector\Symfony\Tests\Rector\MethodCall\FormTypeInstanceToClassConstRector\Source\FormBuilder $builder, array $options) + { + $this->items = $options['items']; + } + public function configureOptions(\Symfony\Component\OptionsResolver\OptionsResolver $resolver) + { + $resolver->setDefaults(['items' => null]); + } +} diff --git a/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Correct/correct2.php.inc b/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Correct/correct2.php.inc new file mode 100644 index 00000000000..2f67aeede61 --- /dev/null +++ b/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Correct/correct2.php.inc @@ -0,0 +1,18 @@ +add('someText', SomeClass::class); + + $form = new FormType(); + $form->add('text', AnotherFormTypeClass::class); + } +} diff --git a/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Correct/correct3.php.inc b/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Correct/correct3.php.inc new file mode 100644 index 00000000000..2f15fa01b7f --- /dev/null +++ b/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Correct/correct3.php.inc @@ -0,0 +1,30 @@ +add('someText', SomeTypeWithCtor::class, ['number' => 1]); + } +} + +class SomeTypeWithCtor +{ + /** + * @var int + */ + private $number; + public function buildForm(\Rector\Symfony\Tests\Rector\MethodCall\FormTypeInstanceToClassConstRector\Source\FormBuilder $builder, array $options) + { + $this->number = $options['number']; + } + public function configureOptions(\Symfony\Component\OptionsResolver\OptionsResolver $resolver) + { + $resolver->setDefaults(['number' => null]); + } +} diff --git a/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/FormTypeInstanceToClassConstRectorTest.php b/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/FormTypeInstanceToClassConstRectorTest.php new file mode 100644 index 00000000000..ca11e0d4655 --- /dev/null +++ b/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/FormTypeInstanceToClassConstRectorTest.php @@ -0,0 +1,32 @@ +doTestFileMatchesExpectedContent($wrong, $fixed); + } + + public function provideWrongToFixedFiles(): Iterator + { + yield [__DIR__ . '/Wrong/wrong.php.inc', __DIR__ . '/Correct/correct.php.inc']; + yield [__DIR__ . '/Wrong/wrong2.php.inc', __DIR__ . '/Correct/correct2.php.inc']; + yield [__DIR__ . '/Wrong/wrong3.php.inc', __DIR__ . '/Correct/correct3.php.inc']; + } + + protected function provideConfig(): string + { + return __DIR__ . '/config.yml'; + } +} diff --git a/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Source/ControllerClass.php b/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Source/ControllerClass.php new file mode 100644 index 00000000000..6b6939485b9 --- /dev/null +++ b/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Source/ControllerClass.php @@ -0,0 +1,8 @@ +createForm(new AnotherFormType(), $entity, [ + 'action' => $this->generateUrl('teams_update', ['id' => $entity->getId()]), + 'method' => 'PUT', + ]); + + $form = $this->createForm(new AnotherFormType([1]), $entity); + } +} + +final class AnotherFormType +{ + /** + * @var array + */ + private $items; + + public function __construct(array $items = []) + { + $this->items = $items; + } +} diff --git a/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Wrong/wrong2.php.inc b/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Wrong/wrong2.php.inc new file mode 100644 index 00000000000..79ed10819f5 --- /dev/null +++ b/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Wrong/wrong2.php.inc @@ -0,0 +1,18 @@ +add('someText', new SomeClass); + + $form = new FormType(); + $form->add('text', new AnotherFormTypeClass); + } +} diff --git a/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Wrong/wrong3.php.inc b/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Wrong/wrong3.php.inc new file mode 100644 index 00000000000..7877de1288c --- /dev/null +++ b/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/Wrong/wrong3.php.inc @@ -0,0 +1,27 @@ +add('someText', new SomeTypeWithCtor(1)); + } +} + +class SomeTypeWithCtor +{ + /** + * @var int + */ + private $number; + + public function __construct(int $number) + { + $this->number = $number; + } +} diff --git a/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/config.yml b/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/config.yml new file mode 100644 index 00000000000..9f52533c9f3 --- /dev/null +++ b/packages/Symfony/tests/Rector/MethodCall/FormTypeInstanceToClassConstRector/config.yml @@ -0,0 +1,5 @@ +services: + Rector\Symfony\Rector\MethodCall\FormTypeInstanceToClassConstRector: + $controllerClass: 'Rector\Symfony\Tests\Rector\MethodCall\FormTypeInstanceToClassConstRector\Source\ControllerClass' + $formBuilderType: 'Rector\Symfony\Tests\Rector\MethodCall\FormTypeInstanceToClassConstRector\Source\FormBuilder' + $formType: 'Rector\Symfony\Tests\Rector\MethodCall\FormTypeInstanceToClassConstRector\Source\FormType' diff --git a/packages/Symfony/tests/Rector/Process/ProcessBuilderGetProcessRector/ProcessBuilderGetProcessRectorTest.php b/packages/Symfony/tests/Rector/Process/ProcessBuilderGetProcessRector/ProcessBuilderGetProcessRectorTest.php index 3b93c1af389..450d3335bc9 100644 --- a/packages/Symfony/tests/Rector/Process/ProcessBuilderGetProcessRector/ProcessBuilderGetProcessRectorTest.php +++ b/packages/Symfony/tests/Rector/Process/ProcessBuilderGetProcessRector/ProcessBuilderGetProcessRectorTest.php @@ -1,6 +1,6 @@ \) does not accept PhpParser\\Node\\Expr#' - '#Cannot access property \$expr on PhpParser\\Node\\Stmt\|null#' diff --git a/tests/Composer/AutoloadWrongCasesEventSubscriber.php b/tests/Composer/AutoloadWrongCasesEventSubscriber.php index 952cb889402..569b4bdeeb9 100644 --- a/tests/Composer/AutoloadWrongCasesEventSubscriber.php +++ b/tests/Composer/AutoloadWrongCasesEventSubscriber.php @@ -26,6 +26,8 @@ final class AutoloadWrongCasesEventSubscriber self::$wrongDirectories = array_merge(self::$wrongDirectories, self::getWrongDirectoriesInPath($path)); } + sort(self::$wrongDirectories); + $package = $event->getComposer()->getPackage(); $autoload = $package->getDevAutoload(); $autoload['classmap'] = array_merge($autoload['classmap'] ?? [], self::$wrongDirectories); @@ -40,7 +42,7 @@ final class AutoloadWrongCasesEventSubscriber $globResult = self::globRecursive($path, GLOB_ONLYDIR); return array_filter($globResult, function ($name) { - return strpos($name, '/Wrong'); + return strpos($name, '/Wrong') && ! strpos($name, 'ContributorTools'); }); }