Updated Rector to commit 738cea7736

738cea7736 [DeadCode] Skip array_map in class extends Exception on RemoveUnusedPrivateMethodRector (#598)
This commit is contained in:
Tomas Votruba 2021-08-05 12:41:19 +00:00
parent 00f3fbe30d
commit d2c1af4455
26 changed files with 933 additions and 327 deletions

View File

@ -0,0 +1,47 @@
<?php
declare (strict_types=1);
namespace Rector\DeadCode\NodeAnalyzer;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PHPStan\Type\TypeWithClassName;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\NodeTypeResolver;
final class CallCollectionAnalyzer
{
/**
* @var \Rector\NodeTypeResolver\NodeTypeResolver
*/
private $nodeTypeResolver;
/**
* @var \Rector\NodeNameResolver\NodeNameResolver
*/
private $nodeNameResolver;
public function __construct(\Rector\NodeTypeResolver\NodeTypeResolver $nodeTypeResolver, \Rector\NodeNameResolver\NodeNameResolver $nodeNameResolver)
{
$this->nodeTypeResolver = $nodeTypeResolver;
$this->nodeNameResolver = $nodeNameResolver;
}
/**
* @param StaticCall[]|MethodCall[] $calls
*/
public function isExists(array $calls, string $classMethodName, ?string $className) : bool
{
foreach ($calls as $call) {
$callerRoot = $call instanceof \PhpParser\Node\Expr\StaticCall ? $call->class : $call->var;
$callerType = $this->nodeTypeResolver->resolve($callerRoot);
if (!$callerType instanceof \PHPStan\Type\TypeWithClassName) {
continue;
}
if ($callerType->getClassName() !== $className) {
continue;
}
// the method is used
if ($this->nodeNameResolver->isName($call->name, $classMethodName)) {
return \true;
}
}
return \false;
}
}

View File

@ -5,15 +5,17 @@ namespace Rector\DeadCode\Rector\ClassMethod;
use PhpParser\Node;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ArrayItem;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Type\TypeWithClassName;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\MethodName;
use Rector\DeadCode\NodeAnalyzer\CallCollectionAnalyzer;
use Rector\NodeCollector\NodeAnalyzer\ArrayCallableMethodMatcher;
use Rector\NodeCollector\ValueObject\ArrayCallable;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -28,9 +30,14 @@ final class RemoveUnusedPrivateMethodRector extends \Rector\Core\Rector\Abstract
* @var \Rector\NodeCollector\NodeAnalyzer\ArrayCallableMethodMatcher
*/
private $arrayCallableMethodMatcher;
public function __construct(\Rector\NodeCollector\NodeAnalyzer\ArrayCallableMethodMatcher $arrayCallableMethodMatcher)
/**
* @var \Rector\DeadCode\NodeAnalyzer\CallCollectionAnalyzer
*/
private $callCollectionAnalyzer;
public function __construct(\Rector\NodeCollector\NodeAnalyzer\ArrayCallableMethodMatcher $arrayCallableMethodMatcher, \Rector\DeadCode\NodeAnalyzer\CallCollectionAnalyzer $callCollectionAnalyzer)
{
$this->arrayCallableMethodMatcher = $arrayCallableMethodMatcher;
$this->callCollectionAnalyzer = $callCollectionAnalyzer;
}
public function getRuleDefinition() : \Symplify\RuleDocGenerator\ValueObject\RuleDefinition
{
@ -129,58 +136,62 @@ CODE_SAMPLE
$className = $this->getName($class);
/** @var StaticCall[] $staticCalls */
$staticCalls = $this->betterNodeFinder->findInstanceOf($class, \PhpParser\Node\Expr\StaticCall::class);
foreach ($staticCalls as $staticCall) {
$callerType = $this->nodeTypeResolver->resolve($staticCall->class);
if (!$callerType instanceof \PHPStan\Type\TypeWithClassName) {
continue;
}
if ($callerType->getClassName() !== $className) {
continue;
}
if ($this->isName($staticCall->name, $classMethodName)) {
return \true;
}
}
return \false;
return $this->callCollectionAnalyzer->isExists($staticCalls, $classMethodName, $className);
}
private function isClassMethodCalledInLocalMethodCall(\PhpParser\Node\Stmt\Class_ $class, string $classMethodName) : bool
{
$className = $this->getName($class);
/** @var MethodCall[] $methodCalls */
$methodCalls = $this->betterNodeFinder->findInstanceOf($class, \PhpParser\Node\Expr\MethodCall::class);
foreach ($methodCalls as $methodCall) {
$callerType = $this->nodeTypeResolver->resolve($methodCall->var);
if (!$callerType instanceof \PHPStan\Type\TypeWithClassName) {
continue;
}
if ($callerType->getClassName() !== $className) {
continue;
}
// the method is used
if ($this->isName($methodCall->name, $classMethodName)) {
return \true;
}
return $this->callCollectionAnalyzer->isExists($methodCalls, $classMethodName, $className);
}
private function isInArrayMap(\PhpParser\Node\Stmt\Class_ $class, \PhpParser\Node\Expr\Array_ $array) : bool
{
$parentFuncCall = $this->betterNodeFinder->findParentType($array, \PhpParser\Node\Expr\FuncCall::class);
if (!$parentFuncCall instanceof \PhpParser\Node\Expr\FuncCall) {
return \false;
}
return \false;
if (!$this->nodeNameResolver->isName($parentFuncCall->name, 'array_map')) {
return \false;
}
if (\count($array->items) !== 2) {
return \false;
}
if (!$array->items[1] instanceof \PhpParser\Node\Expr\ArrayItem) {
return \false;
}
$value = $this->valueResolver->getValue($array->items[1]->value);
if (!\is_string($value)) {
return \false;
}
return $class->getMethod($value) instanceof \PhpParser\Node\Stmt\ClassMethod;
}
private function isClassMethodCalledInLocalArrayCall(\PhpParser\Node\Stmt\Class_ $class, \PhpParser\Node\Stmt\ClassMethod $classMethod) : bool
{
/** @var Array_[] $arrays */
$arrays = $this->betterNodeFinder->findInstanceOf($class, \PhpParser\Node\Expr\Array_::class);
foreach ($arrays as $array) {
$arrayCallable = $this->arrayCallableMethodMatcher->match($array);
if (!$arrayCallable instanceof \Rector\NodeCollector\ValueObject\ArrayCallable) {
continue;
if ($this->isInArrayMap($class, $array)) {
return \true;
}
// is current class method?
if (!$this->isName($class, $arrayCallable->getClass())) {
$arrayCallable = $this->arrayCallableMethodMatcher->match($array);
if ($this->shouldSkipArrayCallable($class, $arrayCallable)) {
continue;
}
// the method is used
/** @var ArrayCallable $arrayCallable */
if ($this->nodeNameResolver->isName($classMethod->name, $arrayCallable->getMethod())) {
return \true;
}
}
return \false;
}
private function shouldSkipArrayCallable(\PhpParser\Node\Stmt\Class_ $class, ?\Rector\NodeCollector\ValueObject\ArrayCallable $arrayCallable) : bool
{
if (!$arrayCallable instanceof \Rector\NodeCollector\ValueObject\ArrayCallable) {
return \true;
}
// is current class method?
return !$this->isName($class, $arrayCallable->getClass());
}
}

View File

@ -16,11 +16,11 @@ final class VersionResolver
/**
* @var string
*/
public const PACKAGE_VERSION = 'ad15c5f694b9ed5049a85846740665c0f657c491';
public const PACKAGE_VERSION = '738cea7736f865c1d660c1f168fc6e35639466a2';
/**
* @var string
*/
public const RELEASE_DATE = '2021-08-05 08:22:02';
public const RELEASE_DATE = '2021-08-05 14:28:14';
public static function resolvePackageVersion() : string
{
$process = new \RectorPrefix20210805\Symfony\Component\Process\Process(['git', 'log', '--pretty="%H"', '-n1', 'HEAD'], __DIR__);

2
vendor/autoload.php vendored
View File

@ -4,4 +4,4 @@
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit533369b6f1bebfefbae9ed468dbeb83c::getLoader();
return ComposerAutoloaderInitdf25b088fcc52cbfc899699d2cfd389e::getLoader();

View File

@ -1933,6 +1933,7 @@ return array(
'Rector\\DeadCode\\ConditionResolver' => $baseDir . '/rules/DeadCode/ConditionResolver.php',
'Rector\\DeadCode\\Contract\\ConditionInterface' => $baseDir . '/rules/DeadCode/Contract/ConditionInterface.php',
'Rector\\DeadCode\\FeatureSupport\\FunctionSupportResolver' => $baseDir . '/rules/DeadCode/FeatureSupport/FunctionSupportResolver.php',
'Rector\\DeadCode\\NodeAnalyzer\\CallCollectionAnalyzer' => $baseDir . '/rules/DeadCode/NodeAnalyzer/CallCollectionAnalyzer.php',
'Rector\\DeadCode\\NodeAnalyzer\\ExprUsedInNextNodeAnalyzer' => $baseDir . '/rules/DeadCode/NodeAnalyzer/ExprUsedInNextNodeAnalyzer.php',
'Rector\\DeadCode\\NodeAnalyzer\\ExprUsedInNodeAnalyzer' => $baseDir . '/rules/DeadCode/NodeAnalyzer/ExprUsedInNodeAnalyzer.php',
'Rector\\DeadCode\\NodeAnalyzer\\InstanceOfUniqueKeyResolver' => $baseDir . '/rules/DeadCode/NodeAnalyzer/InstanceOfUniqueKeyResolver.php',
@ -2225,7 +2226,6 @@ return array(
'Rector\\Laravel\\Rector\\FuncCall\\HelperFuncCallToFacadeClassRector' => $vendorDir . '/rector/rector-laravel/src/Rector/FuncCall/HelperFuncCallToFacadeClassRector.php',
'Rector\\Laravel\\Rector\\MethodCall\\ChangeQueryWhereDateValueWithCarbonRector' => $vendorDir . '/rector/rector-laravel/src/Rector/MethodCall/ChangeQueryWhereDateValueWithCarbonRector.php',
'Rector\\Laravel\\Rector\\New_\\AddGuardToLoginEventRector' => $vendorDir . '/rector/rector-laravel/src/Rector/New_/AddGuardToLoginEventRector.php',
'Rector\\Laravel\\Rector\\New_\\MakeTaggedPassedToParameterIterableTypeRector' => $vendorDir . '/rector/rector-laravel/src/Rector/New_/MakeTaggedPassedToParameterIterableTypeRector.php',
'Rector\\Laravel\\Rector\\StaticCall\\MinutesToSecondsInCacheRector' => $vendorDir . '/rector/rector-laravel/src/Rector/StaticCall/MinutesToSecondsInCacheRector.php',
'Rector\\Laravel\\Rector\\StaticCall\\Redirect301ToPermanentRedirectRector' => $vendorDir . '/rector/rector-laravel/src/Rector/StaticCall/Redirect301ToPermanentRedirectRector.php',
'Rector\\Laravel\\Rector\\StaticCall\\RequestStaticValidateToInjectRector' => $vendorDir . '/rector/rector-laravel/src/Rector/StaticCall/RequestStaticValidateToInjectRector.php',
@ -2312,7 +2312,6 @@ return array(
'Rector\\Nette\\FormControlTypeResolver\\VariableConstructorFormControlTypeResolver' => $vendorDir . '/rector/rector-nette/src/FormControlTypeResolver/VariableConstructorFormControlTypeResolver.php',
'Rector\\Nette\\Kdyby\\BlueprintFactory\\VariableWithTypesFactory' => $vendorDir . '/rector/rector-nette/src/Kdyby/BlueprintFactory/VariableWithTypesFactory.php',
'Rector\\Nette\\Kdyby\\ContributeEventClassResolver' => $vendorDir . '/rector/rector-nette/src/Kdyby/ContributeEventClassResolver.php',
'Rector\\Nette\\Kdyby\\DataProvider\\GetSubscribedEventsClassMethodProvider' => $vendorDir . '/rector/rector-nette/src/Kdyby/DataProvider/GetSubscribedEventsClassMethodProvider.php',
'Rector\\Nette\\Kdyby\\Naming\\EventClassNaming' => $vendorDir . '/rector/rector-nette/src/Kdyby/Naming/EventClassNaming.php',
'Rector\\Nette\\Kdyby\\NodeAnalyzer\\GetSubscribedEventsClassMethodAnalyzer' => $vendorDir . '/rector/rector-nette/src/Kdyby/NodeAnalyzer/GetSubscribedEventsClassMethodAnalyzer.php',
'Rector\\Nette\\Kdyby\\NodeFactory\\DispatchMethodCallFactory' => $vendorDir . '/rector/rector-nette/src/Kdyby/NodeFactory/DispatchMethodCallFactory.php',
@ -2353,6 +2352,10 @@ return array(
'Rector\\Nette\\NodeFactory\\CheckRequirementsClassMethodFactory' => $vendorDir . '/rector/rector-nette/src/NodeFactory/CheckRequirementsClassMethodFactory.php',
'Rector\\Nette\\NodeFactory\\ParentGetterStmtsToExternalStmtsFactory' => $vendorDir . '/rector/rector-nette/src/NodeFactory/ParentGetterStmtsToExternalStmtsFactory.php',
'Rector\\Nette\\NodeFactory\\RenderParameterArrayFactory' => $vendorDir . '/rector/rector-nette/src/NodeFactory/RenderParameterArrayFactory.php',
'Rector\\Nette\\NodeFinder\\FormFieldsFinder' => $vendorDir . '/rector/rector-nette/src/NodeFinder/FormFieldsFinder.php',
'Rector\\Nette\\NodeFinder\\FormOnSuccessCallbackFinder' => $vendorDir . '/rector/rector-nette/src/NodeFinder/FormOnSuccessCallbackFinder.php',
'Rector\\Nette\\NodeFinder\\FormOnSuccessCallbackValuesParamFinder' => $vendorDir . '/rector/rector-nette/src/NodeFinder/FormOnSuccessCallbackValuesParamFinder.php',
'Rector\\Nette\\NodeFinder\\FormVariableFinder' => $vendorDir . '/rector/rector-nette/src/NodeFinder/FormVariableFinder.php',
'Rector\\Nette\\NodeFinder\\ParamFinder' => $vendorDir . '/rector/rector-nette/src/NodeFinder/ParamFinder.php',
'Rector\\Nette\\NodeResolver\\FormVariableInputNameTypeResolver' => $vendorDir . '/rector/rector-nette/src/NodeResolver/FormVariableInputNameTypeResolver.php',
'Rector\\Nette\\NodeResolver\\MethodNamesByInputNamesResolver' => $vendorDir . '/rector/rector-nette/src/NodeResolver/MethodNamesByInputNamesResolver.php',
@ -2364,6 +2367,8 @@ return array(
'Rector\\Nette\\Rector\\ClassMethod\\RemoveParentAndNameFromComponentConstructorRector' => $vendorDir . '/rector/rector-nette/src/Rector/ClassMethod/RemoveParentAndNameFromComponentConstructorRector.php',
'Rector\\Nette\\Rector\\ClassMethod\\TemplateMagicAssignToExplicitVariableArrayRector' => $vendorDir . '/rector/rector-nette/src/Rector/ClassMethod/TemplateMagicAssignToExplicitVariableArrayRector.php',
'Rector\\Nette\\Rector\\ClassMethod\\TranslateClassMethodToVariadicsRector' => $vendorDir . '/rector/rector-nette/src/Rector/ClassMethod/TranslateClassMethodToVariadicsRector.php',
'Rector\\Nette\\Rector\\Class_\\FormDataRector' => $vendorDir . '/rector/rector-nette/src/Rector/Class_/FormDataRector.php',
'Rector\\Nette\\Rector\\Class_\\LatteVarTypesBasedOnPresenterTemplateParametersRector' => $vendorDir . '/rector/rector-nette/src/Rector/Class_/LatteVarTypesBasedOnPresenterTemplateParametersRector.php',
'Rector\\Nette\\Rector\\Class_\\MoveFinalGetUserToCheckRequirementsClassMethodRector' => $vendorDir . '/rector/rector-nette/src/Rector/Class_/MoveFinalGetUserToCheckRequirementsClassMethodRector.php',
'Rector\\Nette\\Rector\\Class_\\MoveInjectToExistingConstructorRector' => $vendorDir . '/rector/rector-nette/src/Rector/Class_/MoveInjectToExistingConstructorRector.php',
'Rector\\Nette\\Rector\\FuncCall\\FilePutContentsToFileSystemWriteRector' => $vendorDir . '/rector/rector-nette/src/Rector/FuncCall/FilePutContentsToFileSystemWriteRector.php',
@ -2393,6 +2398,7 @@ return array(
'Rector\\Nette\\ValueObject\\AlwaysTemplateParameterAssign' => $vendorDir . '/rector/rector-nette/src/ValueObject/AlwaysTemplateParameterAssign.php',
'Rector\\Nette\\ValueObject\\ConditionalTemplateParameterAssign' => $vendorDir . '/rector/rector-nette/src/ValueObject/ConditionalTemplateParameterAssign.php',
'Rector\\Nette\\ValueObject\\ContentExprAndNeedleExpr' => $vendorDir . '/rector/rector-nette/src/ValueObject/ContentExprAndNeedleExpr.php',
'Rector\\Nette\\ValueObject\\FormField' => $vendorDir . '/rector/rector-nette/src/ValueObject/FormField.php',
'Rector\\Nette\\ValueObject\\FuncCallAndExpr' => $vendorDir . '/rector/rector-nette/src/ValueObject/FuncCallAndExpr.php',
'Rector\\Nette\\ValueObject\\LatteVariableType' => $vendorDir . '/rector/rector-nette/src/ValueObject/LatteVariableType.php',
'Rector\\Nette\\ValueObject\\NetteFormMethodNameToControlType' => $vendorDir . '/rector/rector-nette/src/ValueObject/NetteFormMethodNameToControlType.php',

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit533369b6f1bebfefbae9ed468dbeb83c
class ComposerAutoloaderInitdf25b088fcc52cbfc899699d2cfd389e
{
private static $loader;
@ -22,15 +22,15 @@ class ComposerAutoloaderInit533369b6f1bebfefbae9ed468dbeb83c
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit533369b6f1bebfefbae9ed468dbeb83c', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInitdf25b088fcc52cbfc899699d2cfd389e', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
spl_autoload_unregister(array('ComposerAutoloaderInit533369b6f1bebfefbae9ed468dbeb83c', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInitdf25b088fcc52cbfc899699d2cfd389e', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit533369b6f1bebfefbae9ed468dbeb83c::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInitdf25b088fcc52cbfc899699d2cfd389e::getInitializer($loader));
} else {
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
@ -42,19 +42,19 @@ class ComposerAutoloaderInit533369b6f1bebfefbae9ed468dbeb83c
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit533369b6f1bebfefbae9ed468dbeb83c::$files;
$includeFiles = Composer\Autoload\ComposerStaticInitdf25b088fcc52cbfc899699d2cfd389e::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire533369b6f1bebfefbae9ed468dbeb83c($fileIdentifier, $file);
composerRequiredf25b088fcc52cbfc899699d2cfd389e($fileIdentifier, $file);
}
return $loader;
}
}
function composerRequire533369b6f1bebfefbae9ed468dbeb83c($fileIdentifier, $file)
function composerRequiredf25b088fcc52cbfc899699d2cfd389e($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file;

View File

@ -4,7 +4,7 @@
namespace Composer\Autoload;
class ComposerStaticInit533369b6f1bebfefbae9ed468dbeb83c
class ComposerStaticInitdf25b088fcc52cbfc899699d2cfd389e
{
public static $files = array (
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
@ -2293,6 +2293,7 @@ class ComposerStaticInit533369b6f1bebfefbae9ed468dbeb83c
'Rector\\DeadCode\\ConditionResolver' => __DIR__ . '/../..' . '/rules/DeadCode/ConditionResolver.php',
'Rector\\DeadCode\\Contract\\ConditionInterface' => __DIR__ . '/../..' . '/rules/DeadCode/Contract/ConditionInterface.php',
'Rector\\DeadCode\\FeatureSupport\\FunctionSupportResolver' => __DIR__ . '/../..' . '/rules/DeadCode/FeatureSupport/FunctionSupportResolver.php',
'Rector\\DeadCode\\NodeAnalyzer\\CallCollectionAnalyzer' => __DIR__ . '/../..' . '/rules/DeadCode/NodeAnalyzer/CallCollectionAnalyzer.php',
'Rector\\DeadCode\\NodeAnalyzer\\ExprUsedInNextNodeAnalyzer' => __DIR__ . '/../..' . '/rules/DeadCode/NodeAnalyzer/ExprUsedInNextNodeAnalyzer.php',
'Rector\\DeadCode\\NodeAnalyzer\\ExprUsedInNodeAnalyzer' => __DIR__ . '/../..' . '/rules/DeadCode/NodeAnalyzer/ExprUsedInNodeAnalyzer.php',
'Rector\\DeadCode\\NodeAnalyzer\\InstanceOfUniqueKeyResolver' => __DIR__ . '/../..' . '/rules/DeadCode/NodeAnalyzer/InstanceOfUniqueKeyResolver.php',
@ -2585,7 +2586,6 @@ class ComposerStaticInit533369b6f1bebfefbae9ed468dbeb83c
'Rector\\Laravel\\Rector\\FuncCall\\HelperFuncCallToFacadeClassRector' => __DIR__ . '/..' . '/rector/rector-laravel/src/Rector/FuncCall/HelperFuncCallToFacadeClassRector.php',
'Rector\\Laravel\\Rector\\MethodCall\\ChangeQueryWhereDateValueWithCarbonRector' => __DIR__ . '/..' . '/rector/rector-laravel/src/Rector/MethodCall/ChangeQueryWhereDateValueWithCarbonRector.php',
'Rector\\Laravel\\Rector\\New_\\AddGuardToLoginEventRector' => __DIR__ . '/..' . '/rector/rector-laravel/src/Rector/New_/AddGuardToLoginEventRector.php',
'Rector\\Laravel\\Rector\\New_\\MakeTaggedPassedToParameterIterableTypeRector' => __DIR__ . '/..' . '/rector/rector-laravel/src/Rector/New_/MakeTaggedPassedToParameterIterableTypeRector.php',
'Rector\\Laravel\\Rector\\StaticCall\\MinutesToSecondsInCacheRector' => __DIR__ . '/..' . '/rector/rector-laravel/src/Rector/StaticCall/MinutesToSecondsInCacheRector.php',
'Rector\\Laravel\\Rector\\StaticCall\\Redirect301ToPermanentRedirectRector' => __DIR__ . '/..' . '/rector/rector-laravel/src/Rector/StaticCall/Redirect301ToPermanentRedirectRector.php',
'Rector\\Laravel\\Rector\\StaticCall\\RequestStaticValidateToInjectRector' => __DIR__ . '/..' . '/rector/rector-laravel/src/Rector/StaticCall/RequestStaticValidateToInjectRector.php',
@ -2672,7 +2672,6 @@ class ComposerStaticInit533369b6f1bebfefbae9ed468dbeb83c
'Rector\\Nette\\FormControlTypeResolver\\VariableConstructorFormControlTypeResolver' => __DIR__ . '/..' . '/rector/rector-nette/src/FormControlTypeResolver/VariableConstructorFormControlTypeResolver.php',
'Rector\\Nette\\Kdyby\\BlueprintFactory\\VariableWithTypesFactory' => __DIR__ . '/..' . '/rector/rector-nette/src/Kdyby/BlueprintFactory/VariableWithTypesFactory.php',
'Rector\\Nette\\Kdyby\\ContributeEventClassResolver' => __DIR__ . '/..' . '/rector/rector-nette/src/Kdyby/ContributeEventClassResolver.php',
'Rector\\Nette\\Kdyby\\DataProvider\\GetSubscribedEventsClassMethodProvider' => __DIR__ . '/..' . '/rector/rector-nette/src/Kdyby/DataProvider/GetSubscribedEventsClassMethodProvider.php',
'Rector\\Nette\\Kdyby\\Naming\\EventClassNaming' => __DIR__ . '/..' . '/rector/rector-nette/src/Kdyby/Naming/EventClassNaming.php',
'Rector\\Nette\\Kdyby\\NodeAnalyzer\\GetSubscribedEventsClassMethodAnalyzer' => __DIR__ . '/..' . '/rector/rector-nette/src/Kdyby/NodeAnalyzer/GetSubscribedEventsClassMethodAnalyzer.php',
'Rector\\Nette\\Kdyby\\NodeFactory\\DispatchMethodCallFactory' => __DIR__ . '/..' . '/rector/rector-nette/src/Kdyby/NodeFactory/DispatchMethodCallFactory.php',
@ -2713,6 +2712,10 @@ class ComposerStaticInit533369b6f1bebfefbae9ed468dbeb83c
'Rector\\Nette\\NodeFactory\\CheckRequirementsClassMethodFactory' => __DIR__ . '/..' . '/rector/rector-nette/src/NodeFactory/CheckRequirementsClassMethodFactory.php',
'Rector\\Nette\\NodeFactory\\ParentGetterStmtsToExternalStmtsFactory' => __DIR__ . '/..' . '/rector/rector-nette/src/NodeFactory/ParentGetterStmtsToExternalStmtsFactory.php',
'Rector\\Nette\\NodeFactory\\RenderParameterArrayFactory' => __DIR__ . '/..' . '/rector/rector-nette/src/NodeFactory/RenderParameterArrayFactory.php',
'Rector\\Nette\\NodeFinder\\FormFieldsFinder' => __DIR__ . '/..' . '/rector/rector-nette/src/NodeFinder/FormFieldsFinder.php',
'Rector\\Nette\\NodeFinder\\FormOnSuccessCallbackFinder' => __DIR__ . '/..' . '/rector/rector-nette/src/NodeFinder/FormOnSuccessCallbackFinder.php',
'Rector\\Nette\\NodeFinder\\FormOnSuccessCallbackValuesParamFinder' => __DIR__ . '/..' . '/rector/rector-nette/src/NodeFinder/FormOnSuccessCallbackValuesParamFinder.php',
'Rector\\Nette\\NodeFinder\\FormVariableFinder' => __DIR__ . '/..' . '/rector/rector-nette/src/NodeFinder/FormVariableFinder.php',
'Rector\\Nette\\NodeFinder\\ParamFinder' => __DIR__ . '/..' . '/rector/rector-nette/src/NodeFinder/ParamFinder.php',
'Rector\\Nette\\NodeResolver\\FormVariableInputNameTypeResolver' => __DIR__ . '/..' . '/rector/rector-nette/src/NodeResolver/FormVariableInputNameTypeResolver.php',
'Rector\\Nette\\NodeResolver\\MethodNamesByInputNamesResolver' => __DIR__ . '/..' . '/rector/rector-nette/src/NodeResolver/MethodNamesByInputNamesResolver.php',
@ -2724,6 +2727,8 @@ class ComposerStaticInit533369b6f1bebfefbae9ed468dbeb83c
'Rector\\Nette\\Rector\\ClassMethod\\RemoveParentAndNameFromComponentConstructorRector' => __DIR__ . '/..' . '/rector/rector-nette/src/Rector/ClassMethod/RemoveParentAndNameFromComponentConstructorRector.php',
'Rector\\Nette\\Rector\\ClassMethod\\TemplateMagicAssignToExplicitVariableArrayRector' => __DIR__ . '/..' . '/rector/rector-nette/src/Rector/ClassMethod/TemplateMagicAssignToExplicitVariableArrayRector.php',
'Rector\\Nette\\Rector\\ClassMethod\\TranslateClassMethodToVariadicsRector' => __DIR__ . '/..' . '/rector/rector-nette/src/Rector/ClassMethod/TranslateClassMethodToVariadicsRector.php',
'Rector\\Nette\\Rector\\Class_\\FormDataRector' => __DIR__ . '/..' . '/rector/rector-nette/src/Rector/Class_/FormDataRector.php',
'Rector\\Nette\\Rector\\Class_\\LatteVarTypesBasedOnPresenterTemplateParametersRector' => __DIR__ . '/..' . '/rector/rector-nette/src/Rector/Class_/LatteVarTypesBasedOnPresenterTemplateParametersRector.php',
'Rector\\Nette\\Rector\\Class_\\MoveFinalGetUserToCheckRequirementsClassMethodRector' => __DIR__ . '/..' . '/rector/rector-nette/src/Rector/Class_/MoveFinalGetUserToCheckRequirementsClassMethodRector.php',
'Rector\\Nette\\Rector\\Class_\\MoveInjectToExistingConstructorRector' => __DIR__ . '/..' . '/rector/rector-nette/src/Rector/Class_/MoveInjectToExistingConstructorRector.php',
'Rector\\Nette\\Rector\\FuncCall\\FilePutContentsToFileSystemWriteRector' => __DIR__ . '/..' . '/rector/rector-nette/src/Rector/FuncCall/FilePutContentsToFileSystemWriteRector.php',
@ -2753,6 +2758,7 @@ class ComposerStaticInit533369b6f1bebfefbae9ed468dbeb83c
'Rector\\Nette\\ValueObject\\AlwaysTemplateParameterAssign' => __DIR__ . '/..' . '/rector/rector-nette/src/ValueObject/AlwaysTemplateParameterAssign.php',
'Rector\\Nette\\ValueObject\\ConditionalTemplateParameterAssign' => __DIR__ . '/..' . '/rector/rector-nette/src/ValueObject/ConditionalTemplateParameterAssign.php',
'Rector\\Nette\\ValueObject\\ContentExprAndNeedleExpr' => __DIR__ . '/..' . '/rector/rector-nette/src/ValueObject/ContentExprAndNeedleExpr.php',
'Rector\\Nette\\ValueObject\\FormField' => __DIR__ . '/..' . '/rector/rector-nette/src/ValueObject/FormField.php',
'Rector\\Nette\\ValueObject\\FuncCallAndExpr' => __DIR__ . '/..' . '/rector/rector-nette/src/ValueObject/FuncCallAndExpr.php',
'Rector\\Nette\\ValueObject\\LatteVariableType' => __DIR__ . '/..' . '/rector/rector-nette/src/ValueObject/LatteVariableType.php',
'Rector\\Nette\\ValueObject\\NetteFormMethodNameToControlType' => __DIR__ . '/..' . '/rector/rector-nette/src/ValueObject/NetteFormMethodNameToControlType.php',
@ -3844,9 +3850,9 @@ class ComposerStaticInit533369b6f1bebfefbae9ed468dbeb83c
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInit533369b6f1bebfefbae9ed468dbeb83c::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit533369b6f1bebfefbae9ed468dbeb83c::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit533369b6f1bebfefbae9ed468dbeb83c::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInitdf25b088fcc52cbfc899699d2cfd389e::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInitdf25b088fcc52cbfc899699d2cfd389e::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInitdf25b088fcc52cbfc899699d2cfd389e::$classMap;
}, null, ClassLoader::class);
}

View File

@ -1287,17 +1287,17 @@
},
{
"name": "rector\/rector-laravel",
"version": "0.11.4",
"version_normalized": "0.11.4.0",
"version": "0.11.5",
"version_normalized": "0.11.5.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/rectorphp\/rector-laravel.git",
"reference": "d19c1666aa753d863a2b7296da9ea3eeabe38671"
"reference": "6c5f56c2655039052ef3fe4301596241421d7ee9"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-laravel\/zipball\/d19c1666aa753d863a2b7296da9ea3eeabe38671",
"reference": "d19c1666aa753d863a2b7296da9ea3eeabe38671",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-laravel\/zipball\/6c5f56c2655039052ef3fe4301596241421d7ee9",
"reference": "6c5f56c2655039052ef3fe4301596241421d7ee9",
"shasum": ""
},
"require": {
@ -1316,7 +1316,7 @@
"symplify\/phpstan-rules": "^9.4",
"symplify\/rule-doc-generator": "^9.4"
},
"time": "2021-07-06T14:18:21+00:00",
"time": "2021-08-05T10:22:16+00:00",
"type": "rector-extension",
"extra": {
"branch-alias": {
@ -1341,23 +1341,23 @@
"description": "Rector upgrades rules for Laravel Framework",
"support": {
"issues": "https:\/\/github.com\/rectorphp\/rector-laravel\/issues",
"source": "https:\/\/github.com\/rectorphp\/rector-laravel\/tree\/0.11.4"
"source": "https:\/\/github.com\/rectorphp\/rector-laravel\/tree\/0.11.5"
},
"install-path": "..\/rector\/rector-laravel"
},
{
"name": "rector\/rector-nette",
"version": "0.11.18",
"version_normalized": "0.11.18.0",
"version": "0.11.20",
"version_normalized": "0.11.20.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/rectorphp\/rector-nette.git",
"reference": "b95ea8b6a6191221100cac0e9578cf64d3f748ca"
"reference": "91163c5055afb9d5405eb44dba1dcb037c545035"
},
"dist": {
"type": "zip",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-nette\/zipball\/b95ea8b6a6191221100cac0e9578cf64d3f748ca",
"reference": "b95ea8b6a6191221100cac0e9578cf64d3f748ca",
"url": "https:\/\/api.github.com\/repos\/rectorphp\/rector-nette\/zipball\/91163c5055afb9d5405eb44dba1dcb037c545035",
"reference": "91163c5055afb9d5405eb44dba1dcb037c545035",
"shasum": ""
},
"require": {
@ -1383,7 +1383,7 @@
"symplify\/phpstan-rules": "^9.4",
"symplify\/rule-doc-generator": "^9.4"
},
"time": "2021-07-25T11:50:31+00:00",
"time": "2021-08-05T12:27:39+00:00",
"type": "rector-extension",
"extra": {
"branch-alias": {
@ -1408,7 +1408,7 @@
"description": "Rector upgrades rules for Nette Framework",
"support": {
"issues": "https:\/\/github.com\/rectorphp\/rector-nette\/issues",
"source": "https:\/\/github.com\/rectorphp\/rector-nette\/tree\/0.11.18"
"source": "https:\/\/github.com\/rectorphp\/rector-nette\/tree\/0.11.20"
},
"install-path": "..\/rector\/rector-nette"
},
@ -1535,8 +1535,8 @@
},
{
"name": "rector\/rector-symfony",
"version": "0.11.15",
"version_normalized": "0.11.15.0",
"version": "0.11.16",
"version_normalized": "0.11.16.0",
"source": {
"type": "git",
"url": "https:\/\/github.com\/rectorphp\/rector-symfony.git",
@ -1593,7 +1593,7 @@
"description": "Rector upgrades rules for Symfony Framework",
"support": {
"issues": "https:\/\/github.com\/rectorphp\/rector-symfony\/issues",
"source": "https:\/\/github.com\/rectorphp\/rector-symfony\/tree\/0.11.15"
"source": "https:\/\/github.com\/rectorphp\/rector-symfony\/tree\/0.11.16"
},
"install-path": "..\/rector\/rector-symfony"
},

File diff suppressed because one or more lines are too long

View File

@ -9,7 +9,7 @@ namespace Rector\RectorInstaller;
*/
final class GeneratedConfig
{
public const EXTENSIONS = array('rector/rector-cakephp' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-cakephp', 'relative_install_path' => '../../rector-cakephp', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.3'), 'rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.14'), 'rector/rector-laravel' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-laravel', 'relative_install_path' => '../../rector-laravel', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.4'), 'rector/rector-nette' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-nette', 'relative_install_path' => '../../rector-nette', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.18'), 'rector/rector-phpoffice' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpoffice', 'relative_install_path' => '../../rector-phpoffice', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.2'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.7'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.15'), 'ssch/typo3-rector' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/ssch/typo3-rector', 'relative_install_path' => '../../../ssch/typo3-rector', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'v0.11.22'));
public const EXTENSIONS = array('rector/rector-cakephp' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-cakephp', 'relative_install_path' => '../../rector-cakephp', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.3'), 'rector/rector-doctrine' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-doctrine', 'relative_install_path' => '../../rector-doctrine', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.14'), 'rector/rector-laravel' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-laravel', 'relative_install_path' => '../../rector-laravel', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.5'), 'rector/rector-nette' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-nette', 'relative_install_path' => '../../rector-nette', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.20'), 'rector/rector-phpoffice' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpoffice', 'relative_install_path' => '../../rector-phpoffice', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.2'), 'rector/rector-phpunit' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-phpunit', 'relative_install_path' => '../../rector-phpunit', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.7'), 'rector/rector-symfony' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/rector/rector-symfony', 'relative_install_path' => '../../rector-symfony', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => '0.11.16'), 'ssch/typo3-rector' => array('install_path' => '/home/runner/work/rector-src/rector-src/vendor/ssch/typo3-rector', 'relative_install_path' => '../../../ssch/typo3-rector', 'extra' => array('includes' => array(0 => 'config/config.php')), 'version' => 'v0.11.22'));
private function __construct()
{
}

View File

@ -5,7 +5,6 @@ namespace RectorPrefix20210805;
use PHPStan\Type\BooleanType;
use Rector\Laravel\Rector\Class_\PropertyDeferToDeferrableProviderToRector;
use Rector\Laravel\Rector\New_\MakeTaggedPassedToParameterIterableTypeRector;
use Rector\Laravel\Rector\StaticCall\MinutesToSecondsInCacheRector;
use Rector\Renaming\Rector\PropertyFetch\RenamePropertyRector;
use Rector\Renaming\ValueObject\RenameProperty;
@ -23,5 +22,4 @@ return static function (\Symfony\Component\DependencyInjection\Loader\Configurat
$services->set(\Rector\TypeDeclaration\Rector\ClassMethod\AddReturnTypeDeclarationRector::class)->call('configure', [[\Rector\TypeDeclaration\Rector\ClassMethod\AddReturnTypeDeclarationRector::METHOD_RETURN_TYPES => \Symplify\SymfonyPhpConfig\ValueObjectInliner::inline([new \Rector\TypeDeclaration\ValueObject\AddReturnTypeDeclaration('Illuminate\\Contracts\\Cache\\Repository', 'put', new \PHPStan\Type\BooleanType()), new \Rector\TypeDeclaration\ValueObject\AddReturnTypeDeclaration('Illuminate\\Contracts\\Cache\\Repository', 'forever', new \PHPStan\Type\BooleanType()), new \Rector\TypeDeclaration\ValueObject\AddReturnTypeDeclaration('Illuminate\\Contracts\\Cache\\Store', 'put', new \PHPStan\Type\BooleanType()), new \Rector\TypeDeclaration\ValueObject\AddReturnTypeDeclaration('Illuminate\\Contracts\\Cache\\Store', 'putMany', new \PHPStan\Type\BooleanType()), new \Rector\TypeDeclaration\ValueObject\AddReturnTypeDeclaration('Illuminate\\Contracts\\Cache\\Store', 'forever', new \PHPStan\Type\BooleanType())])]]);
$services->set(\Rector\Renaming\Rector\PropertyFetch\RenamePropertyRector::class)->call('configure', [[\Rector\Renaming\Rector\PropertyFetch\RenamePropertyRector::RENAMED_PROPERTIES => \Symplify\SymfonyPhpConfig\ValueObjectInliner::inline([new \Rector\Renaming\ValueObject\RenameProperty('Illuminate\\Routing\\UrlGenerator', 'cachedSchema', 'cachedScheme')])]]);
$services->set(\Rector\Laravel\Rector\Class_\PropertyDeferToDeferrableProviderToRector::class);
$services->set(\Rector\Laravel\Rector\New_\MakeTaggedPassedToParameterIterableTypeRector::class);
};

View File

@ -11,8 +11,6 @@ use Rector\Renaming\Rector\Name\RenameClassRector;
use Rector\Renaming\Rector\StaticCall\RenameStaticMethodRector;
use Rector\Renaming\ValueObject\MethodCallRename;
use Rector\Renaming\ValueObject\RenameStaticMethod;
use Rector\Transform\Rector\Expression\MethodCallToReturnRector;
use Rector\Transform\ValueObject\MethodCallToReturn;
use Rector\TypeDeclaration\Rector\FunctionLike\ParamTypeDeclarationRector;
use Rector\Visibility\Rector\ClassMethod\ChangeMethodVisibilityRector;
use Rector\Visibility\ValueObject\ChangeMethodVisibility;
@ -22,7 +20,6 @@ use Symplify\SymfonyPhpConfig\ValueObjectInliner;
# https://github.com/laravel/docs/pull/5531/files
return static function (\Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator $containerConfigurator) : void {
$services = $containerConfigurator->services();
$services->set(\Rector\Transform\Rector\Expression\MethodCallToReturnRector::class)->call('configure', [[\Rector\Transform\Rector\Expression\MethodCallToReturnRector::METHOD_CALL_WRAPS => \Symplify\SymfonyPhpConfig\ValueObjectInliner::inline([new \Rector\Transform\ValueObject\MethodCallToReturn('Illuminate\\Auth\\Access\\HandlesAuthorization', 'deny')])]]);
# https://github.com/laravel/framework/commit/67a38ba0fa2acfbd1f4af4bf7d462bb4419cc091
$services->set(\Rector\TypeDeclaration\Rector\FunctionLike\ParamTypeDeclarationRector::class);
$services->set(\Rector\Renaming\Rector\MethodCall\RenameMethodRector::class)->call('configure', [[\Rector\Renaming\Rector\MethodCall\RenameMethodRector::METHOD_CALL_RENAMES => \Symplify\SymfonyPhpConfig\ValueObjectInliner::inline([new \Rector\Renaming\ValueObject\MethodCallRename(

View File

@ -1,113 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Laravel\Rector\New_;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\MethodName;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\PHPStanStaticTypeMapper\ValueObject\TypeKind;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see https://laravel.com/docs/5.8/upgrade#container-generators
*
* @see \Rector\Laravel\Tests\Rector\New_\MakeTaggedPassedToParameterIterableTypeRector\MakeTaggedPassedToParameterIterableTypeRectorTest
*/
final class MakeTaggedPassedToParameterIterableTypeRector extends \Rector\Core\Rector\AbstractRector
{
public function getRuleDefinition() : \Symplify\RuleDocGenerator\ValueObject\RuleDefinition
{
return new \Symplify\RuleDocGenerator\ValueObject\RuleDefinition('Change param type to iterable, if passed one', [new \Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample(<<<'CODE_SAMPLE'
class AnotherClass
{
/**
* @var \Illuminate\Contracts\Foundation\Application
*/
private $app;
public function create()
{
$tagged = $this->app->tagged('some_tagged');
return new SomeClass($tagged);
}
}
class SomeClass
{
public function __construct(array $items)
{
}
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
class AnotherClass
{
/**
* @var \Illuminate\Contracts\Foundation\Application
*/
private $app;
public function create()
{
$tagged = $this->app->tagged('some_tagged');
return new SomeClass($tagged);
}
}
class SomeClass
{
public function __construct(iterable $items)
{
}
}
CODE_SAMPLE
)]);
}
/**
* @return array<class-string<Node>>
*/
public function getNodeTypes() : array
{
return [\PhpParser\Node\Expr\New_::class];
}
/**
* @param New_ $node
*/
public function refactor(\PhpParser\Node $node) : ?\PhpParser\Node
{
$className = $this->getName($node->class);
if ($className === null) {
return null;
}
$class = $this->nodeRepository->findClass($className);
if (!$class instanceof \PhpParser\Node\Stmt\Class_) {
return null;
}
foreach ($node->args as $arg) {
$this->refactorClassWithArgType($class, $arg);
}
return null;
}
private function refactorClassWithArgType(\PhpParser\Node\Stmt\Class_ $class, \PhpParser\Node\Arg $arg) : void
{
$argValueType = $this->getStaticType($arg->value);
$constructClassMethod = $class->getMethod(\Rector\Core\ValueObject\MethodName::CONSTRUCT);
$argumentPosition = (int) $arg->getAttribute(\Rector\NodeTypeResolver\Node\AttributeKey::ARGUMENT_POSITION);
if (!$constructClassMethod instanceof \PhpParser\Node\Stmt\ClassMethod) {
return;
}
$param = $constructClassMethod->params[$argumentPosition] ?? null;
if (!$param instanceof \PhpParser\Node\Param) {
return;
}
$argTypeNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($argValueType, \Rector\PHPStanStaticTypeMapper\ValueObject\TypeKind::PARAM());
$param->type = $argTypeNode;
}
}

View File

@ -23,10 +23,6 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
*/
final class MinutesToSecondsInCacheRector extends \Rector\Core\Rector\AbstractRector
{
/**
* @var string
*/
private const ATTRIBUTE_KEY_ALREADY_MULTIPLIED = 'already_multiplied';
/**
* @var string
*/
@ -110,15 +106,12 @@ CODE_SAMPLE
if (!$this->nodeTypeResolver->isNumberType($argExpr)) {
return null;
}
$mul = $this->mulByNumber($argExpr, 60);
// already multiplied
if ($argExpr instanceof \PhpParser\Node\Expr\BinaryOp\Mul) {
return null;
}
$mul = new \PhpParser\Node\Expr\BinaryOp\Mul($argExpr, new \PhpParser\Node\Scalar\LNumber(60));
$node->args[$argumentPosition] = new \PhpParser\Node\Arg($mul);
return $node;
}
private function mulByNumber(\PhpParser\Node\Expr $argExpr, int $value) : \PhpParser\Node\Expr
{
if ($this->valueResolver->isValue($argExpr, 1)) {
return new \PhpParser\Node\Scalar\LNumber($value);
}
return new \PhpParser\Node\Expr\BinaryOp\Mul($argExpr, new \PhpParser\Node\Scalar\LNumber($value));
}
}

View File

@ -117,32 +117,6 @@ Change `containerBuilder->expand()` to static call with parameters
<br>
## ChangeFormArrayAccessToAnnotatedControlVariableRector
Change array access magic on `$form` to explicit standalone typed variable
- class: [`Rector\Nette\Rector\ArrayDimFetch\ChangeFormArrayAccessToAnnotatedControlVariableRector`](../src/Rector/ArrayDimFetch/ChangeFormArrayAccessToAnnotatedControlVariableRector.php)
```diff
use Nette\Application\UI\Form;
class SomePresenter
{
public function run()
{
$form = new Form();
$this->addText('email', 'Email');
- $form['email']->value = 'hey@hi.hello';
+ /** @var \Nette\Forms\Controls\TextInput $emailControl */
+ $emailControl = $form['email'];
+ $emailControl->value = 'hey@hi.hello';
}
}
```
<br>
## ChangeNetteEventNamesInGetSubscribedEventsRector
Change EventSubscriber from Kdyby to Contributte
@ -264,6 +238,56 @@ Change `file_put_contents()` to `FileSystem::write()`
<br>
## FormDataRector
Create form data class with all fields of Form
:wrench: **configure it!**
- class: [`Rector\Nette\Rector\Class_\FormDataRector`](../src/Rector/Class_/FormDataRector.php)
```php
use Rector\Nette\Rector\Class_\FormDataRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(FormDataRector::class)
->call('configure', [[
FormDataRector::FORM_DATA_CLASS_PARENT => '',
FormDataRector::FORM_DATA_CLASS_TRAITS => [],
]]);
};
```
```diff
+class MyFormFactoryFormData
+{
+ public string $foo;
+ public string $bar;
+}
+
class MyFormFactory
{
public function create()
{
$form = new Form();
$form->addText('foo', 'Foo');
$form->addText('bar', 'Bar')->setRequired();
- $form->onSuccess[] = function (Form $form, ArrayHash $values) {
+ $form->onSuccess[] = function (Form $form, MyFormFactoryFormData $values) {
// do something
}
}
}
```
<br>
## JsonDecodeEncodeToNetteUtilsJsonDecodeEncodeRector
Changes `json_encode()/json_decode()` to safer and more verbose `Nette\Utils\Json::encode()/decode()` calls
@ -297,6 +321,37 @@ Changes `json_encode()/json_decode()` to safer and more verbose `Nette\Utils\Jso
<br>
## LatteVarTypesBasedOnPresenterTemplateParametersRector
Adds latte {varType}s based on presenter `$this->template` parameters
- class: [`Rector\Nette\Rector\Class_\LatteVarTypesBasedOnPresenterTemplateParametersRector`](../src/Rector/Class_/LatteVarTypesBasedOnPresenterTemplateParametersRector.php)
```diff
// presenters/SomePresenter.php
<?php
use Nette\Application\UI\Presenter;
class SomePresenter extends Presenter
{
public function renderDefault(): void
{
$this->template->title = 'My title';
$this->template->count = 123;
}
}
// templates/Some/default.latte
+{varType string $title}
+{varType int $count}
+
<h1>{$title}</h1>
<span class="count">{$count}</span>
```
<br>
## MagicHtmlCallToAppendAttributeRector
Change magic `addClass()` etc. calls on Html to explicit methods
@ -610,64 +665,6 @@ Change Kdyby EventManager to EventDispatcher
<br>
## ReplaceMagicPropertyEventWithEventClassRector
Change `$onProperty` magic call with event disptacher and class dispatch
- class: [`Rector\Nette\Kdyby\Rector\MethodCall\ReplaceMagicPropertyEventWithEventClassRector`](../src/Kdyby/Rector/MethodCall/ReplaceMagicPropertyEventWithEventClassRector.php)
```diff
final class FileManager
{
- public $onUpload;
+ use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
+ public function __construct(EventDispatcherInterface $eventDispatcher)
+ {
+ $this->eventDispatcher = $eventDispatcher;
+ }
+
public function run(User $user)
{
- $this->onUpload($user);
+ $onFileManagerUploadEvent = new FileManagerUploadEvent($user);
+ $this->eventDispatcher->dispatch($onFileManagerUploadEvent);
}
}
```
<br>
## ReplaceMagicPropertyWithEventClassRector
Change `getSubscribedEvents()` from on magic property, to Event class
- class: [`Rector\Nette\Kdyby\Rector\ClassMethod\ReplaceMagicPropertyWithEventClassRector`](../src/Kdyby/Rector/ClassMethod/ReplaceMagicPropertyWithEventClassRector.php)
```diff
use Kdyby\Events\Subscriber;
final class ActionLogEventSubscriber implements Subscriber
{
public function getSubscribedEvents(): array
{
return [
- AlbumService::class . '::onApprove' => 'onAlbumApprove',
+ AlbumServiceApproveEvent::class => 'onAlbumApprove',
];
}
- public function onAlbumApprove(Album $album, int $adminId): void
+ public function onAlbumApprove(AlbumServiceApproveEventAlbum $albumServiceApproveEventAlbum): void
{
+ $album = $albumServiceApproveEventAlbum->getAlbum();
$album->play();
}
}
```
<br>
## ReplaceTimeNumberWithDateTimeConstantRector
Replace time numbers with `Nette\Utils\DateTime` constants
@ -849,3 +846,28 @@ Change `translate()` method call 2nd arg to variadic
```
<br>
## WrapTransParameterNameRector
Adds %% to placeholder name of `trans()` method if missing
- class: [`Rector\Nette\Kdyby\Rector\MethodCall\WrapTransParameterNameRector`](../src/Kdyby/Rector/MethodCall/WrapTransParameterNameRector.php)
```diff
use Symfony\Component\Translation\Translator;
final class SomeController
{
public function run()
{
$translator = new Translator('');
$translated = $translator->trans(
'Hello %name%',
- ['name' => $name]
+ ['%name%' => $name]
);
}
}
```
<br>

View File

@ -1,34 +0,0 @@
<?php
declare (strict_types=1);
namespace Rector\Nette\Kdyby\DataProvider;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\NodeCollector\NodeCollector\NodeRepository;
final class GetSubscribedEventsClassMethodProvider
{
/**
* @var \Rector\NodeCollector\NodeCollector\NodeRepository
*/
private $nodeRepository;
public function __construct(\Rector\NodeCollector\NodeCollector\NodeRepository $nodeRepository)
{
$this->nodeRepository = $nodeRepository;
}
/**
* @return ClassMethod[]
*/
public function provide() : array
{
$subscriberClasses = $this->nodeRepository->findClassesAndInterfacesByType('Kdyby\\Events\\Subscriber');
$classMethods = [];
foreach ($subscriberClasses as $subscriberClass) {
$subscribedEventsClassMethod = $subscriberClass->getMethod('getSubscribedEvents');
if ($subscribedEventsClassMethod === null) {
continue;
}
$classMethods[] = $subscribedEventsClassMethod;
}
return $classMethods;
}
}

View File

@ -0,0 +1,155 @@
<?php
declare (strict_types=1);
namespace Rector\Nette\NodeFinder;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Identifier;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Expression;
use PHPStan\Type\ObjectType;
use Rector\Nette\ValueObject\FormField;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\NodeTypeResolver;
/**
* @see \Rector\Nette\Tests\NodeFinder\FormFinder\FormFinderTest
*/
final class FormFieldsFinder
{
/**
* @var \Rector\NodeTypeResolver\NodeTypeResolver
*/
private $nodeTypeResolver;
/**
* @var \Rector\NodeNameResolver\NodeNameResolver
*/
private $nodeNameResolver;
public function __construct(\Rector\NodeTypeResolver\NodeTypeResolver $nodeTypeResolver, \Rector\NodeNameResolver\NodeNameResolver $nodeNameResolver)
{
$this->nodeTypeResolver = $nodeTypeResolver;
$this->nodeNameResolver = $nodeNameResolver;
}
/**
* @return FormField[]
*/
public function find(\PhpParser\Node\Stmt\Class_ $class, \PhpParser\Node\Expr\Variable $form) : array
{
$formFields = [];
foreach ($class->getMethods() as $method) {
foreach ($method->stmts ?: [] as $stmt) {
if (!$stmt instanceof \PhpParser\Node\Stmt\Expression) {
continue;
}
$methodCall = $this->findMethodCall($stmt);
if ($methodCall === null) {
continue;
}
$addFieldMethodCall = $this->findAddFieldMethodCall($methodCall);
if (!$addFieldMethodCall) {
continue;
}
if (!$this->isFormAddFieldMethodCall($addFieldMethodCall, $form)) {
continue;
}
$formFields = $this->addFormField($formFields, $addFieldMethodCall, $methodCall);
}
}
return $formFields;
}
private function findMethodCall(\PhpParser\Node\Stmt\Expression $expression) : ?\PhpParser\Node\Expr\MethodCall
{
$methodCall = null;
if ($expression->expr instanceof \PhpParser\Node\Expr\MethodCall) {
$methodCall = $expression->expr;
} elseif ($expression->expr instanceof \PhpParser\Node\Expr\Assign && $expression->expr->expr instanceof \PhpParser\Node\Expr\MethodCall) {
$methodCall = $expression->expr->expr;
}
return $methodCall;
}
private function findAddFieldMethodCall(\PhpParser\Node\Expr\MethodCall $methodCall) : ?\PhpParser\Node\Expr\MethodCall
{
if ($methodCall->var instanceof \PhpParser\Node\Expr\Variable) {
// skip submit buttons
if ($this->nodeTypeResolver->isObjectType($methodCall, new \PHPStan\Type\ObjectType('Nette\\Forms\\Controls\\SubmitButton'))) {
return null;
}
if ($this->nodeTypeResolver->isObjectType($methodCall, new \PHPStan\Type\ObjectType('Nette\\Forms\\Container'))) {
return $methodCall;
}
// skip groups, renderers, translator etc.
if ($this->nodeTypeResolver->isObjectType($methodCall, new \PHPStan\Type\ObjectType('Nette\\Forms\\Controls\\BaseControl'))) {
return $methodCall;
}
return null;
}
if ($methodCall->var instanceof \PhpParser\Node\Expr\MethodCall) {
return $this->findAddFieldMethodCall($methodCall->var);
}
return null;
}
private function isFormAddFieldMethodCall(\PhpParser\Node\Expr\MethodCall $addFieldMethodCall, \PhpParser\Node\Expr\Variable $form) : bool
{
$methodCallVariable = $this->findMethodCallVariable($addFieldMethodCall);
if ($methodCallVariable === null) {
return \false;
}
if ($methodCallVariable->name !== $form->name) {
return \false;
}
return \true;
}
private function findMethodCallVariable(\PhpParser\Node\Expr\MethodCall $methodCall) : ?\PhpParser\Node\Expr\Variable
{
if ($methodCall->var instanceof \PhpParser\Node\Expr\Variable) {
return $methodCall->var;
}
if ($methodCall->var instanceof \PhpParser\Node\Expr\MethodCall) {
return $this->findMethodCallVariable($methodCall->var);
}
return null;
}
/**
* @param FormField[] $formFields
* @return FormField[]
*/
private function addFormField(array $formFields, \PhpParser\Node\Expr\MethodCall $addFieldMethodCall, \PhpParser\Node\Expr\MethodCall $methodCall) : array
{
$arg = $addFieldMethodCall->args[0] ?? null;
if (!$arg) {
return $formFields;
}
$name = $arg->value;
if (!$name instanceof \PhpParser\Node\Scalar\String_) {
return $formFields;
}
$formFields[] = new \Rector\Nette\ValueObject\FormField($name->value, $this->resolveFieldType($this->nodeNameResolver->getName($addFieldMethodCall->name)), $this->isFieldRequired($methodCall));
return $formFields;
}
private function isFieldRequired(\PhpParser\Node\Expr\MethodCall $methodCall) : bool
{
if ($methodCall->name instanceof \PhpParser\Node\Identifier && $methodCall->name->name === 'setRequired') {
// TODO addRule(Form:FILLED) is also required
return \true;
}
if ($methodCall->var instanceof \PhpParser\Node\Expr\MethodCall) {
return $this->isFieldRequired($methodCall->var);
}
return \false;
}
private function resolveFieldType(?string $methodName) : string
{
switch ($methodName) {
case 'addInteger':
return 'int';
case 'addContainer':
return 'array';
case 'addCheckbox':
return 'bool';
default:
return 'string';
}
}
}

View File

@ -0,0 +1,59 @@
<?php
declare (strict_types=1);
namespace Rector\Nette\NodeFinder;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\ArrayDimFetch;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Identifier;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Expression;
final class FormOnSuccessCallbackFinder
{
public function find(\PhpParser\Node\Stmt\Class_ $class, \PhpParser\Node\Expr\Variable $form) : ?\PhpParser\Node\Expr
{
foreach ($class->getMethods() as $method) {
$stmts = $method->stmts ?: [];
foreach ($stmts as $stmt) {
if (!$stmt instanceof \PhpParser\Node\Stmt\Expression) {
continue;
}
if (!$stmt->expr instanceof \PhpParser\Node\Expr\Assign) {
continue;
}
if (!$stmt->expr->var instanceof \PhpParser\Node\Expr\ArrayDimFetch) {
continue;
}
/** @var ArrayDimFetch $arrayDimFetch */
$arrayDimFetch = $stmt->expr->var;
if (!$this->isFormOnSuccess($arrayDimFetch, $form)) {
continue;
}
return $stmt->expr->expr;
}
}
return null;
}
private function isFormOnSuccess(\PhpParser\Node\Expr\ArrayDimFetch $arrayDimFetch, \PhpParser\Node\Expr\Variable $form) : bool
{
if (!$arrayDimFetch->var instanceof \PhpParser\Node\Expr\PropertyFetch) {
return \false;
}
if (!$arrayDimFetch->var->var instanceof \PhpParser\Node\Expr\Variable) {
return \false;
}
if ($arrayDimFetch->var->var->name !== $form->name) {
return \false;
}
if (!$arrayDimFetch->var->name instanceof \PhpParser\Node\Identifier) {
return \false;
}
if ($arrayDimFetch->var->name->name !== 'onSuccess') {
return \false;
}
return \true;
}
}

View File

@ -0,0 +1,48 @@
<?php
declare (strict_types=1);
namespace Rector\Nette\NodeFinder;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Param;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\Class_;
final class FormOnSuccessCallbackValuesParamFinder
{
public function find(\PhpParser\Node\Stmt\Class_ $class, \PhpParser\Node\Expr $onSuccessCallback) : ?\PhpParser\Node\Param
{
if ($onSuccessCallback instanceof \PhpParser\Node\Expr\Closure) {
return $onSuccessCallback->params[1] ?? null;
}
$methodName = null;
if ($onSuccessCallback instanceof \PhpParser\Node\Expr\Array_) {
/** @var Expr\ArrayItem|null $varPart */
$varPart = $onSuccessCallback->items[0] ?? null;
$methodNamePart = $onSuccessCallback->items[1] ?? null;
if ($varPart === null || $methodNamePart === null) {
return null;
}
if (!$varPart->value instanceof \PhpParser\Node\Expr\Variable) {
return null;
}
if ($varPart->value->name !== 'this') {
return null;
}
if (!$methodNamePart->value instanceof \PhpParser\Node\Scalar\String_) {
return null;
}
$methodName = $methodNamePart->value->value;
}
if ($methodName === null) {
return null;
}
$classMethod = $class->getMethod($methodName);
if ($classMethod === null) {
return null;
}
return $classMethod->params[1] ?? null;
}
}

View File

@ -0,0 +1,49 @@
<?php
declare (strict_types=1);
namespace Rector\Nette\NodeFinder;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Expression;
use PHPStan\Type\ObjectType;
use Rector\NodeTypeResolver\NodeTypeResolver;
/**
* @see \Rector\Nette\Tests\NodeFinder\FormFinder\FormFinderTest
*/
final class FormVariableFinder
{
/**
* @var \Rector\NodeTypeResolver\NodeTypeResolver
*/
private $nodeTypeResolver;
public function __construct(\Rector\NodeTypeResolver\NodeTypeResolver $nodeTypeResolver)
{
$this->nodeTypeResolver = $nodeTypeResolver;
}
public function find(\PhpParser\Node\Stmt\Class_ $class) : ?\PhpParser\Node\Expr\Variable
{
foreach ($class->getMethods() as $method) {
$stmts = $method->stmts ?: [];
foreach ($stmts as $stmt) {
if (!$stmt instanceof \PhpParser\Node\Stmt\Expression) {
continue;
}
if (!$stmt->expr instanceof \PhpParser\Node\Expr\Assign) {
continue;
}
$var = $stmt->expr->var;
$expr = $stmt->expr->expr;
if (!$var instanceof \PhpParser\Node\Expr\Variable) {
continue;
}
if (!$this->nodeTypeResolver->isObjectType($expr, new \PHPStan\Type\ObjectType('Nette\\Forms\\Form'))) {
continue;
}
return $var;
}
}
return null;
}
}

View File

@ -0,0 +1,160 @@
<?php
declare (strict_types=1);
namespace Rector\Nette\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Identifier;
use PhpParser\Node\Stmt\Class_;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\NodeFactory\ClassWithPublicPropertiesFactory;
use Rector\Core\Rector\AbstractRector;
use Rector\FileSystemRector\ValueObject\AddedFileWithContent;
use Rector\Nette\NodeFinder\FormFieldsFinder;
use Rector\Nette\NodeFinder\FormOnSuccessCallbackFinder;
use Rector\Nette\NodeFinder\FormOnSuccessCallbackValuesParamFinder;
use Rector\Nette\NodeFinder\FormVariableFinder;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
use RectorPrefix20210805\Webmozart\Assert\Assert;
/**
* @see https://doc.nette.org/en/3.1/form-presenter#toc-mapping-to-classes
* @see \Rector\Nette\Tests\Rector\Class_\FormDataRector\FormDataRectorTest
*/
final class FormDataRector extends \Rector\Core\Rector\AbstractRector implements \Rector\Core\Contract\Rector\ConfigurableRectorInterface
{
public const FORM_DATA_CLASS_PARENT = 'form_data_class_parent';
public const FORM_DATA_CLASS_TRAITS = 'form_data_class_traits';
/**
* @var string
*/
private $formDataClassParent = 'Nette\\Utils\\ArrayHash';
/**
* @var string[]
*/
private $formDataClassTraits = ['Nette\\SmartObject'];
/**
* @var \Rector\Nette\NodeFinder\FormVariableFinder
*/
private $formVariableFinder;
/**
* @var \Rector\Nette\NodeFinder\FormFieldsFinder
*/
private $formFieldsFinder;
/**
* @var \Rector\Nette\NodeFinder\FormOnSuccessCallbackFinder
*/
private $formOnSuccessCallbackFinder;
/**
* @var \Rector\Nette\NodeFinder\FormOnSuccessCallbackValuesParamFinder
*/
private $formOnSuccessCallbackValuesParamFinder;
/**
* @var \Rector\Core\NodeFactory\ClassWithPublicPropertiesFactory
*/
private $classWithPublicPropertiesFactory;
public function __construct(\Rector\Nette\NodeFinder\FormVariableFinder $formVariableFinder, \Rector\Nette\NodeFinder\FormFieldsFinder $formFieldsFinder, \Rector\Nette\NodeFinder\FormOnSuccessCallbackFinder $formOnSuccessCallbackFinder, \Rector\Nette\NodeFinder\FormOnSuccessCallbackValuesParamFinder $formOnSuccessCallbackValuesParamFinder, \Rector\Core\NodeFactory\ClassWithPublicPropertiesFactory $classWithPublicPropertiesFactory)
{
$this->formVariableFinder = $formVariableFinder;
$this->formFieldsFinder = $formFieldsFinder;
$this->formOnSuccessCallbackFinder = $formOnSuccessCallbackFinder;
$this->formOnSuccessCallbackValuesParamFinder = $formOnSuccessCallbackValuesParamFinder;
$this->classWithPublicPropertiesFactory = $classWithPublicPropertiesFactory;
}
public function getRuleDefinition() : \Symplify\RuleDocGenerator\ValueObject\RuleDefinition
{
return new \Symplify\RuleDocGenerator\ValueObject\RuleDefinition('Create form data class with all fields of Form', [new \Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample(<<<'CODE_SAMPLE'
class MyFormFactory
{
public function create()
{
$form = new Form();
$form->addText('foo', 'Foo');
$form->addText('bar', 'Bar')->setRequired();
$form->onSuccess[] = function (Form $form, ArrayHash $values) {
// do something
}
}
}
CODE_SAMPLE
, <<<'CODE_SAMPLE'
class MyFormFactoryFormData
{
public string $foo;
public string $bar;
}
class MyFormFactory
{
public function create()
{
$form = new Form();
$form->addText('foo', 'Foo');
$form->addText('bar', 'Bar')->setRequired();
$form->onSuccess[] = function (Form $form, MyFormFactoryFormData $values) {
// do something
}
}
}
CODE_SAMPLE
, [self::FORM_DATA_CLASS_PARENT => '', self::FORM_DATA_CLASS_TRAITS => []])]);
}
public function getNodeTypes() : array
{
return [\PhpParser\Node\Stmt\Class_::class];
}
public function configure(array $configuration) : void
{
if (isset($configuration[self::FORM_DATA_CLASS_PARENT])) {
\RectorPrefix20210805\Webmozart\Assert\Assert::string($configuration[self::FORM_DATA_CLASS_PARENT]);
$this->formDataClassParent = $configuration[self::FORM_DATA_CLASS_PARENT];
}
if (isset($configuration[self::FORM_DATA_CLASS_TRAITS])) {
\RectorPrefix20210805\Webmozart\Assert\Assert::isArray($configuration[self::FORM_DATA_CLASS_TRAITS]);
$this->formDataClassTraits = $configuration[self::FORM_DATA_CLASS_TRAITS];
}
}
/**
* @param Class_ $node
*/
public function refactor(\PhpParser\Node $node) : ?\PhpParser\Node
{
if ($node->name === null) {
return null;
}
$shortClassName = $this->nodeNameResolver->getShortName($node);
$fullClassName = $this->getName($node);
$form = $this->formVariableFinder->find($node);
if ($form === null) {
return null;
}
$formFields = $this->formFieldsFinder->find($node, $form);
if ($formFields === []) {
return null;
}
$properties = [];
foreach ($formFields as $formField) {
$properties[$formField->getName()] = ['type' => $formField->getType(), 'nullable' => $formField->getType() === 'int' && $formField->isRequired() === \false];
}
$formDataClassName = $shortClassName . 'FormData';
$fullFormDataClassName = '\\' . $fullClassName . 'FormData';
$formDataClass = $this->classWithPublicPropertiesFactory->createNode($fullFormDataClassName, $properties, $this->formDataClassParent, $this->formDataClassTraits);
$printedClassContent = "<?php\n\n" . $this->betterStandardPrinter->print($formDataClass) . "\n";
$smartFileInfo = $this->file->getSmartFileInfo();
$targetFilePath = $smartFileInfo->getRealPathDirectory() . '/' . $formDataClassName . '.php';
$addedFileWithContent = new \Rector\FileSystemRector\ValueObject\AddedFileWithContent($targetFilePath, $printedClassContent);
$this->removedAndAddedFilesCollector->addAddedFile($addedFileWithContent);
$onSuccessCallback = $this->formOnSuccessCallbackFinder->find($node, $form);
if ($onSuccessCallback === null) {
return null;
}
$valuesParam = $this->formOnSuccessCallbackValuesParamFinder->find($node, $onSuccessCallback);
if ($valuesParam === null) {
return null;
}
$valuesParam->type = new \PhpParser\Node\Identifier($fullFormDataClassName);
return $node;
}
}

View File

@ -0,0 +1,165 @@
<?php
declare (strict_types=1);
namespace Rector\Nette\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use PHPStan\Type\ObjectType;
use PHPStan\Type\VerbosityLevel;
use Rector\Core\Rector\AbstractRector;
use Rector\FileSystemRector\ValueObject\AddedFileWithContent;
use Rector\Nette\ValueObject\LatteVariableType;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
/**
* @see \Rector\Nette\Tests\Rector\Class_\LatteVarTypesBasedOnPresenterTemplateParametersRector\LatteVarTypesBasedOnPresenterTemplateParametersRectorTest
*/
final class LatteVarTypesBasedOnPresenterTemplateParametersRector extends \Rector\Core\Rector\AbstractRector
{
public function getRuleDefinition() : \Symplify\RuleDocGenerator\ValueObject\RuleDefinition
{
return new \Symplify\RuleDocGenerator\ValueObject\RuleDefinition('Adds latte {varType}s based on presenter $this->template parameters', [new \Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample(<<<'CODE_SAMPLE'
// presenters/SomePresenter.php
<?php
use Nette\Application\UI\Presenter;
class SomePresenter extends Presenter
{
public function renderDefault(): void
{
$this->template->title = 'My title';
$this->template->count = 123;
}
}
// templates/Some/default.latte
<h1>{$title}</h1>
<span class="count">{$count}</span>
CODE_SAMPLE
, <<<'CODE_SAMPLE'
// presenters/SomePresenter.php
<?php
use Nette\Application\UI\Presenter;
class SomePresenter extends Presenter
{
public function renderDefault(): void
{
$this->template->title = 'My title';
$this->template->count = 123;
}
}
// templates/Some/default.latte
{varType string $title}
{varType int $count}
<h1>{$title}</h1>
<span class="count">{$count}</span>
CODE_SAMPLE
)]);
}
public function getNodeTypes() : array
{
return [\PhpParser\Node\Stmt\Class_::class];
}
/**
* @param Class_ $node
*/
public function refactor(\PhpParser\Node $node)
{
if (!$this->nodeTypeResolver->isObjectType($node, new \PHPStan\Type\ObjectType('Nette\\Application\\UI\\Presenter'))) {
return null;
}
if ($node->name === null) {
return null;
}
$shortClassName = $this->nodeNameResolver->getShortName($node);
$presenterName = \str_replace('Presenter', '', $shortClassName);
$actionVarTypes = [];
foreach ($node->getMethods() as $method) {
$fullActionName = $method->name->name;
if (!(\strncmp($fullActionName, 'action', \strlen('action')) === 0 || \strncmp($fullActionName, 'render', \strlen('render')) === 0)) {
continue;
}
$actionName = \str_replace(['action', 'render'], '', $fullActionName);
$actionName = \lcfirst($actionName);
if (!isset($actionVarTypes[$actionName])) {
$actionVarTypes[$actionName] = [];
}
$actionVarTypes[$actionName] = \array_merge($actionVarTypes[$actionName], $this->findVarTypesForAction($method));
}
$this->printVarTypesToTemplateFiles($actionVarTypes, $presenterName);
return null;
}
/**
* @return LatteVariableType[]
*/
private function findVarTypesForAction(\PhpParser\Node\Stmt\ClassMethod $method) : array
{
$varTypes = [];
$stmts = $method->stmts ?: [];
foreach ($stmts as $stmt) {
if (!$stmt instanceof \PhpParser\Node\Stmt\Expression) {
continue;
}
if (!$stmt->expr instanceof \PhpParser\Node\Expr\Assign) {
continue;
}
if (!$stmt->expr->var instanceof \PhpParser\Node\Expr\PropertyFetch) {
continue;
}
/** @var PropertyFetch $propertyFetch */
$propertyFetch = $stmt->expr->var;
if (!$this->isName($propertyFetch->var, 'template')) {
continue;
}
$staticType = $this->getStaticType($stmt->expr->expr);
$varTypes[] = new \Rector\Nette\ValueObject\LatteVariableType((string) $this->getName($propertyFetch->name), $staticType->describe(\PHPStan\Type\VerbosityLevel::typeOnly()));
}
return $varTypes;
}
/**
* @param array<string, LatteVariableType[]> $actionVarTypes
*/
private function printVarTypesToTemplateFiles(array $actionVarTypes, string $presenterName) : void
{
foreach ($actionVarTypes as $actionName => $varTypes) {
if ($varTypes === []) {
continue;
}
$templateFilePath = $this->findTemplateFilePath($presenterName, $actionName);
if ($templateFilePath === null) {
continue;
}
$content = \file_get_contents($templateFilePath);
$varTypeContentParts = [];
foreach ($varTypes as $varType) {
$varTypeContentParts[] = '{varType ' . $varType->getType() . ' $' . $varType->getName() . '}';
}
$content = \implode("\n", $varTypeContentParts) . "\n\n" . $content;
$addedFileWithContent = new \Rector\FileSystemRector\ValueObject\AddedFileWithContent($templateFilePath, $content);
$this->removedAndAddedFilesCollector->addAddedFile($addedFileWithContent);
}
}
private function findTemplateFilePath(string $presenterName, string $actionName) : ?string
{
$smartFileInfo = $this->file->getSmartFileInfo();
$dir = $smartFileInfo->getRealPathDirectory();
$dir = \is_dir("{$dir}/templates") ? $dir : \dirname($dir);
$templateFileCandidates = ["{$dir}/templates/{$presenterName}/{$actionName}.latte", "{$dir}/templates/{$presenterName}.{$actionName}.latte"];
foreach ($templateFileCandidates as $templateFileCandidate) {
if (\file_exists($templateFileCandidate)) {
return $templateFileCandidate;
}
}
return null;
}
}

View File

@ -102,7 +102,6 @@ CODE_SAMPLE
return $new;
}
$arrayDimFetch = new \PhpParser\Node\Expr\ArrayDimFetch($methodCall->var, $key);
$new = $this->createDateTimeControlNew($methodCall);
$formAssign = new \PhpParser\Node\Expr\Assign($arrayDimFetch, $new);
if ($parent !== null) {
$methodCalls = $this->betterNodeFinder->findInstanceOf($parent, \PhpParser\Node\Expr\MethodCall::class);

View File

@ -89,10 +89,10 @@ CODE_SAMPLE
if (!$phpDocInfo->hasByName('inject')) {
return null;
}
if ($this->netteInjectPropertyAnalyzer->canBeRefactored($node, $phpDocInfo)) {
return $this->refactorNetteInjectProperty($phpDocInfo, $node);
if (!$this->netteInjectPropertyAnalyzer->canBeRefactored($node, $phpDocInfo)) {
return null;
}
return null;
return $this->refactorNetteInjectProperty($phpDocInfo, $node);
}
private function refactorNetteInjectProperty(\Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo $phpDocInfo, \PhpParser\Node\Stmt\Property $property) : ?\PhpParser\Node\Stmt\Property
{

View File

@ -0,0 +1,38 @@
<?php
declare (strict_types=1);
namespace Rector\Nette\ValueObject;
final class FormField
{
/**
* @var string
*/
private $name;
/**
* @var string
*/
private $type;
/**
* @var bool
*/
private $isRequired;
public function __construct(string $name, string $type, bool $isRequired)
{
$this->name = $name;
$this->type = $type;
$this->isRequired = $isRequired;
}
public function getName() : string
{
return $this->name;
}
public function getType() : string
{
return $this->type;
}
public function isRequired() : bool
{
return $this->isRequired;
}
}

View File

@ -9,8 +9,8 @@ $loader = require_once __DIR__.'/autoload.php';
if (!class_exists('AutoloadIncluder', false) && !interface_exists('AutoloadIncluder', false) && !trait_exists('AutoloadIncluder', false)) {
spl_autoload_call('RectorPrefix20210805\AutoloadIncluder');
}
if (!class_exists('ComposerAutoloaderInit533369b6f1bebfefbae9ed468dbeb83c', false) && !interface_exists('ComposerAutoloaderInit533369b6f1bebfefbae9ed468dbeb83c', false) && !trait_exists('ComposerAutoloaderInit533369b6f1bebfefbae9ed468dbeb83c', false)) {
spl_autoload_call('RectorPrefix20210805\ComposerAutoloaderInit533369b6f1bebfefbae9ed468dbeb83c');
if (!class_exists('ComposerAutoloaderInitdf25b088fcc52cbfc899699d2cfd389e', false) && !interface_exists('ComposerAutoloaderInitdf25b088fcc52cbfc899699d2cfd389e', false) && !trait_exists('ComposerAutoloaderInitdf25b088fcc52cbfc899699d2cfd389e', false)) {
spl_autoload_call('RectorPrefix20210805\ComposerAutoloaderInitdf25b088fcc52cbfc899699d2cfd389e');
}
if (!class_exists('AjaxLogin', false) && !interface_exists('AjaxLogin', false) && !trait_exists('AjaxLogin', false)) {
spl_autoload_call('RectorPrefix20210805\AjaxLogin');
@ -3305,9 +3305,9 @@ if (!function_exists('print_node')) {
return \RectorPrefix20210805\print_node(...func_get_args());
}
}
if (!function_exists('composerRequire533369b6f1bebfefbae9ed468dbeb83c')) {
function composerRequire533369b6f1bebfefbae9ed468dbeb83c() {
return \RectorPrefix20210805\composerRequire533369b6f1bebfefbae9ed468dbeb83c(...func_get_args());
if (!function_exists('composerRequiredf25b088fcc52cbfc899699d2cfd389e')) {
function composerRequiredf25b088fcc52cbfc899699d2cfd389e() {
return \RectorPrefix20210805\composerRequiredf25b088fcc52cbfc899699d2cfd389e(...func_get_args());
}
}
if (!function_exists('parseArgs')) {